【问题标题】:How do I modify proxy responses using asynchronous servlets?如何使用异步 servlet 修改代理响应?
【发布时间】:2015-02-24 11:05:13
【问题描述】:

我正在尝试实现一个异步 servlet,它将接收最终用户的请求,将其传递给后端服务器并获取响应。

到目前为止,这听起来像是 Jetty 的 ProxyServlet 的一个非常标准的应用程序。

现在,变化在于我的后端将使用包含语句(有点像服务器端包含)进行响应,我需要对其进行解析、查询后端并插入到最终用户响应流中的适当位置。

您将如何实施?我对在 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();
    }
}

【问题讨论】:

    标签: asynchronous jetty servlet-3.0 ssi


    【解决方案1】:

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

    注意:这是全新的功能,在实现中肯定会有一些缺陷。

    这是一个专门的AsyncProxyServlet,旨在简化修改来自客户端的请求内容和/或来自远程服务器的响应内容的复杂性。 (这在proxy的2边有不同的Transfer-Encoding时尤其复杂)

    在您的用例中,从覆盖 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字符串。

    【讨论】:

    • 很棒的反应!现在,如果有办法根据后端响应标头转换输入,我就准备好了。
    • @mabi 您需要清楚“输入”的含义。如果您的意思是“一种基于服务器响应标头转换服务器响应内容的方法”,那么这当然是可能的。创建服务器响应转换器时,您可以使用服务器响应(包括标头和所有),因此您可以在转换服务器响应内容时查看服务器响应标头。
    • 我错过了转换器可以使用响应的事实。是的,这就是我所追求的。越来越好,谢谢!
    猜你喜欢
    • 1970-01-01
    • 2022-06-18
    • 2012-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多