2015-07-16 21 views
14

Ho un'applicazione costruita su Spring MVC.Come eseguire il proxy delle richieste HTTP in Spring MVC?

voglio scrivere semplice proxy che elabora le richieste come segue:

  1. inviare la stessa richiesta HTTP ad un server specifico
  2. risposta acquisizione HTTP da questo server specifico
  3. ritorno la stessa risposta alla richiesta di cliente

Ecco quello che ho finora:

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

Funziona bene, ma non in tutti i casi. Ho controllato il monitor di rete di Chrome e alcune delle richieste che utilizzano questo proxy non sono riuscite.

Ecco le intestazioni di campione richieste non riuscite risposta:

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 

Qui ci sono le intestazioni di risposta richiesta campione di successo:

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 

Cosa c'è di più Chrome genera un errore nella console:

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

Le richieste che sto inoltrando sono richieste WMS GetMap e il mio proxy i li sta inoltrando a Geoserver nascosto. Ho notato che le richieste non riuscite dovrebbero restituire immagini 512x512 .png trasparenti che sono tutte vuote. I successi restituiscono immagini 512x512 .png che non sono solo trasparenti ma contengono anche alcuni colori.

risposta

8

Sembra che il server remoto risponda con risposte chunked quando le dimensioni diventano troppo grandi, la libreria Apache HttpClient raccoglie tutti gli elementi troncati in un unico HttpResponse, ma lascia l'intestazione Transfer-Encoding: chunked.

non ho potuto testare, ma si dovrebbe filtrare il Transfer-Encoding: chunked per sbarazzarsi di questo problema:

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()); 
     } 
    } 
    ... 
+0

Grande risposta. Grazie. Ho esaminato la documentazione HTTP e ho scoperto quanto segue: "I proxy/gateway DEVONO rimuovere qualsiasi codifica di trasferimento prima di inoltrare un messaggio tramite un protocollo conforme a MIME." http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.4.6 –