[GIS] While developing stage, Is Proxy.cgi required to get Openlayers WMSGetFeatureInfo

asp.netgeoserverjavascriptopenlayers-2wms

I have published the data in Geoserver (Tomcat and OS Ubuntu) and I am developing a map application in my local machine (OS windows xp) using asp.net. In my application, I can get WMS feature information in IE8 with the confirmation msg "This page is accessing information that is not under its control. This poses a security risk. Do you want to continue?" given Yes. But in Chrome, i cannt get feature info. It says

XMLHttpRequest cannot load http://xxx.xxx.x.xxx:8080/geoserver/cite/wms?LAYERS=cite%3Aplym_p1_examplec…e%2Fpng&INFO_FORMAT=application%2Fvnd.ogc.gml&SRS=EPSG%3A27700&X=596&Y=160. Origin http://localhost:3890 is not allowed by Access-Control-Allow-Origin.

I have found similar questions Using WFS protocol in OpenLayers? but its for after hosting the web application in geoserver.My case is still its in under developing in my local machine. My code is:

roadidPicker = new OpenLayers.Control.WMSGetFeatureInfo({
url: 'http://xxx.xxx.x.xxx:8080/geoserver/cite/wms',
    title: 'identify features on click',        
    queryVisible: true
});
roadidPicker.infoFormat = 'application/vnd.ogc.gml';
roadidPicker.events.register("getfeatureinfo", this, pickRoadid);
osMap.addControl(roadidPicker);
roadidPicker.activate();

function pickRoadid(e) {    
if (e.features.length > 0) {
    var val = e.features[0].attributes['theme'];
    alert(val);
}
}

I have configured the proxy.cgi file in Geoserver (usr/lip/cgi-bin/proxy.cgi) and added my local ip address in

allowedHosts = ['xxx.xxx.x.xxx', 'www.openlayers.org', 'openlayers.org', 'labs.metacarta.com', 'world.freemap.in', 'prototype.openmnnd.org', 'geo.openplans.org', 'sigma.openplans.org', 'demo.opengeo.org', 'www.openstreetmap.org', 'sample.azavea.com', 'v2.suite.opengeo.org', 'v-swe.uni-muenster.de:8080', 'vmap0.tiles.osgeo.org','www.openrouteservice.org']

and added the below line in my script.

OpenLayers.ProxyHost = "/cgi-bin/proxy.cgi?url=";

but it says another error in chrome console:

GET localhost:3890/usr/lib/cgi-bin/….…T%3D‌​application%252Fvnd.ogc.gml%26SRS%3DEPSG%253A27700%26X%3D682%26Y%3D284 404 (Not Found) 

I dont know whether its right or wrong. Proxy.cgi should be copied in Geoserver or my machine? in which path?

Please anyone suggest me to fix this issue

Best Answer

It is a little more complicated than just adding proxy.cgi to your web server. From your post I assume you are developing you application on your local windows machine and connecting to Geoserver that is hosted on a separate web server somewhere.

The initial issue you are running into is the different domain issue. If a web applications javascript attempts to load data that is not of a very limited range of formats from a different webserver than the webserver that hosts the site the browser will not allow this to work. With the Geoserver and the OpenLayers.Control.WMSGetFeatureInfo the information can be presented in a number of different formats and that in turn triggers the Access-Control-Allow-Origin error.

The way to get around this is to add a proxy script to the same webserver (in this case your local machine) that is serving up the web application you are working on. The dependancy here will be that your webserver can run the script. For example if you are using tomcat or jetty I would recommend a .jsp script as it is supported by default by these systems. If you are using apache2 you will need to configure it to support whatever script you prefer.

I am going to assume you are using something simple like tomcat or jetty. If this is the case add this script in the root directory of your webapp:

<%@page session="false"%>
<%@page import="java.net.*,java.io.*" %>
<%
try {
    String reqUrl = request.getQueryString();

    URL url = new URL(reqUrl);
    HttpURLConnection con = (HttpURLConnection)url.openConnection();
    con.setDoOutput(true);
    con.setRequestMethod(request.getMethod());
    int clength = request.getContentLength();
    if(clength > 0) {
        con.setDoInput(true);
        byte[] idata = new byte[clength];
        request.getInputStream().read(idata, 0, clength);
        con.getOutputStream().write(idata, 0, clength);
    }
    response.setContentType(con.getContentType());

    BufferedReader rd = new BufferedReader(new InputStreamReader(con.getInputStream()));
    String line;
    while ((line = rd.readLine()) != null) {
        out.println(line);
    }
    rd.close();

} catch(Exception e) {
    response.setStatus(500);
}
%>

This should be something like [tomcat_root)/webapps/MyApplication/proxy.jsp Now somewhere in you application before you make any openlayers calls ect add the following:

OpenLayers.ProxyHost = "/proxy.jsp?url=";

This should get around the issue. Of course depending on your setup you may need to adjust some of this to work in your particular situation. This is how I have setup my applications before and it works quite well.

One final thing to note is that this is a very basic proxy script that I have given you here. If you are going to put it on a production server you will need to be mindful that it presents a security risk and should be hardened to protect your sytem before putting it into production.