I have currently a simple angular application configured with yeoman, and the only customisation I'm trying is with grunt-connect-proxy. So I followed the instructions and modified my Gruntfile :
var proxySnippet = require('grunt-connect-proxy/lib/utils').proxyRequest;
module.exports = function (grunt) {
...
grunt.initConfig({
...
connect: {
...
server: {
proxies: [
{
context: '/api',
host: 'somevirtualhost',
port: 8080,
https: false,
changeOrigin: true
}
]
},
livereload: {
options: {
open: true,
middleware: function (connect) {
return [
proxySnippet,
...
];
}
}
},
...
},
});
...
grunt.registerTask('serve', 'Compile then start a connect web server', function (target) {
...
grunt.task.run([
...
'configureProxies:server',
...
]);
});
}
And in a controller I tried the following :
var Versions = $resource('/api/version/:versId', { versId: '#id' });
var version = Versions.get({ versId: 'Ultra' }, function () {
console.log('here I am');
});
When I run grunt serve I can see the proxy is created :
Running "configureProxies:server" (configureProxies) task
Proxy created for: /api to somevirtualhost:8080
But in the console of the web page I get :
Failed to load resource: the server responded with a status of 404 (Not Found)
http://localhost:9000/api/version/Ultra
Any idea ?
I found some clues here : https://github.com/drewzboto/grunt-connect-proxy/issues/69
I don't understand everything but for now I add the headers option in my proxies :
proxies: [
{
context: '/api',
host: 'somevirtualhost',
port: 8080,
https: false,
changeOrigin: true,
headers: {
'host': 'somevirtualhost'
},
}
]
And it seems to work
Related
I have a web application with front end based on angular and back end as a spring rest API. I'm using grunt connect to serve the front end while the rest api runs on localhst:8080, the grunt server runs on localhost:9002.
So from angular, when I'm sending an http call to the back end server using angular-resource, I'm getting following error :
Failed to load localhost:8080/api/v1/user: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https
angular.js:14800 Possibly unhandled rejection: {"data":null,"status":-1,"config":{"method":"POST","transformRequest":[null],"transformResponse":[null],"jsonpCallbackParam":"callback","url":"localhost:8080/api/v1/user","data":{"user":{"email":"a","password":"a"}},"headers":{"Accept":"application/json, text/plain, */*","Content-Type":"application/json;charset=utf-8"}},"statusText":"","xhrStatus":"error","resource":{"user":"..."}}
JS File :
angular.module('userModule').factory('userService',function($resource){
var dataResource = $resource('user',{},
{
saveUser :{
method: 'POST',
url:'localhost:8080/api/v1/user',
params : '#user'
},
});
return dataResource;
});
Gruntfile
'use strict';
module.exports = function (grunt) {
var proxySnippet = require('grunt-connect-proxy/lib/utils').proxyRequest;
// Load grunt tasks automatically
require('load-grunt-tasks')(grunt);
// Time how long tasks take. Can help when optimizing build times
require('time-grunt')(grunt);
var serveStatic = require('serve-static');
// Define the configuration for all the tasks
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
clean: ["dist"],
htmlmin: { // Task
dist: { // Target
options: { // Target options
removeComments: true,
collapseWhitespace: true
},
files: { // Dictionary of files
'dist/index.html': 'dist/index.html' // 'destination': 'source'
}
}
},
copy: {
main: {
expand: true,
cwd: '.',
src: ['**', /* '!js/**', '!lib/**', */ '!**/*.css', '!node_modules/**', '!Gruntfile.js', '!package.json', '!package-lock.json'],
dest: 'dist/'
},
fonts: {
expand: true,
cwd: 'lib/fonts',
src: ['**'],
dest: 'dist/fonts'
}
},
rev: {
files: {
src: ['dist/**/*.{js,css}', '!dist/lib/**/*.{js,css}', '!dist/js/services/**/*.{js,css}']
}
},
useminPrepare: {
html: 'index.html'
},
usemin: {
html: ['dist/index.html']
},
uglify: {
options: {
report: 'min',
mangle: false
}
},
// Watches files for changes and runs tasks based on the changed files
watch: {
js: {
files: ['js/*.js'],
options: {
livereload: '<%= connect.options.livereload %>'
}
},
styles: {
files: ['css/*.css']
},
gruntfile: {
files: ['Gruntfile.js']
},
livereload: {
options: {
livereload: '<%= connect.options.livereload %>'
},
files: [
'*.html',
'css/*.css',
'images/*.{png,jpg,jpeg,gif,webp,svg}'
]
}
},
// The actual grunt server settings
connect: {
options: {
port: 9002,
// Change this to '0.0.0.0' to access the server from outside.
hostname: '0.0.0.0',
livereload: 35730,
base: '.',
middleware: function (connect, options, middlewares) {
middlewares.unshift(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', '*');
return next();
});
return middlewares;
}
},
proxies: [
{
context: '/api/v1',
host: 'localhost',
port: 8080,
changeOrigin: true
}
],
livereload: {
options: {
open: false,
middleware: function (connect) {
return [
proxySnippet,
serveStatic('.')
];
}
}
}
},
});
grunt.registerTask('serve', 'Compile then start a connect web server', function (target) {
grunt.task.run([
'configureProxies',
'connect:livereload',
'watch'
]);
});
grunt.registerTask('default', [
'clean', 'copy', 'useminPrepare', 'concat', 'uglify', 'cssmin', 'rev', 'usemin', 'htmlmin'
]);
};
Can some one tell me is it possible to send http calls with grunt connect?
You are running into CORS issue, This happens when you are making request to a different domain or schema http https or different port (your case falls in this). There are two options.
Allow CORS on your backend server (spring backed server in your case).
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
// by default uses a Bean by the name of corsConfigurationSource
.cors().and()
...
}
#Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("http://localhost:8080"));
configuration.setAllowedMethods(Arrays.asList("GET","POST"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
Further information can be found here.
Configure Front end and backend in same full fledged HTTP server like apache, nginx and setup the request handling as below.
a. Serve all static/angular resources on default path. (localhost/)
b. Send all your backend request to localhost/api/ and proxy it to your backend localhost:8080/api application.
Nginx example:
server {
listen 80;
# The host name to respond to
server_name localhost;
location /api/ {
# Backend nodejs server
proxy_pass http://localhost:8080/api;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
location / {
root /angular directory path/;
}
}
My app uses a Python backend so when I'm running locally I need to proxy my requests to a different port than what Webpack is running on.
I've tried several different ways of making this work:
devServer: {
contentBase: outDir,
proxy: [
{
path: "**",
target: "http://localhost:8000",
secure: false,
bypass: function(req, res, options) {
if(req.url === '' || req.url === '/') {
res.statusCode = 302;
res.setHeader('Location', '/a/');
return '/a/';
}
var frontend = new RegExp("^\/$^|\/a\/index\.html|^\/a\/|^\/a$|^\/styleguide");
if (frontend.test(req.url)) return req.url;
}
}
],
// serve index.html for all 404 (required for push-state)
historyApiFallback: true,
},
And this:
proxy: [{
context: '/',
target: 'http://localhost:8000',
}],
Both of those will at least show a message similar to this when it starts up: [HPM] Proxy created: ** -> http://localhost:8000. When I look at the docs and do something like this, it doesn't work either (I don't even get a message about the proxy running):
proxy: {
"/": "http://localhost:8000"
}
Is there something obvious I'm doing wrong? I'be been trying every combination that I can think of to make it work.
Try to add changeOrigin: true. Don't forget to change API pattern.
proxy: {
'/api/**': {
target: 'http://localhost:8000',
secure: false,
changeOrigin: true
},
}
I'm using grunt-connect-proxy "^0.2.0" to proxy to an api from my angularjs application. The project was started with yeoman angular-generator.
I've followed the instructions here but when the proxy is used, I get:
Failed to load resource: the server responded with a status of 404 (Not Found)
http://localhost:9000/api/users
My Proxy Configuration:
connect: {
options: {
port: 9000,
// Change this to '0.0.0.0' to access the server from outside.
hostname: 'localhost',
livereload: 35729
},
proxies: [{
context: '/api', // the context of the data service
host: 'localhost', // wherever the data service is running
port: 8080, // the port that the data service is running on
https: false,
xforward: false
}],
My Middleware:
livereload: {
options: {
open: true,
base: '',
middleware: function (connect, options) {
var middlewares = [];
middlewares.push(require('grunt-connect-proxy/lib/utils').proxyRequest);
middlewares.push(connect.static('.tmp'));
middlewares.push(connect.static('test'));
middlewares.push(connect().use(
'/bower_components',
connect.static('./bower_components')
));
middlewares.push(connect.static(appConfig.app));
return middlewares;
}
}
},
My Serve Task
grunt.registerTask('serve', 'Compile then start a connect web server', function (target) {
if (target === 'dist') {
return grunt.task.run(['build', 'connect:dist:keepalive']);
}
grunt.task.run([
'clean:server',
'wiredep',
'concurrent:server',
'autoprefixer:server',
'configureProxies:server',
'connect:livereload',
'watch'
]);
});
EDIT
localhost:8080/users returns a 403 currently via Postman, so the API is running.
not directly answering your question but providing a solution (since noone else has answered) ... have you tried the npm module connect-modrewrite
this does exactly what you are trying to do.
I was having the same issue i resolve this way and its work for me. Look into my code below:-
connect: {
server: {
options: {
keepalive: true,
port: 8001,
protocol: 'http',
hostname: '*',
directory: 'dist',
open: {
target: 'http://localhost:8001/myDemo.html',
},
middleware: function(connect, options, middlewares) {
middlewares.unshift(function(req, res, next) {
res.setHeader('Access-Control-Allow-Credentials', true);
res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.setHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
**if (req.method.toUpperCase() == 'POST') req.method='GET';**
return next();
});
return middlewares;
}
}
}
},
see the star marked line ie if (req.method.toUpperCase() == 'POST') req.method='GET'; i done this trick and its worked for me. This aricle also helps to me https://github.com/gruntjs/grunt-contrib-connect#middleware
I have this config:
connect: {
develop: {
options: {
livereload: 35729,
hostname: '*',
port: 8000,
open: {
target: 'http://localhost:<%= connect.develop.options.port %>/src',
appName: 'Google Chrome'
},
}
}
},
I start it and then 'watch' grunt connect:develop watch, but nothing gets 'reloaded'.
It looks like grunt-connect is properly injecting script into HTML cause i Have:
<script src="//localhost:35729/livereload.js?snipver=1"></script>
But
I get error in browser:
GET http://localhost:35729/livereload.js?snipver=1 net::ERR_CONNECTION_REFUSED
I am working with a yeoman generator-angular app and a remote API, my gruntfile config seems to be fine:
// Generated on 2015-06-01 using generator-angular 0.11.1
'use strict';
module.exports = function (grunt) {
/ * Removed for brevity */
grunt.initConfig({
yeoman: appConfig,
watch: {
/ * Removed for brevity */
},
connect: {
options: {
port: 9000,
hostname: 'localhost',
livereload: 35729
},
proxies: [
{
context: '/api',
host: 'subdomain.hostname.com',
xforward: true,
secure: false,
headers: {
'Authorization': 'RemovedToken'
},
}
],
livereload: {
options: {
open: true,
middleware: function (connect, options) {
var middlewares = [require('grunt-connect-proxy/lib/utils').proxyRequest];
middlewares.push(
connect.static('.tmp'),
connect().use('/bower_components',connect.static('./bower_components')),
connect().use('/app/styles', connect.static('./app/styles')),
connect().use(connect.static(appConfig.app))
);
return middlewares;
}
}
},
/ * Removed for brevity */
},
/ * Removed for brevity */
});
grunt.registerTask('serve', 'Compile then start a connect web server', function (target) {
if (target === 'dist') {
return grunt.task.run(['build', 'connect:dist:keepalive']);
}
grunt.task.run([
'clean:server',
'wiredep',
'concurrent:server',
'autoprefixer:server',
'configureProxies:server',
'connect:livereload',
'watch'
]);
});
grunt.loadNpmTasks('grunt-connect-proxy');
};
grunt serve --verbose returns this when a request is made:
Proxied request: /api/foo/bar/?baz=6 -> http://subdomain.hostname.com:80/api/foo/bar/?baz=6
{
"host": "localhost:9000",
"connection": "keep-alive",
"accept": "application/json, text/plain, */*",
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36",
"referer": "http://localhost:9000/",
"accept-encoding": "gzip, deflate, sdch",
"accept-language": "en-US,en;q=0.8,es;q=0.6",
"cookie": "connect.sid=s%3AQpOp8pdI8GM2g8s0qCX602-ds-Xs-5le.C%2BrosIxHQ4ZcLLPgZKhABjji18kqK2K73C7mjF6scqM",
"Authorization": "RemovedToken",
"x-forwarded-for": "127.0.0.1",
"x-forwarded-port": "9000",
"x-forwarded-proto": "http"
}
I can't find any error there, maybe that the "host" is still localhost:9000, but I'm unsure if that could be a problem and in Chrome I am getting: 503 Service Unavailable, but there is indeed a service running, I know because I tested it with Postman and everything works fine, could somebody help me with this? Maybe I am missing something in the configuration?
Thanks.
After digging some more in the project I found that I had to specify the "host" header too.
https://github.com/drewzboto/grunt-connect-proxy/issues/72