Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to proxy HTTP requests in Spring MVC?

I have an application built on top of Spring MVC.

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

  1. send the same HTTP request to some specific server
  2. capture HTTP response from this specific server
  3. return the same answer to requesting client

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;
}

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

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

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

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.

like image 871
Mateusz Radziszewski Avatar asked Jul 16 '15 10:07

Mateusz Radziszewski


People also ask

How to set proxy in Spring RestTemplate?

Using SimpleClientHttpRequestFactory Sending a request to a proxy using RestTemplate is pretty simple. All we need to do is to call the setProxy(java. net. Proxy) from SimpleClientHttpRequestFactory before building the RestTemplate object.


1 Answers

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.

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());
        }
    }
    ...
like image 116
Serge Ballesta Avatar answered Oct 18 '22 00:10

Serge Ballesta