1

I have node.js 4.1.1 and express.js 4.8.5 on port 5550. I also have Geoserver 2.8.0 on port 8080. Both servers are on the same laptop.

An app on node wants to access some map data from Geoserver and these are the details on openlayers

 source: new ol.source.TileWMS({
      url: 'http://localhost:8080/geoserver/mymap/wms?',
      crossOrigin: 'anonymous',
// I also tried  crossOrigin: 'localhost:8080/' and crossOrigin: 'localhost:5550/' but nothing

       params: {'LAYERS': 'mymap:layer, mymap:anotherLayer, FORMAT': 'image/png' ,'CRS': 'EPSG:3857'},
       serverType: 'geoserver'

Setting CORS or proxy on Geoserver is not possible cause of technical problems (old Jetty core, hack-ish solutions on the wild, unavailiable jars for old Jetty version). To avoid CORS and Access Control Allow Origins errors I want to set a proxy on Node. I just want to use Node because its easier to set.

According to this and a previous question here I have to set a reverse proxy, so

  • I do not do proxy configs on the client
  • Geoserver gets served via a Node reverse proxy, so looks like they have the same origin (=no more CORS problems)
  • client want to access Geoserver but does that via Node without knowing it

I guess I got the concept right, but I dont know how to implement this. I chose the http-proxy-middleware to do this. I added on my app.js

var proxyMiddleware = require('http-proxy-middleware'); 

    var proxy = proxyMiddleware('http://localhost:8080/geoserver', {
                    target: 'http://localhost:5550',
                    changeOrigin: true   
                });

var app = express();

app.use('/' , function (req, res) {
       res.render('index', { title: 'testing', head: 'Welcome Testing Area'});
    });

app.use(proxy); 
app.listen(5550);

On console I see [HPM] Proxy created: /geoserver -> http://localhost:5550

But I still 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. The response had HTTP status code 404.

I fail to understand how to implement this. Please point out my errors or if I did not get the concept right. Please help me understand.

Thanks

UPDATE

These are the headers I see when I open the browser's console

General
Remote Address:[::1]:8080
Request URL:http://localhost:8080/geoserver/mymap/wms?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&LAYERS=mymap%3Aplanet_osm_polygon%2C%20mymap%3Aplanet_osm_line%2C%20mymap%3Aplanet_osm_roads%2C%20mymap%3Aplanet_osm_point&TILED=true&CRS=EPSG%3A3857&WIDTH=256&HEIGHT=256&STYLES=&BBOX=2269873.9919565953%2C4618019.500877209%2C2348145.508920616%2C4696291.017841229
Request Method:GET
Status Code:404 Not Found

Response Headers
HTTP/1.1 404 Not Found
Content-Type: text/html; charset=iso-8859-1
Content-Length: 1408
Server: Jetty(6.1.8)

Request Headers
Accept:image/webp,image/*,*/*;q=0.8
Accept-Encoding:gzip, deflate, sdch
Accept-Language:el-GR,el;q=0.8,en;q=0.6
Cache-Control:max-age=0
Connection:keep-alive
Host:localhost:8080
Origin:http://localhost:5550
Referer:http://localhost:5550/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36
Community
  • 1
  • 1
slevin
  • 4,166
  • 20
  • 69
  • 129
  • Similar question here: http://gis.stackexchange.com/questions/4323/is-it-possible-to-put-geoserver-behind-a-proxy-and-access-the-wms-wfs-using-open I need some time to try out the reverse proxy with nodejs. – inf3rno Oct 05 '15 at 17:04
  • You should use a different proxy lib: http://stackoverflow.com/questions/22889417/create-a-reverse-proxy-in-nodejs-that-can-handle-multiple-secure-domains they have over 1000 stars, while your lib only around 25 stars... There is some tutorial here about one of the libs: http://blog.ccare.me/blog/2013/09/18/custom-reverse-proxying-with-node-dot-js/ Try it out! – inf3rno Oct 05 '15 at 17:12

2 Answers2

2

Looks like you misconfigured the proxy.

  • mix usage of the normal proxy configuration and the shorthand configuration
  • target should be the Geoserver, instead of your express server.

Normal syntax with Geoserver as target:

var proxy = proxyMiddleware('/geoserver', {
                 target: 'http://localhost:8080',
                 changeOrigin: true   
            });

Or with the shorthand syntax:

This configuration behaves exactly as the previous one.

var proxy = proxyMiddleware('http://localhost:8080/geoserver', {
                 changeOrigin: true   
            });
chimurai
  • 1,285
  • 1
  • 16
  • 18
  • I did what you said, but still nothing. – slevin Oct 05 '15 at 20:50
  • Can you provide the requests made to the server and their response codes? – chimurai Oct 05 '15 at 21:03
  • You mean open the browser's console and copy/paste the `Response Headers` and `Request Headers`? This will give the info you want? – slevin Oct 05 '15 at 21:39
  • See my original question, I added the headers. Thanks again – slevin Oct 05 '15 at 21:52
  • Can you access the image directly without the proxy? And where does this img url originates? Is it from another reponse? – chimurai Oct 05 '15 at 21:57
  • You mean take this link `http://localhost:8080/geoserver/cultumap/wms?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&LAYERS=cultumap%3Aplanet_osm_polygon%2C%20cultumap%3Aplanet_osm_line%2C%20cultumap%3Aplanet_osm_roads%2C%20cultumap%3Aplanet_osm_point&TILED=true&CRS=EPSG%3A3857&WIDTH=256&HEIGHT=256&STYLES=&BBOX=2269873.9919565953%2C4696291.017841229%2C2348145.508920616%2C4774562.534805249` from the header and paste it to a browser and see if it loads the image? No. I get 404. But the Geoserver on 8080 works, I just log in as admin – slevin Oct 05 '15 at 22:00
  • Geoserver creates these images and these URLs. Gets data from PostGIS. I dont know how, I am sorry. In my original question, if I put `app.use(proxy); ` before the `app.use('/' , function (req, res) {...` I can access Geoserver via `5550` and `8080`. – slevin Oct 05 '15 at 22:38
  • But if I go to `http://localhost:5550/` I get `Error 404 - Not Found. No context on this server matched or handled this request. Contexts known to this server are: /javadoc ---> org.mortbay.jetty.servlet.Context@62afe8c5{/javadoc,file:/C:/Program%20Files%20(x86)/GeoServer%202.8.0/javadoc} /geoserver ---> org.mortbay.jetty.webapp.WebAppContext@adb1021{/geoserver,file:/C:/Program%20Files%20(x86)/GeoServer%202.8.0/webapps/geoserver/}` – slevin Oct 05 '15 at 22:38
  • I know that in the question says `mymap` and in the comment above `cultumap`, but is the same thing, I made a typo – slevin Oct 05 '15 at 23:05
  • 1
    @chimurai The geoserver is on 8080 port, the webapp is on 5550 and he wants to proxy the geoserver under a 5550 subfolder. – inf3rno Oct 06 '15 at 08:39
  • 1
    Think I see another configuration mistake. `target` should be the geoserver instead of the express server. ` var proxy = proxyMiddleware('/geoserver', { target: 'http://localhost:8080', changeOrigin: true }); ` – chimurai Oct 06 '15 at 09:20
  • @chimurai Thanks. I see how I messed up. Let me get some rest and I will come back with an answer – slevin Oct 06 '15 at 12:59
  • @chimurai I think you should edit your answer with that. – inf3rno Oct 07 '15 at 10:34
  • I'll update the answer. Only saw the actual issue after your hint @inf3rno :) – chimurai Oct 07 '15 at 13:04
  • @chimurai I am so sorry I made a typo on my link. Now works. Check my answer and thanks for your time and effort. Are you the guy that created `http-proxy-middleware`? One last thing, so I can understand the concept. By using your code I redirect the requests from node to geoserver or I send the data from geoserver through node? – slevin Oct 07 '15 at 22:31
0

chimurai was right. What finally worked for me was setting the http-proxy-middleware

On my app.js I now have

var proxyMiddleware = require('http-proxy-middleware'); 

var proxy = proxyMiddleware('http://localhost:5550', {
                 target: 'http://localhost:8080',
                 changeOrigin: true,
                 xfwd: true
            });

/*
the above can be replaced by chimurai's version : 
var proxy = proxyMiddleware('/geoserver', {
                 target: 'http://localhost:8080',
                 changeOrigin: true   
            });
and will still work
*/

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')));

app.use('/', function(req, res, next) {
    httpProxy.createProxyServer({target:'http://localhost:8080'});
    next();
});

app.use(proxy);

app.listen(5550);

I erased this crossOrigin: 'anonymous', in my Openlayers code and I fixed a typo on the link in the Openlayers and now works fine.

I also tried to fix this via setting a proxy on Geoserver, but this is not possible because Geoserver runs an old Jetty version that is now EOL, so there is no official solution to proxying Geoserver nor upgrading it.

Troubleshooting this via Node is the best solution

slevin
  • 4,166
  • 20
  • 69
  • 129