Openlayers WFS跨域请求

通常web项目于gis服务器不在同一域下,这就涉及到了wfs跨域问题。

1 c#代理

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Net;
using System.IO;

namespace WebApplication1
{
    /// <summary>
    /// OpenlayerProxy 的摘要说明
    /// </summary>
    public class OpenlayerProxy : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            if (string.IsNullOrEmpty(context.Request["URL"])) return;
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(context.Request["URL"]);
            request.UserAgent = context.Request.UserAgent;
            request.ContentType = context.Request.ContentType;
            request.Method = context.Request.HttpMethod;

            byte[] trans = new byte[1024];
            int offset = 0;
            int offcnt = 0;

            if (request.Method.ToUpper() == "POST")
            {
                Stream nstream = request.GetRequestStream();
                while (offset < context.Request.ContentLength)
                {
                    offcnt = context.Request.InputStream.Read(trans, offset, 1024);
                    if (offcnt > 0)
                    {
                        nstream.Write(trans, 0, offcnt);
                        offset += offcnt;
                    }
                }
                nstream.Close();
            }
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            //Encoding enc = Encoding.GetEncoding(65001);
            context.Response.ContentType = response.ContentType;
            StreamReader loResponseStream = new StreamReader(response.GetResponseStream());
            string lcHtml = loResponseStream.ReadToEnd();
            context.Response.Write(lcHtml);
            response.Close();
            loResponseStream.Close();

        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }

    }
}

2 基于java的servlet

package com.nkstar.action;

import javax.servlet.http.HttpServlet;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * This is a transparent HTTP proxy written in Java that is similar to the proxy
 * in the OpenLayers examples, which is written in Python. These proxies are
 * used to circumvent browser restrictions on cross-domain requests with
 * Javascript.
 * </p>
 * <p>
 * To use the proxy you need to 1) configure the proxy servlet in your web.xml
 * and 2) use OpenLayers.setProxyHost to set the url-path to the proxy. If the
 * proxy is configured to listen to the url-pattern '/gwtOpenLayersProxy/*' then
 * the proxy host should be set to 'gwtOpenLayersProxy?targetURL='.
 * </p>
 * Initial code for this proxy is based upon <a href=
 * "http://trac.openlayers.org/changeset/8099/sandbox?format=diff&new=8099">the
 * following code</a><br />
 * see also <a href=
 * "http://java.sun.com/docs/books/tutorial/networking/urls/readingWriting.html"
 * title="this networking tutorial">this networking tutorial</a>
 * <p>
 */
@SuppressWarnings("serial")
public class OpenLayersProxyServlet extends HttpServlet {

	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		processRequest(request, response);
	}

	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		processRequest(request, response);
	}

	private void processRequest(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		HttpURLConnection connection = null;
		InputStream istream = null; // input to proxy
		OutputStream ostream = null; // output from proxy
		InputStream connectionIstream = null; // output for the target is
		// input for the connection
		OutputStream connectionOstream = null; // input for the target is
		// output for the connection

		String remoteHost = request.getRemoteHost(); // get host address of
		// client - for checking
		// allowedHosts
		boolean allowedHost = isAllowedHost(remoteHost); // The allowedHosts
		// are the hosts
		// that are allowed
		// to use the Open
		// Proxy.
		try {
			// easy way to ignore case of param?
			if (request.getParameter("targetURL") != null
					&& request.getParameter("targetURL") != "" && allowedHost) {

				// HTTPUrlConnection looks at http.proxyHost and http.proxyPort
				// system properties.
				// Make sure these properties are set these if you are behind a
				// proxy.

				// step 1: initialize
				String requestMethod = request.getMethod();

				URL targetURL = new URL(request.getParameter("targetURL"));
				connection = (HttpURLConnection) targetURL.openConnection();
				connection.setRequestMethod(requestMethod);
				transferHTTPRequestHeaders(connection, request);

				// step 2: proxy requests
				if (requestMethod.equals("GET")) {
					// default for setDoInput is true
					connectionIstream = connection.getInputStream();
				}
				;
				if (requestMethod.equals("POST")) {
					transferHTTPRequestHeadersForPOST(connection, request);
					int clength = request.getContentLength();// clength is
					// for checking
					// if there is a
					// POST body. Is
					// that
					// sufficient?

					if (clength > 0) {
						istream = request.getInputStream();
						connection.setDoOutput(true);// for POST we need to
						// write to connection
						connection.setRequestProperty("Content-Length", Integer
								.toString(clength)); // only valid for POST
						// request
						connectionOstream = connection.getOutputStream();
						// copy the request body to remote outputStream
						copy(istream, connectionOstream);
					}
					connectionIstream = connection.getInputStream();
				}

				// step 3: return output
				// can output be the same for GET/POST? or different return
				// headers?
				// servlet may return 3 things: status code, response headers,
				// response body
				// status code and headers have to be set before response body
				response.setContentType(connection.getContentType());
				ostream = response.getOutputStream();
				copy(connectionIstream, ostream);
			}
			// if not targetURL send page that targetURL is required param
		} catch (Exception e) {
			response.setStatus(500); // what will user get? default page for
			// response code
			// WMS/WFS have specific responses to errors
			// response.getWriter();//will writing custom result help
			e.printStackTrace();
		} finally {
			if (istream != null) {
				istream.close();
			}
			if (ostream != null) {
				ostream.close();
			}
			if (connectionIstream != null) {
				connectionIstream.close();
			}
			if (connectionOstream != null) {
				connectionOstream.close();
			}
		}

	}

	private void copy(InputStream istream, OutputStream ostream)
			throws Exception {
		int bufferSize = 4 * 4 * 1024;// same buffer size as in Jetty utils
		// (2*8192)
		byte[] buffer = new byte[bufferSize];
		int read;
		while ((read = istream.read(buffer)) != -1) {
			ostream.write(buffer, 0, read);
		}
	}

	private void transferHTTPRequestHeaders(HttpURLConnection connection,
			HttpServletRequest request) {
		// TODO make sure all headers are copied to target, see for HTTP headers
		// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
		// Do request.getProperties to get request properties
		if (request.getHeader("Accept") != null) {
			connection
					.setRequestProperty("Accept", request.getHeader("Accept"));
		}
		if (request.getHeader("Accept-Charset") != null) {
			connection.setRequestProperty("Accept-Charset", request
					.getHeader("Accept-Charset"));
		}
		if (request.getHeader("Accept-Encoding") != null) {
			// TODO browsers accept gzipped, should proxy accept gzip and how to
			// handle it?
			// connection.setRequestProperty("Accept-Encoding",
			// request.getHeader("Accept-Encoding"));
		}
		if (request.getHeader("Authorization") != null) {
			connection.setRequestProperty("Authorization", request
					.getHeader("Authorization"));
		}
		if (request.getHeader("Connection") != null) {
			// TODO HTTP/1.1 proxies MUST parse the Connection header field
			// before a message is forwarded and, for each connection-token in
			// this field, remove any header field(s) from the message with the
			// same name as the connection-token.
			// connection.setRequestProperty("Connection",
			// request.getHeader("Connection"));
		}

		// set de-facto standard proxy headers (x-forwarded-for, others?s)
		if (request.getHeader("X-Forwarded-For") != null) {
			connection.setRequestProperty("X-Forwarded-For", request
					.getHeader("X-Forwarded-For"));// TODO append IP proxy
		} else {
			connection.setRequestProperty("X-Forwarded-For", request
					.getRemoteAddr());// TODO append IP proxy
		}
	}

	private void transferHTTPRequestHeadersForPOST(
			HttpURLConnection connection, HttpServletRequest request) {
		if (request.getHeader("Content-Type") != null) {
			connection.setRequestProperty("Content-Type", request
					.getContentType());
		} else {
			// throw exception?
		}
	}

	private boolean isAllowedHost(String remoteHost) {
		// TODO checking of host
		return true;
	}

}

ashx,servlet这两种直接可以放在web项目当中部署,简单操作。

使用说明

OpenLayer2代理使用,只需在程序开头或init方法第一句写上proxyhost即可。
OpenLayers.ProxyHost = '/OpenlayerProxy.ashx?URL=';

  var url = 'http://localhost:8090/geoserver/wfs?SERVICE=WFS&VERSION=1.1.0&REQUEST=GetFeature&OUTPUTFORMAT=GML2&TYPENAME=pgrouting:Mypgrouting&viewparams=' + viewparams;
	    var request = OpenLayers.Request.POST({
	        url: url,
	        callback: onComplete
	    });

OpenLayer3 代理使用

 queryButton.addEventListener('click', function (event) {
        var viewparams = "ARRAY[[" + locatearr.join("],[") + "]]";
        viewparams = stringReg(viewparams);
        viewparams = "destinationarr:" + viewparams;
        var url ='http://localhost:8090/geoserver/wfs?SERVICE=WFS&VERSION=1.1.0&REQUEST=GetFeature&OUTPUTFORMAT=json&TYPENAME=pgrouting:Mypgrouting&viewparams=' + viewparams;
        url = '/OpenlayerProxy.ashx?URL=' + encodeURIComponent(url);
        $.ajax({
            type: "POST",
            url: url,
            dataType:"text",
            success: onComplete
        });
    });

需要对url进行编码,否则代理进去丢失参数。

3 使用cros

3.1 下载地址:http://pan.baidu.com/s/1miDDwJu

3.2 下载后解压,得到的是org/mortbay/servlets/CrossOriginFilter.class文件,把此文件复制到安装目录下的WEB-INF/classes文件夹中,在我电脑上的路径为:GeoServer 2.7.0\webapps\geoserver\WEB-INF\classes\org\mortbay\servlets\CrossOriginFilter.class.

3.3 打开geoserver安装目录下的web.xml文件,我的电脑上路径为:GeoServer 2.7.0\webapps\geoserver\WEB-INF\web.xml

3.4 在filter集合末尾额外添加一个filter:
 <filter>
      <filter-name>cross-origin</filter-name>
      
      <filter-class>org.mortbay.servlets.CrossOriginFilter</filter-class>
      <init-param>
        <param-name>allowedOrigins</param-name>
        <param-value>*</param-value>
      </init-param>
      <init-param>
       <param-name>allowedMethods</param-name>
       <param-value>GET,POST</param-value>
      </init-param>
      <init-param>
       <param-name>allowedHeaders</param-name>
      <param-value>X-Requested-With,Content-Type,Accept,Origin</param-value>
      </init-param>
    </filter> 
3.5 在filter-mapping末尾额外添加一个filter-mapping
<filter-mapping>
        <filter-name>cross-origin</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
3.6 重启GeoServer服务即可。
优点:post,get跨域请求即可。
–以上针对geoserver2.9以下版本,以独立安装方式,非war包形式安装。

–以下针对>=geoserver2.9版本设置如下:
1 从http://central.maven.org/maven2/org/eclipse/jetty/jetty-servlets/下载对应的jar,比如geoserver2.9依赖的jetty版本号是9.2.13.v20150730,那么就下载该版本的jar。
2 将下载好的 jetty-servlets-9.2.13.v20150730.jar 放到webapps/geoserver下的lib中。
3 配置下webapps/geoserver/web.xml。
<filter>
        <filter-name>cross-origin</filter-name>
        <filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>cross-origin</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
4 重启geoserver即可。


4 使用jsonp

4.1  打开geoserver安装目录下的web.xml文件,我的电脑上路径为:GeoServer 2.7.0\webapps\geoserver\WEB-INF\web.xml
4.2 将jsonp注释取消

4.3 重启GeoServer。

4.4 使用示例

function getFeature(options)
{
    $.ajax(Global360Val.gisserverhost+'geoserver/wfs',{
        type: 'GET',
        data: {
            service: 'WFS',
            version: '1.1.0',
            request: 'GetFeature',
            typename: options.typename,
            srsname: options.srid,
            outputFormat: 'text/javascript',
            viewparams:options.viewparams,
            bbox:(options.extent===undefined)?undefined:options.extent.join(',') +  ','+options.srid,//与filter只能用一个
            filter:options.filter
        },
        dataType: 'jsonp',
        jsonpCallback:'callback:'+options.callback,
        jsonp:'format_options'
    });

}
 Source.deviceSource=new ol.source.Vector();
    getFeature({
        typename:'tb_place_management',
        callback:'loadDevice'
    });
function loadDevice(res){
    var features=geojsonFormat.readFeatures(res);
    Source.deviceSource.addFeatures(features);
}
优点:无需安装插件,取消注释即可。
缺点:jsonb只能get,对于参数过长的url的get会失败。不能post,所以提交xml,或者wfs_t都不行。

完毕!


转载自:https://blog.csdn.net/freeland1/article/details/41204485

You may also like...