Dr.*_*ibo 3 java apache-httpcomponents
我正在使用 Apache httpcomponents 实现彗星式(延迟响应)http 服务器。我的代码与http://hc.apache.org/httpcomponents-core-ga/examples.html上的“基本非阻塞 HTTP 服务器”示例非常相似
我使用 DefaultServerIOEventDispatch 和 DefaultListeningIOReactor 来调度请求,就像在示例代码中一样。在我的 NHttpRequestHandler 中,我想记录每个请求的 IP 地址。
在 HttpRequestHandler 中,您可以访问 HttpRequest、HttpResponse 和 HttpContext。使用 NHttpRequestHandler,您还有一个 NHttpResponseTrigger。如何获取请求来自的远程 IP 地址?我看不出如何使用可用的对象来做到这一点。
更新,这是我最终使用的 Scala 代码:
def getIp(context: HttpContext): Option[String] = {
val conn = context.getAttribute(ExecutionContext.HTTP_CONNECTION)
conn match {
case inet: HttpInetConnection =>
inet.getRemoteAddress match {
case sock: java.net.InetSocketAddress => // HttpComponents 4.1
Some(sock.getAddress.getHostAddress)
case adr: java.net.InetAddress => // HttpComponents 4.2
Some(adr.getHostAddress)
case unknown =>
Some(unknown.toString)
}
case _ => None
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,HttpComponents 4.1 中有一个额外的步骤。
我花了很长时间弄清楚这一点,所以我想我会分享以防将来有人在这篇文章中徘徊。
起初,我在httpcore-nio 4.1并获得连接似乎是不可能的。最终,我用反射 hack 做到了(这可能绝不是最好的方法)。升级到 4.2.1 后就容易多了。我将在下面分享这两种解决方案。403 Forbidden如果连接的客户端不是本地主机,将返回以下代码。
@Override
public void handle(final HttpRequest request, final HttpResponse response, final HttpContext context) {
HttpInetConnection connection = (HttpInetConnection) context.getAttribute(ExecutionContext.HTTP_CONNECTION);
InetAddress ia = connection.getRemoteAddress();
if("localhost".equals(ia.getHostName()) {
response.setStatusCode(HttpStatus.SC_FORBIDDEN);
return;
}
...
}
Run Code Online (Sandbox Code Playgroud)
给智者一句话:不要这样做。它适用于 4.1,但在升级 4.2.x 时会中断。如果可以,请改为升级。
该解决方案适用于httpcore-nio 4.1但要注意,该代码是一个可怕的、可怕的反射黑客,用于从iosession最终变量 ( HttpContext) 中获取私有字段( ) 。
@Override
public void handle(final HttpRequest request, final HttpResponse response, final HttpContext context) {
try {
Field f = context.getClass().getDeclaredField("iosession");
boolean accessible = f.isAccessible();
Field modifiersField = Field.class.getDeclaredField("modifiers");
int modifiers = f.getModifiers();
modifiersField.setAccessible(true);
modifiersField.set(f, f.getModifiers() & ~Modifier.FINAL & ~Modifier.PRIVATE);
f.setAccessible(true);
IOSession io = (IOSession) f.get(context);
f.setAccessible(accessible);
modifiersField.set(f, modifiers);
SocketAddress sa = io.getRemoteAddress();
if("localhost".equals(((InetSocketAddress) sa).getHostName())) {
response.setStatusCode(HttpStatus.SC_FORBIDDEN);
return;
}
} catch (Exception e) {
logger.error("No way! I can't believe this fantastic piece of code threw an exception!", e);
}
...
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2535 次 |
| 最近记录: |