簡體   English   中英

如何處理具有許多無效URL的代理HTTP請求

[英]How should I handle proxying HTTP requests with many invalid URLs

我需要為我的團隊正在處理的應用程序創建一個代理,如果請求中的某些條件符合條件,我們可以使用該代理來攔截對某些域的請求並返回特定內容(主要是模擬內容,有時包括調試信息等)。滿足(例如,某些身份驗證標頭,遠程地址范圍等)。

對於不需要轉移到我們的開發環境的請求,我希望將它們發送到最初的預期目標。 我最初如何實現此目的的方法是使用ProxyService,該服務將接收HttpServletRequest並使用Apache HttpClient 4.3,提交請求並以要評估的字符串形式返回響應(我們有時會修改內容以簡化調試)。

我遇到了許多問題,其中請求URI的字符無效。 最初,我嘗試使用URL來對URI路徑的每個片段,文件,查詢字符串值等使用URLEncoder.encode之類的東西來重建URI,但是很快我又遇到了另一個問題。

這些請求的某些原始服務器不檢查URL是否已編碼,並且在進行URL編碼時最終失敗。

例如,

http://www.example.com/file.php|x=1|y=2,z=3
https://www.example.com/some/path?foo=[{"x":"1"}]
https://www.example.com/some/path;x=1;y=2/stuff|foo|bar|baz/here

我嘗試將路徑分解為片段,並對每個片段進行編碼,然后將它們附加到字符串生成器中以重新創建URI,但是后來我發現某些服務在接收到編碼URL時會阻塞。

在處理Java這樣的問題時,我相對而言比較環保,我不確定應該在哪里尋找解決方案。

有關該應用程序的詳細信息:

使用Spring 4 MVC嵌入式Tomcat 8 Servlet的Spring Boot應用

理想的情況是,如果我可以采取某種方法,僅接收HttpServletRequest對象,然后以最小的更改將其透明地代理到原始主機,這樣就可以保留標頭,內容,參數等,但是我會仍然能夠訪問響應內容以進行修改以進行開發。

我真正想要避免的是必須編寫和維護一個服務類,該服務類自己處理這些URI。

我認為您可以用任何語言將此問題(編寫反向代理)歸類為一般的難題。 Java中的客戶端HTTP庫充滿了怪癖,公平地說,這可能僅反映了HTTP並非真的就是這么簡單的協議這一事實。 您可能最終不得不實現,或者至少比您想要的更詳細地理解,才能很好地完成代理問題。 客戶端有時會因為太聰明而沮喪(例如,緩存連接和cookie,或進行重定向)。 客戶端的唯一明智選擇是Apache Commons,但它的API並不是很穩定,並且文檔稀疏。

我不得不在Spring應用程序中多次進行反向代理,但是從來沒有找到一個開箱即用的庫。 我總是以特殊情況結​​尾,我確信這些特殊情況會在為其編寫的特定情況下使用(因為我可以對其進行詳盡的測試,並觀察它們在生產中的行為),但始終不相信它們會堅持下去作為通用解決方案。 這是一個非常接近於泛型(也許)的類,但是我敢肯定會遇到問題(其中至少有一個我沒有處理大型響應主體的流)。

上面的摘錄(它使用Spring RestTemplate和Apache HttpClient ):

protected ResponseEntity<byte[]> passthru(HttpServletRequest request, HttpEntity<byte[]> entity,
                Map<String, Object> model) throws Exception {

    String path = extractPath(request);

    HttpHeaders requestHeaders = new HttpHeaders();
    requestHeaders.putAll(getRequestHeaders(entity.getHeaders()));
    requestHeaders.remove(COOKIE);
    requestHeaders.remove(COOKIE.toLowerCase());
    // Get back end cookie if saved in session
    String cookie = (String) model.get(COOKIE_MODEL);
    if (cookie != null) {
        logger.debug("Found back end cookies: " + cookie);
        for (String value : cookie.split(";")) {
            requestHeaders.add(COOKIE, value);
        }
    }

    ResponseEntity<byte[]> response = defaultTemplate.exchange(getUaaBaseUrl() + "/" + path,
                    HttpMethod.valueOf(request.getMethod()), new HttpEntity<byte[]>(entity.getBody(),
                                    requestHeaders),
                    byte[].class);
    HttpHeaders outgoingHeaders = getResponseHeaders(response.getHeaders());
    return new ResponseEntity<byte[]>(response.getBody(), outgoingHeaders, response.getStatusCode());

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM