如何使用异步servlet修改代理响应?

时间:2015-02-24 11:05:14

标签: asynchronous jetty servlet-3.0 ssi

我正在尝试实现异步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();
    }
}

1 个答案:

答案 0 :(得分:6)

如果您在代理该内容期间修改内容,请使用Jetty 9.2.8.v20150217及其新org.eclipse.jetty.proxy.AsyncMiddleManServlet

注意:这是全新的功能,实施中肯定会有一些瑕疵。

这是一个专门的AsyncProxyServlet,旨在简化从客户端修改请求内容和/或从远程服务器修改响应内容的复杂性。 (当代理的两面具有不同的传输编码时,这尤其复杂)

在您的使用案例中,首先覆盖AsyncMiddleManServlet.newServerResponseContentTransformer(HttpServletRequest clientRequest, HttpServletResponse proxyResponse, Response serverResponse)并让它返回设计ContentTransformer的新实例,该实例将执行此转换所需的逻辑。

实施您自己的ContentTransformer,它可以在.transform(ByteBuffer input, boolean finished, List<ByteBuffer> output)

中完成所需的操作

input阅读您的内容,一旦您有要写的内容,请执行output.add(modified)。请注意finished标志,因为它可以让您知道何时收到输入内容的最后一位。

另外请注意,如果您需要控制从客户端请求端到远程服务器端的URL差异,请覆盖String rewriteTarget(HttpServletRequest clientRequest)方法,读取客户端请求信息并返回修改后的远程URL字符串