我需要为我的团队正在开发的应用程序创建一个代理,我们可以使用它来拦截对某些域的请求并返回特定内容(主要是模拟内容,有时包括调试信息等)如果某些条件在满足请求(例如,某些身份验证 header 、远程地址范围等)。
对于不需要转移到我们开发环境的请求,我希望将它们发送到原来的预定目标。我最初是如何开始实现这个的是使用一个 ProxyService,它会接受一个 HttpServletRequest 并使用 Apache HttpClient 4.3,提交请求并将响应作为要评估的字符串返回(我们有时会修改内容以使调试更容易)。
我遇到了很多问题,请求 URI 中充斥着无效字符。起初,我尝试使用 URL 为 URI 路径的每个片段、文件、查询字符串值等重建 URI,例如 URLEncoder.encode...但我很快遇到了另一个问题。
这些请求的一些源服务器不检查 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 的 Spring Boot 应用程序 嵌入式 Tomcat 8 servlet
理想的情况是,如果有某种方法我可以只获取 HttpServletRequest 对象,并透明地将其代理到原始主机并进行最小的更改,这样标题、内容、参数等...都将被保留,但我仍然可以访问响应内容以进行修改以进行开发。
我真正想要尝试避免的是必须自己编写和维护一个服务类来处理规范化和清理这些 URI。
最佳答案
我认为您可以将此(编写反向代理)归类为任何语言中的一般难题。 Java 中的客户端 HTTP 库充满了怪癖,公平地说,这可能只是 HTTP 并不是真正那么简单的协议(protocol)这一事实的反射(reflect)。您可能最终不得不实现,或者至少比您希望的更详细地了解整个事情,以做好代理问题。客户端有时会因为过于聪明而让您感到沮丧(例如,缓存连接和 cookie,或遵循重定向)。客户端唯一明智的选择是 Apache Commons,但它的 API 不是很稳定,而且文档也很少。
我不得不在 Spring 应用程序中多次执行反向代理,但从未找到开箱即用的库。我总是以特殊情况结束,我确信这些情况会在它们所针对的特定情况下工作(因为我可以相当详尽地测试它们,并观察它们在生产中的行为),但从未相信它们会站得住脚作为通用解决方案。 Here's one这非常接近通用(也许),但我肯定会遇到问题(其中最重要的是我没有处理过大型响应主体的流)。
以上摘录(使用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());
}
关于java - 我应该如何处理具有许多无效 URL 的代理 HTTP 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22876831/