如何在Spring MVC中代理HTTP请求? [英] How to proxy HTTP requests in Spring MVC?

查看:567
本文介绍了如何在Spring MVC中代理HTTP请求?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个基于Spring MVC构建的应用程序.

I have an application built on top of Spring MVC.

我想写一个简单的代理来处理请求,如下所示:

I want to write simple proxy that processes requests as follows:

  1. 将相同的HTTP请求发送到某些特定的服务器
  2. 捕获来自此特定服务器的HTTP响应
  3. 将相同的答案返回给请求客户

这是到目前为止我得到的:

Here is what I've got so far:

public void proxyRequest(HttpServletRequest request, HttpServletResponse response) {
    try {
        HttpUriRequest proxiedRequest = createHttpUriRequest(request);
        HttpResponse proxiedResponse = httpClient.execute(proxiedRequest);
        writeToResponse(proxiedResponse, response);
    } catch (URISyntaxException e) {
        e.printStackTrace();
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

private void writeToResponse(HttpResponse proxiedResponse, HttpServletResponse response){
    for(Header header : proxiedResponse.getAllHeaders()){
        response.addHeader(header.getName(), header.getValue());
    }
    OutputStream os = null;
    InputStream is = null;
    try {
        is = proxiedResponse.getEntity().getContent();
        os = response.getOutputStream();
        IOUtils.copy(is, os);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } finally {
        if (os != null) {
            try {
                os.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        if (is != null) {
            try {
                is.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

private HttpUriRequest createHttpUriRequest(HttpServletRequest request) throws URISyntaxException{
    URI uri = new URI(geoserverConfig.getUrl()+"/wms?"+request.getQueryString());

    RequestBuilder rb = RequestBuilder.create(request.getMethod());
    rb.setUri(uri);

    Enumeration<String> headerNames = request.getHeaderNames();
    while(headerNames.hasMoreElements()){
        String headerName = headerNames.nextElement();
        String headerValue = request.getHeader(headerName);
        rb.addHeader(headerName, headerValue);
    }

    HttpUriRequest proxiedRequest = rb.build();
    return proxiedRequest;
}

它可以正常工作,但并非在所有情况下都可以.我已经检查了Chrome的网络监视器,并且使用此代理的某些请求失败.

It works ok but not in all cases. I've checked in Chrome's network monitor and some of the requests that are using this proxy failed.

以下是示例失败的请求响应的标头:

Here are headers of sample failed request response:

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Disposition: inline; filename=JEDN_EWID.png
Transfer-Encoding: chunked
Date: Thu, 16 Jul 2015 10:31:49 GMT
Content-Type: image/png;charset=UTF-8
Content-Length: 6727

以下是示例成功请求响应的标头:

Here are headers of sample successfull request response:

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Disposition: inline; filename=JEDN_EWID.png
Transfer-Encoding: chunked
Date: Thu, 16 Jul 2015 10:31:49 GMT
Content-Type: image/png;charset=UTF-8
Transfer-Encoding: chunked

此外,Chrome浏览器在控制台中引发错误:

What's more Chrome throws an error in the console:

GET http://localhost:8080/<rest of url> net::ERR_INVALID_CHUNKED_ENCODING

我正在代理的请求是WMS GetMap请求,我的代理正在将它们转发到隐藏的Geoserver.我注意到失败的请求应返回透明的512x512 .png图像,这些图像全部为空.成功的图像返回512x512 .png图像,这些图像不仅透明,而且还包含一些颜色.

The requests that I'm proxying are WMS GetMap requests and my proxy is forwarding them to hidden Geoserver. I've noticed that failed requests should return transparent 512x512 .png images which are all empty. The successfull ones return 512x512 .png images that are not only transparent but also contain some colors.

推荐答案

当大小太大时,远程服务器似乎以分块响应进行响应,Apache HttpClient库将所有分块元素收集在一个大的HttpResponse中,但是将Transfer-Encoding: chunked标头.

It looks like remote server responds with chunked responses when size become too big, Apache HttpClient library gathers all chunked elements in one big HttpResponse, but leaves the Transfer-Encoding: chunked header.

我无法测试,但是您应该过滤掉Transfer-Encoding: chunked来摆脱此问题:

I could not test, but you should filter out the Transfer-Encoding: chunked to get rid of this problem :

private void writeToResponse(HttpResponse proxiedResponse, HttpServletResponse response){
    for(Header header : proxiedResponse.getAllHeaders()){
        if ((! header.getName().equals("Transfer-Encoding")) || (! header.getValue().equals("chunked"))) {
            response.addHeader(header.getName(), header.getValue());
        }
    }
    ...

这篇关于如何在Spring MVC中代理HTTP请求?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆