如何使用异步 servlet 修改代理响应?
How do I modify proxy responses using asynchronous servlets?
我正在尝试实现一个异步 servlet,它将接收最终用户的请求,将其传递到后端服务器并获取响应。
到目前为止,这听起来像是 Jetty ProxyServlet
的一个非常标准的应用程序。
现在,不同之处在于我的后端将使用 include 语句(有点像 Server-Side-Includes)进行响应,我需要对其进行解析、查询后端并插入到最终用户响应中的适当位置流。
您将如何实施?我特别好奇在 onResponseContent
回调期间解析和触发中间请求,据我所知,它可能包含也可能不包含完整响应(因此可能只包含 include 语句的一部分)。
为了说明,这是我目前拥有的:
@WebServlet(name = "MyServlet",
urlPatterns = {"/my/outbounduri/*"},
initParams = {
@WebInitParam(name = "proxyTo", value = "/servlet/backend")
}
)
public class MyHandler extends ProxyServlet {
@Override
protected void customizeProxyRequest(HttpServletRequest srequest,
HttpServletResponse sresponse ) {
// add custom headers for the backend
}
@Override
protected void onResponseContent(HttpServletRequest request,
HttpServletResponse response, Response proxyResponse,
byte[] buffer, int offset, int length, Callback callback) {
try {
// instead of passing the content on, we need to catch
// include statements
// response.getOutputStream().write(buffer, offset, length);
callback.succeeded();
} catch (Throwable x) {
callback.failed(x);
}
}
@Override
protected void onResponseSuccess(HttpServletRequest request,
HttpServletResponse response, Response proxyResponse) {
AsyncContext asyncContext = request.getAsyncContext();
asyncContext.complete();
}
}
如果您在内容代理期间修改内容,请使用 Jetty 9.2.8.v20150217
及其新的 org.eclipse.jetty.proxy.AsyncMiddleManServlet
。
注意:这是全新的功能,在实现中肯定会有一些缺陷。
这是一个专门的 AsyncProxyServlet
旨在简化修改来自客户端的请求内容 and/or 来自远程服务器的响应内容的复杂性。 (当代理的两端有不同的 Transfer-Encoding 时,这尤其复杂)
在您的用例中,从覆盖 AsyncMiddleManServlet.newServerResponseContentTransformer(HttpServletRequest clientRequest, HttpServletResponse proxyResponse, Response serverResponse)
开始,让它 return 成为您设计的 ContentTransformer
的新实例,该实例执行此转换所需的逻辑。
实现您自己的 ContentTransformer
,它可以在 .transform(ByteBuffer input, boolean finished, List<ByteBuffer> output)
中完成它需要做的事情
尽你所能阅读 input
,一旦你有东西要写,就做一个 output.add(modified)
。请注意 finished
标志,因为它会让您知道何时收到了最后一位输入内容。
另外注意,如果需要控制客户端请求端到远程服务器端的URL差异,重写String rewriteTarget(HttpServletRequest clientRequest)
方法,读取客户端请求信息和return修改远程 URL 字符串。
我正在尝试实现一个异步 servlet,它将接收最终用户的请求,将其传递到后端服务器并获取响应。
到目前为止,这听起来像是 Jetty ProxyServlet
的一个非常标准的应用程序。
现在,不同之处在于我的后端将使用 include 语句(有点像 Server-Side-Includes)进行响应,我需要对其进行解析、查询后端并插入到最终用户响应中的适当位置流。
您将如何实施?我特别好奇在 onResponseContent
回调期间解析和触发中间请求,据我所知,它可能包含也可能不包含完整响应(因此可能只包含 include 语句的一部分)。
为了说明,这是我目前拥有的:
@WebServlet(name = "MyServlet",
urlPatterns = {"/my/outbounduri/*"},
initParams = {
@WebInitParam(name = "proxyTo", value = "/servlet/backend")
}
)
public class MyHandler extends ProxyServlet {
@Override
protected void customizeProxyRequest(HttpServletRequest srequest,
HttpServletResponse sresponse ) {
// add custom headers for the backend
}
@Override
protected void onResponseContent(HttpServletRequest request,
HttpServletResponse response, Response proxyResponse,
byte[] buffer, int offset, int length, Callback callback) {
try {
// instead of passing the content on, we need to catch
// include statements
// response.getOutputStream().write(buffer, offset, length);
callback.succeeded();
} catch (Throwable x) {
callback.failed(x);
}
}
@Override
protected void onResponseSuccess(HttpServletRequest request,
HttpServletResponse response, Response proxyResponse) {
AsyncContext asyncContext = request.getAsyncContext();
asyncContext.complete();
}
}
如果您在内容代理期间修改内容,请使用 Jetty 9.2.8.v20150217
及其新的 org.eclipse.jetty.proxy.AsyncMiddleManServlet
。
注意:这是全新的功能,在实现中肯定会有一些缺陷。
这是一个专门的 AsyncProxyServlet
旨在简化修改来自客户端的请求内容 and/or 来自远程服务器的响应内容的复杂性。 (当代理的两端有不同的 Transfer-Encoding 时,这尤其复杂)
在您的用例中,从覆盖 AsyncMiddleManServlet.newServerResponseContentTransformer(HttpServletRequest clientRequest, HttpServletResponse proxyResponse, Response serverResponse)
开始,让它 return 成为您设计的 ContentTransformer
的新实例,该实例执行此转换所需的逻辑。
实现您自己的 ContentTransformer
,它可以在 .transform(ByteBuffer input, boolean finished, List<ByteBuffer> output)
尽你所能阅读 input
,一旦你有东西要写,就做一个 output.add(modified)
。请注意 finished
标志,因为它会让您知道何时收到了最后一位输入内容。
另外注意,如果需要控制客户端请求端到远程服务器端的URL差异,重写String rewriteTarget(HttpServletRequest clientRequest)
方法,读取客户端请求信息和return修改远程 URL 字符串。