Gruntfile.js with grunt-contrib-connect Proxy error: ECONNRESET - angularjs

I have finally ran into an issue that is beyond my skill and no-one in house is very familiar with the issue at hand either. My issue is I am attempting to get grunt serve/server working on windows 7/8 at work to replace our current nginx configuration for development.
If I have my angularjs front-end and grails back-end both running locally I have no issues doing this but when I want to run my angularjs app through grunt serve locally and have it talk to our deployed back-end at test.domain.net I am getting a Proxy error: ECONNRESET error.
I have tried 3 versions of grunt-contrib-connect (0.1.10, 0.1.11, 0.2.0); 10 and 11 have slightly different errors but 2 is what I would prefer and is what is throwing the ECONNRESET.
What seems exceptionally strange to me is that with --stack --verbose it claims that I am redirecting through the proxy but when I look at the url in chrome it is still using local host.
Current error
> Proxied request: /app/orders?limit=15&offset=0 ->
> https://services-test.app.com:443/orders?limit=15&offset=0
> {
"host": "services-test.app.com", "connection": "keep-alive",
> "cache-control": "max-age=0", "accept": "application/json,
> text/plain, */*", "x-auth-token":
> "3an7h1oupnj6e7shfplf06adn8mr8q26", "if-modified-since": "0",
> "user-agent": "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36
> (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/5
> 37.36", "referer": "http://localhost:9000/", "accept-encoding": "gzip, deflate, sdch", "accept-language": "en-US,en;q=0.8",
> "cookie": "_ga=GA1.1.1146585466.1432141723;
> JSESSIONID=5569C3D1BDC2CA2CBF5B72636A9338F4", "x-forwarded-for":
> "127.0.0.1", "x-forwarded-port": "80", "x-forwarded-proto": "http"
> }
> Proxy error: ECONNRESET
Pertinent part of Gruntfile.js (urls modified for privacy)
// The actual grunt server settings
connect: {
options: {
port: 9000,
// Change this to '0.0.0.0' to access the server from outside.
hostname: 'localhost', //'0.0.0.0',
livereload: 35729
},
proxies: [
{
//context: '/api',
//host: 'localhost',
//port: 8080,
//https: false,
//changeOrigin: false,
//xforward: false
context: '/api',
host: 'services-test.app.com',
https: true,
port: 443,
xforward: true,
headers: {
'host': 'services-test.app.com',
'x-auth-token': '3an7h1oupnj6e7shfplf06adn8mr8q26'
},
rewrite: {
'^/api': ''
}
}
],
livereload: {
options: {
open: true,
base: [
'.tmp',
'<%= yeoman.app %>'
],
middleware: function(connect, options) {
if (!Array.isArray(options.base)) {
options.base = [options.base];
}
// Setup the proxy
var middlewares = [require('grunt-connect-proxy/lib/utils').proxyRequest];
// Serve static files.
options.base.forEach(function(base) {
middlewares.push(connect.static(base));
});
// Make directory browse-able.
var directory = options.directory || options.base[options.base.length - 1];
middlewares.push(connect.directory(directory));
return middlewares;
}
}
},
This stackoverflow here Grunt connect proxy rewrite not works in https is my exact issue but this does not solve my issue. Other related posts
http://www.ngroutes.com/questions/AUuACacna5vEqxqlK1fu/grunt-connect-proxy-proxy-created-but-i-get-a-404.html
this post is why host is included in the headers in my gruntfile.js and why services-test.app.com show in my error at all other than local host.
Lastly I have seen some stuff saying that this might be a CORS issue and while that might be possible the point of grunt-contrib-connect is to not have to make server side changes in my understanding.
Thanks to any who might help me resolve this and sorry it was kind of rambling I've looked through a lot of stuff today.

So there was a bug in the grunt-connect-proxy repository. It was fixed in this commit: https://github.com/drewzboto/grunt-connect-proxy/commit/f798bbd31b76b039a392b8f1bca55b310a7ac5c9
Updating to the latest commit in the repo fixed the problem for me. So you could do that or wait for the new release to come out.
Hope that fixes it for you!

I kept getting the error "Proxy error: ECONNRESET" in my console. This solution to downgrade to version 0.1.10 of grunt-connect-proxy worked. I followed this fettblog.eu tutorial on setting the proxy up.

Related

How remove port number ":80" when serving localhost using grunt-contrib-connect

When I serve my project using grunt-contrib-connect, I need it to run using https, and in the browser the root path needs to be:
https://localhost/
I am not familiar with how to set this up using the proxy option in grunt-contrib-connect.
My grunt.initConfig setup is:
connect: {
server: {
options: {
port: 80,
base: 'dist',
protocol: 'https',
livereload: true,
keepalive: true,
debug: true,
hostname: 'localhost',
open: true
}
}
},
```
This serves the project to https://localhost:80/
I will finish setting up livereload once this is working correctly.
Thanks for your help.
For https without a port number in the address bar, port needs to be set to 443, and for livereload you must have simple, self-generated certificates created - they can reside in the project folder as they are in no way connected with security.
The connect/watch setup in my gruntfile is:
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-contrib-watch');
// Project configuration.
grunt.initConfig({
//live server
connect: {
server: {
options: {
port: 443,
base: 'dist', //the folder my compiled web files are generated in
protocol: 'https',
livereload: true,
debug: true, //show me what is being served, helpful for debugging
hostname: 'localhost',
open: true //auto-open browser tab - remove if annoying
}
}
},
//watch for changes and recompile / reload
watch: {
dev: {
options: {
livereload: {
port: 35729,
key: grunt.file.read('livereload.key'),
cert: grunt.file.read('livereload.crt')
// you can pass in any other options you'd like to the https server, as listed here: http://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener
}
},
files: [ // Files to livereload on
"js/**/*.*",
"less/admin/*.less",
"./*.html",
"./Gruntfile.js",
"snippets/*.*"
],
tasks: [
'dev' //the task to run after a change is detected
]
}
},
.....
This guide helped me create the certificates:
https://www.gilluminate.com/2014/06/10/livereload-ssl-https-grunt-watch/
The :9000 detail did not work for me, I left the livereload port at 35729, and once the server was up and running hit this in a new tab to authorise access to the script using self-generated certificates:
https://localhost:35729/livereload.js?snipver=1
I hope this helps someone ;)

http-proxy-middleware is not working in production but in localhost

I used http-proxy-middle for proxying my api domain in order to bypass CORS issue. My code works in localhost, but when it is not working in my live domain.
My code is:
const proxy = require('http-proxy-middleware');
app.use(
'/api',
proxy({
target: ' mylivedomain.com',
pathRewrite: {
'^/api': '/',
},
changeOrigin: true,
logLevel: 'debug',
secure: false,
}),
);
I checked in the network tab, I got a status code: 302 when trying to GET or POST method. Does anyone have any ideas how to fix it?

Using Protractor with proxypass-based AngularJS app

I'm using Protractor to implement end-to-end tests on my AngularJS app using Grunt, and my app does use proxy pass to handle API calls. As a result, when running tests, API calls fail because http://localhost:9000/api is not handled.
I tried the grunt-connect-proxy plugin to handle /api proxy pass but it simply redirects (HTTP code 301) localhost:9000/api to myserver.com/api, and doesn't mimic the behaviour of a proxy pass (and the app doesn't work either).
Here's the Gruntfile configuration:
connect: {
options: {
port: 9000,
hostname: 'localhost',
base: ['<%= globals.appFolder %>/'],
logger: 'dev',
}
},
protractor: {
options: {
configFile: 'tests/e2e/protractor.config.js',
keepAlive: true,
noColor: false,
args: {}
},
e2e: {
options: {
args: {}
}
}
}
And here's the Protractor configuration file:
exports.config = {
specs: ['./suites/*.js'],
baseUrl: 'http://localhost:9000',
maxSessions: 1,
multiCapabilities: [{
browserName: 'chrome'
}],
};
How would you handle this case to let tests run on both a desktop machine, and a remote machine (such as Jenkins)?
According to this issue related on grunt-connect-proxy, this is a bug occurring when dealing with HTTPS endpoints. Use the master/ version instead.
Package.json:
"grunt-connect-proxy": "https://github.com/drewzboto/grunt-connect-proxy#master",
Gruntfile:
proxies: [{
context: '/api',
host: 'myserver.com',
port: 443,
https: true
}]

Unable to view descriptions of generated docs

although I'm able to serve from filesystem the grunt-ngdocs automatically generated index.html, everytime I try to look to a description in the documentation I'm getting:
XMLHttpRequest cannot load file:///C:/<file-path> Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource
even if both the docs/partials and docs/partials/api folders are empty.
This is my grunt-ngdocs configuration
ngdocs: {
options: {
dest: 'docs',
html5Mode: false,
inlinePartials: true,
scripts: [
'bower_components/angular/angular.js',
'bower_components/angular-animate/angular-animate.js'
]
},
api: {
src: ['app/scripts/**/*.js'],
title: 'Docs'
}
}
What am I doing wrong?
Thank you in advance
Problem is you have to run it from a server. I use a node http server (https://www.npmjs.com/package/http-server). After installing it, just head into the docs/ directory and type 'http-server'. You will get the following message:
Starting up http-server, serving ./ on: http://0.0.0.0:8080
You can now check the docs on the given URL (http://0.0.0.0:8080)
Edit:
If you don't want to load it from a server, you can set the option inlinePartials to true in the gruntfile. This is what I have:
ngdocs: {
options: {
dest: 'docs',
title: "Docs",
inlinePartials: true
},
api: {
src: ['<%= yeoman.app %>/scripts/**/*.js'],
title: 'API Documentation'
}
},
see (https://github.com/m7r/grunt-ngdocs)

webpack dev server CORS issue

I am using webpack-dev-server v1.10.1 to boost up my Redux project and I have the options below:
contentBase: `http://${config.HOST}:${config.PORT}`,
quiet: false,
noInfo: true,
hot: true,
inline: true,
lazy: false,
publicPath: configWebpack.output.publicPath,
headers: {"Access-Control-Allow-Origin": "*"},
stats: {colors: true}
In the JS, I am using request from superagent to generate a HTTP GET call
request
.get(config.APIHost + apiUrl)
.set('Accept', 'application/json')
.withCredentials()
.end(function (err, res) {
if (!err && res.body) {
disptach(() => {
return {
type: actionType || GET_DATA,
payload: {
response: res.body
}
}
});
}
});
But I got the CORS error:
XMLHttpRequest cannot load http://localhost:8000/api/getContentByType?category=all. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:5050' is therefore not allowed access
Any suggestion to resolve this? Thanks a lot
Another way to work around it is to directly add the required CORS headers to the dev server:
devServer: {
...
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
"Access-Control-Allow-Headers": "X-Requested-With, content-type, Authorization"
}
}
Doc links
Webpack dev server
Access-Control-Allow-Headers
Access-Control-Allow-Methods
Access-Control-Allow-Origin
With webpack-dev-server 1.15.X you can use this configuration in your config file:
devServer: {
contentBase: DIST_FOLDER,
port: 8888,
// Send API requests on localhost to API server get around CORS.
proxy: {
'/api': {
target: {
host: "0.0.0.0",
protocol: 'http:',
port: 8080
},
pathRewrite: {
'^/api': ''
}
}
}
},
With this example you will redirect all calls from http://0.0.0.0:8888/api/* to http://0.0.0.0:8080/* and CORS solved
Had the same issue, but my api was on a https protocol (https://api....). Had to start the server with https and use https://localhost:8080
devServer: {
https: true,
headers: {
"Access-Control-Allow-Origin": "*",
},
// ....
}
You're running your JavaScript from localhost:5050 but your API server is localhost:8000. This violates the same origin policy, so the browser disallows it.
You can either modify your API server so that CORS is enabled, or follow the instructions on the webpack-dev-server page under "Combining with an existing server" to combine asset serving with webpack-dev-server and your own API server.
There are 2 solutions for this. first one is setting up proxy on the client side, second one is setting CORS on the server. CORS is server issue, server does not allow access from different source. Even using different ports is considered to be different source
First Solution
IN your backend code, you have to set this headers: this is example of in express node.js
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader(
"Access-Control-Allow-Methods",
"OPTIONS, GET, POST, PUT, PATCH, DELETE"
);
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
next();
});
Second Solution:
in webpack config.js, if you want to pass any variable, we export
module.exports=function(env){
return {}}
instead of
module.exports={}
we inject this env through the script.
"dev-server": "webpack-dev-server --env.api='https://jsonplaceholder.typicode.com/users'",
now webpack has access to this env. in webpack.config.js
module.exports = function ({
api = "https://jsonplaceholder.typicode.com/users",
}) {
return {
entry: { main: "./src/index.js" },
output: {
path: path.resolve(__dirname, "public"),
filename: "[name]-bundle.js",
publicPath: "/",
},
mode: "development",
module: {
rules: [
{
loader: "babel-loader",
test: /\.js$/,
exclude: [/node_modules/],
},
{
// Load other files, images etc
test: /\.(png|j?g|gif|ico)?$/,
use: "url-loader",
},
{
test: /\.s?css$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
],
},
//Some JavaScript bundlers may wrap the application code with eval statements in development.
//If you use Webpack, using the cheap-module-source-map setting in development to avoid this problem
devtool: "cheap-module-eval-source-map",
devServer: {
contentBase: path.join(__dirname, "public"),
historyApiFallback: true,
proxy: {
"/api": {
changeOrigin: true,
cookieDomainRewrite: "localhost",
target: api,
onProxyReq: (proxyReq) => {
if (proxyReq.getHeader("origin")) {
proxyReq.setHeader("origin", api);
}
},
},
},
},
};
};

Resources