So I'm using a yeoman project from swiip called generator-gulp-angular - just do "npm search gulp-angular" and you'll see it.
Out of the box the client is running from 127.0.0.1:3000 and I wish to make a $http call to a (python) service on 127.0.0.1:8080. Its using browser-sync for live reload and proxy middleware to make the proxy calls from client to server. Proxy middleware is per default disabled, so the trick is to enable it and successfully make requests to and receive responses from server. So far i've not been able to successfully enable it :-(
Update: I recreated the yeoman project following the motto "give yourself a simple example" in order to concentrate on the Access-Control issue and I got it to work more or less out of the box without having to resort to modifying the server logic in order to allow cross origin requests. Pleasingly it's as simple as the instructions describe. Here's the proxy file that extends the gulp middleware to perform the proxy, or rather mapping from client to server:
/*jshint unused:false */
/***************
This file proxy.js allows you to configure a proxy system plugged into BrowserSync
in order to redirect backend requests while still serving and watching
files from the web project
IMPORTANT: The proxy is disabled by default.
If you want to enable it, watch at the configuration options and finally
change the `module.exports` at the end of the file
***************/
'use strict';
var proxyMiddleware = require('http-proxy-middleware');
var options = {
target: 'http://127.0.0.1:8080'
};
var proxy = proxyMiddleware('/quote', options);
module.exports = function(){
return [proxy];
}
From the gulpfile (gulpfile.js) we have:
'use strict';
var gulp = require('gulp');
var browserSync = require('browser-sync');
var browserSyncSpa = require('browser-sync-spa');
var util = require('util');
var middleware = require('./proxy');
module.exports = function(options) {
function browserSyncInit(baseDir, browser) {
browser = browser === undefined ? 'default' : browser;
var routes = null;
if(baseDir === options.src || (util.isArray(baseDir) && baseDir.indexOf(options.src) !== -1)) {
routes = {
'/bower_components': 'bower_components'
};
}
var server = {
baseDir: baseDir,
routes: routes
};
//
// Here's the relevant bit
//
server.middleware = middleware();
browserSync.instance = browserSync.init({
startPath: '/',
server: server,
browser: browser
});
}
browserSync.use(browserSyncSpa({
selector: '[ng-app]'// Only needed for angular apps
}));
gulp.task('serve', ['watch'], function () {
browserSyncInit([options.tmp + '/serve', options.src]);
});
..
gulp.task('serve:e2e-dist', ['build'], function () {
browserSyncInit(options.dist, []);
});
};
As you see we're configuring gulp to be aware of the "/quote" context that when used on the client (http://localhost:3000/quote) will get mapped to the backend (http://localhost:8080/quote) - for further information: https://github.com/chimurai/http-proxy-middleware/blob/v0.0.5/README.md
Here's where we make the call on the client using the $http service:
function quotePriceGenerator($q, $http) {
var lowPrice = 1.45000, highPrice = 1.47000;
var askPrice, sellPrice;
var service = {};
service.getPrice = function() {
var deferred = $q.defer();
$http({
url: '/quote',
method: 'GET'
})
.then(function(quote) {
var date = new Date();
const quoteZoom = 100000;
const quotePipsWindow = -3;
..
qBox['trading-size-string'] = qBox['trading-size'].toString();
service.qBox = qBox;
return deferred.resolve(service);
});
// Returns a random integer between min (included) and max (included)
// Using Math.round() will give you a non-uniform distribution!
function getRandomIntInclusive(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
return deferred.promise;
};
return service;
..
function randomizeAskSell(low, high){
}
}
quotePriceGenerator.$inject = ['$q', '$http'];
export default quotePriceGenerator;
The backend, a python tornado REST API, didn't require any configuration for Access-Control-Allow-Origin. Here it is:
from __future__ import division
import tornado.ioloop
import pyrestful.rest
import random
from pyrestful import mediatypes
from pyrestful.rest import get
class Quote(object):
quote_date_time = float
..
sell_price = float
trading_size = int
class QuoteResource(pyrestful.rest.RestHandler):
@get(_path="/quote", _produces=mediatypes.APPLICATION_JSON)
def getQuoteJson(self):
price_min = random.randint(145000,146000)/100000
price_max = random.randint(146000,147000)/100000
..
quote.sell_price = sell_price
quote.trading_size = trading_size
return quote
if __name__ == "__main__":
try:
print("Start the service")
app = pyrestful.rest.RestService([QuoteResource])
app.listen(8080)
tornado.ioloop.IOLoop.instance().start()
except KeyboardInterrupt:
print("\nStop the service")
You have to setup a proxy server to forward your requests, setup a reverse proxy, or setup CORS on the back-end to allow the cross-origin request.
Some information on the erroneous request/response would be helpful too.
You could try to set the
changeOrigin
param to true. This will modify the request's host header to match the server's hostname.If that doesn't work; you can add the
Access-Control-Allow-Origin
header to the response:http-proxy-middleware
onProxyRes
option is added in v0.5.0 , so make sure to update it if you're still using v0.0.5