node.js and geoserver CORS
Asked Answered
K

2

14

I have node.js server 0.10.12 and express.js 4.8.5. Node.js is the web server, includes openlayers 3.9.0.

Geoserver 2.1.3 serves the WMS layer. Later, I will implement vector layers.

There is only one route (for the index page)

var routes = require('./routes/index');

The index.js contains

var express = require('express');
var router = express.Router();

router.get('/', function(req, res, next) {
  res.render('index', { title: 'openlayers3 testing', head: 'Welcome' });
  next();
});

module.exports = router;

So the app.js has

var routes = require('./routes/index');//explained above

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

I added the following for CORS

app.use(function (req, res, next) {
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
    res.setHeader('Access-Control-Allow-Credentials', true);
    next();
});


app.get('/', routes);

And in the index.ejs I set my Geoserver WMS layer like this

var ait = new ol.layer.Tile({
extent: textent,
source: new ol.source.TileWMS({
  url: 'http://localhost:8080/geoserver/mymap/wms',
  crossOrigin: 'anonymous',
  attributions: [new ol.Attribution({
    html: '&copy; ' +'<a href="http://www.geo.admin.ch/internet/geoportal/' +'en/home.html">' +'National parks / geo.admin.ch</a>'
  })],
   params: {'LAYERS': 'mymap:planet_osm_polygon, mymap:planet_osm_line, mymap:planet_osm_roads, mymap:planet_osm_point'},
   serverType: 'geoserver'
 })

})

And I get the error

Image from origin 'http://localhost:8080' has been blocked from loading by Cross-Origin Resource Sharing policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:5550' is therefore not allowed access.

I tried a lot of variations I found online. I put the code before the app.use(express.static(path.join(__dirname, 'public')));. I put it inside the router.get of the index.js. Still nothing. I fail to understand what is wrong.

Thanks

notes

This works in internet explorer 11. No errors and I can actually see the layer

No errors in firefox 30 but I cannot see the layer

In chrome 45 I cannot see the layer and I get that error

Kareem answered 28/9, 2015 at 13:6 Comment(9)
Did you see - https://mcmap.net/q/474006/-cors-tomcat-geoserver?Quietism
@Kareem you are adding CORS on wrong side. You are connecting from node app to your Geoserver. So, CORS should be added in your Geoserver, not on Node app.Cantonment
@JonatasWalker Yes, thanks, I plan to re-set my Geoserver according to thisKareem
@ɦassansin Hi there. I come to realise this, you are right. I now read articles on CORS. But, for conversation sake, lets assume that I can only access and set node.js and not Geoserver. What do I do then? Set a proxy to node.js? ThanksKareem
yes, reverse proxy would be one solution in that case.Cantonment
@ɦassansin Hi there again. Setting CORS to Geoserver is not possible due to technical problems. I want to set a peverse proxy on node, but I dont know how to do it. There are many npm modules out there and I dont know witch one fits. Any tips? Thanks againKareem
you can try github.com/chimurai/http-proxy-middlewareCantonment
@JonatasWalker This is a good SO Q&A , but this uses Tomcat and my Geoserver uses and old Jetty. A similar solution is this http://comments.gmane.org/gmane.comp.gis.geoserver.user/42219 but did not work for me and I dont trust it because I dont know if its official. Thanks anyhowKareem
@ɦassansin Hey.http-proxy-middleware looks amazing and I did not see it, so I will experiment. I now try to create a reverse proxy with it, but I dont actually know what to do. If you dont mind checking this http://stackoverflow.com/questions/32952476/cannot-set-proxy-on-node-js. Thanks againKareem
R
7

Forget 'Access-Control-Allow-Origin', '*' it is a huge security risk. Set the name of the requesting domain instead and maintain a whitelist of domains.

I think it is obvious that your middleware does not set the headers in the http://localhost:8080 response. Check the headers on the network panel, firebug, etc... and debug it. How to debug the http response headers from a HTTP call

Firefox does not handle CORS errors always properly, so you should check chrome as well. Internet explorer works differently from the others: https://mcmap.net/q/410986/-internet-explorer-11-does-not-add-the-origin-header-on-a-cors-request so it accepts http://localhost:5550 as same origin, that's why your buggy code works in msie. Try to use custom named domains by appending the hosts file, and I am sure you will get error message from msie as well.

edit - to catch up with the comments

The main problem with the example code, that the webapp (domain: http://localhost:5550) returns your CORS headers. Since the webapp wants to access the geoserver (http://localhost:8080) from the browser, the geoserver should grant access and not the webapp. So the geoserver should return the CORS headers instead of the webapp.

According to slevin it is not possible with the version of geoserver they currently use. A possible workaround to add a reverse proxy and serve the geoserver under a subfolder of the webapp or serve the webapp under a subfolder of the geoserver. This way they both would have the same origin. Another option to stick with different domains, but add the CORS headers to the geoserver response using the reverse proxy.

Reedbuck answered 29/9, 2015 at 2:4 Comment(7)
Chrome console gives a 200 status for the maps from localhost:8080, but no size. And the CORS error. Firebug also gives a 200 status , there is a size, but no errors. I dont get what you mean by "I think it is obvious that your middleware does not set the headers in the localhost:8080 response. Check the headers on the network panel, firebug, etc... and debug it.". If you want to update your answer and explain to me, that would be great, because frankly I am stack.Kareem
I also red http://jonathanmh.com/how-to-enable-cors-in-express-js-node-js/ and http://www.tamas.io/node-jsexpress-cors-implementation/, and tryed to implement, but no luck. ThaknsKareem
@Kareem According to your error message the access control headers do not show up in the response and that causes the problem. I added a link about how to check the response headers in firefox with firebug, but you can do that with any current browser using the dev tools.Reedbuck
@Kareem In my opinion the problem that you are adding the access control headers to the localhost:5550 response and not to the localhost:8080 response. I don't think you fully understand how CORS works. You should read the manual. w3.org/TR/corsReedbuck
Setting CORS on Geoserver (localhost:8080) not possible due to technical problems, and all the hacks I saw and tryed to implement failed. If I set a proxy or reverse proxy on Node (localhost:5550) will this solve the CORS related problems?Kareem
@Kareem If you mean you serve geoserver from 5550 or you serve your webapp from 8080 through a proxy, then both would work. If you could put the geoserver behind a proxy on a 3rd domain, then you would be able to add the allow origin headers as well. You should ask geoserver developers to implement a CORS header feature in the next version.Reedbuck
Thanks for your time and effort, thanks for making me understand the concept. I now try to set a reverse proxy, but I fail to implement it. If you dont mind checking this http://stackoverflow.com/questions/32952476/cannot-set-proxy-on-node-js would be great. ThanksKareem
C
-2

Try starting google-chrome with disable security and allowing access for local files

google-chrome --disable-web-security --allow-file-access-from-files

This will disable the same origin policy and allow local files to access each other.

You might get Stability and security warning, you can avoid that for development.

Couscous answered 2/10, 2015 at 14:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.