Servlet 过滤器“代理"仅作用于来自远程端点的响应

编程入门 行业动态 更新时间:2024-10-21 09:42:34
本文介绍了Servlet 过滤器“代理"仅作用于来自远程端点的响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我需要某些 HTTP 请求必须重定向到 Spring Boot Web 应用程序/服务,但在请求端,Spring 应用程序什么都不做,而是充当 HTTP 客户端(另一个服务)和请求的真实目的地.但是当响应返回到 Spring 应用程序(从那个目的地)时,我需要 Spring 应用程序能够检查响应并在需要时可能对其采取行动.所以:

I have a need where certain HTTP requests must be redirected to a Spring Boot web app/service, but that on the request-side, the Spring app does nothing and acts as a passthrough between the HTTP client (another service) and the request's true destination. But when the response comes back to the Spring app (from that destination), I need the Spring app to be able to inspect the response and possibly take action on it if need be. So:

  • HTTP 客户端向 someapi.example
  • 发出请求
  • 网络魔术将请求路由到我的 Spring 应用程序,例如 myproxy.example
  • 根据请求,此应用/代理不执行任何操作,因此请求在 someapi.example 上转发
  • someapi.example 处的服务端点将 HTTP 响应返回给代理
  • 位于 myproxy.example 的代理会检查此响应,并可能在将响应返回给原始客户
  • HTTP client makes a request to, say, someapi.example
  • Network magic routes the request to my Spring app at, say, myproxy.example
  • On the request, this app/proxy does nothing, and so the request is forwarded on someapi.example
  • The service endpoint at someapi.example returns an HTTP response back to the proxy
  • The proxy at myproxy.example inspects this response, and possibly sends an alert before returning the response back to the original client
  • 本质上,过滤器充当请求的传递,并且仅在远程服务执行并返回响应之后真正执行任何操作.

    So essentially, a filter that acts as a pass-through on the request, and only really does anything after the remote service has executed and returned a response.

    到目前为止,我最好的尝试是设置一个 servlet 过滤器:

    My best attempt thus far has been to setup a servlet filter:

    @Override void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { chain.doFilter(request, response) // How and where do I put my code? if(responseContainsFizz(response)) { // Send an alert (don't worry about this code) } }

    这可以吗?如果是这样,我应该把检查和响应响应的代码放在哪里?使用我的代码,当我尝试从浏览器点击控制器时抛出异常:

    Is this possible to do? If so, where do I put the code that inspects and acts upon the response? With my code the way it is I get exceptions thrown when trying to hit a controller from a browser:

    java.lang.IllegalStateException: STREAM at org.eclipse.jetty.server.Response.getWriter(Response.java:910) ~[jetty-server-9.2.16.v20160414.jar:9.2.16.v20160414] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_92] rest of stack trace omitted for brevity

    有什么想法吗?

    推荐答案

    根据 Servlet API 文档,您收到 IllegalStateException 的原因是因为您试图调用 ServletResponse.getWriter 在 ServletResponse.getOutputStream 之后已经在响应上被调用.所以看起来你需要调用的方法是ServletResponse.getOutputStream().

    Per the Servlet API documentation, the reason you are getting the IllegalStateException is because you are attempting to call ServletResponse.getWriter after ServletResponse.getOutputStream has already been called on the response. So it appears that the method you need to call is ServletResponse.getOutputStream().

    但是,如果您尝试访问响应的正文,最好的解决方案是将响应包装在 ServletResponseWrapper 中,以便您可以捕获数据:

    However, if you are trying to access the body of the response, the best solution is to wrap the response in a ServletResponseWrapper so that you can capture the data:

    public class MyFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void destroy() { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { MyServletResponseWrapper responseWrapper = new MyServletResponseWrapper((HttpServletResponse) response); chain.doFilter(request, responseWrapper); if (evaluateResponse(responseWrapper)) { // Send an alert } } private boolean evaluateResponse(MyServletResponseWrapper responseWrapper) throws IOException { String body = responseWrapper.getResponseBodyAsText(); // Perform business logic on the body text return true; } private static class MyServletResponseWrapper extends HttpServletResponseWrapper { private ByteArrayOutputStream copyOutputStream; private ServletOutputStream wrappedOutputStream; public MyServletResponseWrapper(HttpServletResponse response) { super(response); } public String getResponseBodyAsText() throws IOException { String encoding = getResponse().getCharacterEncoding(); return copyOutputStream.toString(encoding); } @Override public ServletOutputStream getOutputStream() throws IOException { if (wrappedOutputStream == null) { wrappedOutputStream = getResponse().getOutputStream(); copyOutputStream = new ByteArrayOutputStream(); } return new ServletOutputStream() { @Override public boolean isReady() { return wrappedOutputStream.isReady(); } @Override public void setWriteListener(WriteListener listener) { wrappedOutputStream.setWriteListener(listener); } @Override public void write(int b) throws IOException { wrappedOutputStream.write(b); copyOutputStream.write(b); } @Override public void close() throws IOException { wrappedOutputStream.close(); copyOutputStream.close(); } }; } } }

    更多推荐

    Servlet 过滤器“代理"仅作用于来自远程端点的响应

    本文发布于:2023-10-25 13:50:42,感谢您对本站的认可!
    本文链接:https://www.elefans.com/category/jswz/34/1527139.html
    版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
    本文标签:过滤器   仅作   Servlet   quot

    发布评论

    评论列表 (有 0 条评论)
    草根站长

    >www.elefans.com

    编程频道|电子爱好者 - 技术资讯及电子产品介绍!