带嵌入式码头和球衣的服务器端自定义标头

时间:2019-06-04 18:06:08

标签: java jersey jax-rs jetty

我们有一个旧应用程序,该应用程序使用嵌入式Jetty并通过客户端进行HTTP调用来提供功能。服务器所需的大多数信息/参数由客户端通过HTTP标头发送。现在,我们使用Jersey来原型化REST API调用的使用,其中提供与JSON输入相同的参数。要求之一是保持向后兼容性,并且不干扰现有功能。

虽然我们能够使用Jersey并传递参数,但我们在以下方面寻求帮助:

Request base_request = request instanceof Request ? (Request)request : HttpConnection.getCurrentConnection().getHttpChannel().getRequest();
Response base_response = response instanceof Response ? (Response)response : HttpConnection.getCurrentConnection().getHttpChannel().getResponse();

这实际上不使用我发送的HttpServletRequestWrapper对象。由于此行代码查找org.eclipse.jetty.server.Request对象,因此我尝试围绕该对象创建包装器,但是这样做没有用,因为实例似乎大部分内容为null,再加上它不会提供Request对象将提供的其余方法。

class MyRequestWrapper extends Request
{
   public MyRequestWrapper(HttpServletRequest request)
   {
      super( ((Request)request).getHttpChannel(), ((Request)request).getHttpInput());
   }

   @Override
   public String getHeader(String name)
   {
      if(name.equalsIgnoreCase("X-My-Test"))
      {
         return "MyName";
      }
      return super.getHeader(name);
   }
}

将JSON输入作为标头从REST处理方法发送到现有Jetty处理程序的最佳方法是什么,而又不会引起安全问题?我想我可以稍微调整一下基本请求的检查,但是我不确定执行此请求的最佳方法。

1 个答案:

答案 0 :(得分:0)

被包装的请求仅对在其中创建被包装的请求的同一ServletContextFilter链有效,并且仅从创建之时起才应用于其余正在执行的Filter链。

包装请求永远不会应用于标准码头Handler,因为它不参与ServletContextFilter链。

由于在其中执行的无上下文环境的需求,因此也无法包装核心Jetty Request对象。您无法更改此行为。

如果您要包装请求,而不仅仅是提供自定义请求标头,请立即停止对您正在处理的包装和废话的所有操作。

  

注意:停止包装HttpServletRequestHttpServletResponse或Servlet流的那一刻,您将有能力使用Servlet 3.0及更高版本中引入的功能,例如AsyncContext和AsyncI。 / O。在现代用法中不鼓励使用包装这些组件的技术,因为它限制了您选择性能更好的Web应用程序的可能性。

您有2个选择,都可以就地修改Request标头。

  1. 在分发前修改Request标头。
  2. 在通过低级Jetty处理程序进行分发期间修改Request标头。

如果您选择在发送前修改标头,则可以在2个地方执行此操作。

  1. 作为HttpConfiguration.Customizer
  2. HttpChannel.Listener调度前事件中

如果您选择在分发期间修改标头,则创建一个修改Request标头的Jetty Handler,并将其放在服务器处理程序层次结构的早期。

修改Request标头的代码将做相同的事情,这里以Handler版本为例。

package jetty.demo;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.HandlerWrapper;

public class ModifyRequestHeadersHandler extends AbstractHandler
{
    @Override
    public void handle(String target, Request baseRequest, 
        HttpServletRequest request, HttpServletResponse response) 
        throws IOException, ServletException
    {
        // As fully fleshed out field
        final HttpField X_MY_TEST = new HttpField("X-My-Test", "MyName");
        baseRequest.getHttpFields().put(X_MY_TEST);

        // As predefined header and custom value
        baseRequest.getHttpFields().put(HttpHeader.X_POWERED_BY,
            "ModifiedRequestHeadersHandler");

        // As string header and string value
        baseRequest.getHttpFields().put("X-Foo-Test", "MyFooName");
    }
}