简体   繁体   English

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

[英]Server side custom headers with embedded jetty and jersey

We have a legacy application that uses embedded Jetty and provides functionality through clients making HTTP calls. 我们有一个旧应用程序,该应用程序使用嵌入式Jetty并通过客户端进行HTTP调用来提供功能。 Most of the information/parameters needed by the server is sent by the client through HTTP headers. 服务器所需的大多数信息/参数由客户端通过HTTP标头发送。 We are now prototyping the use of REST API calls using Jersey where the same parameters are provided as JSON inputs. 现在,我们使用Jersey来原型化REST API调用的使用,其中提供与JSON输入相同的参数。 One of the requirements is to maintain backward compatibility and not disturb the existing functionality. 要求之一是保持向后兼容性,并且不干扰现有功能。

While we were able to use Jersey and pass in parameters, we are looking for help with the following: 尽管我们能够使用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();

This effectively does not use the HttpServletRequestWrapper object that I send in. Since this line of code looks for the org.eclipse.jetty.server.Request object, I tried creating a wrapper around this object, like so, but this did not work because this instance seems to have most of the content as null, plus it would not provide the rest of the methods that the Request object would provide. 这实际上不使用我发送的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);
   }
}

What is the best way to send the JSON inputs in as headers from the REST handling method to the existing Jetty handlers, without creating security concerns? 将JSON输入作为标头从REST处理方法发送到现有Jetty处理程序的最佳方法是什么,而又不会引起安全问题? I guess I could tweak that check for the base request a bit, but I am not sure of the best way to do it. 我想我可以稍微调整一下基本请求的检查,但是我不确定做到这一点的最佳方法。

Wrapped requests are only valid for the same ServletContext and Filter chain that the wrapped request was created in and only applies to the rest of the executing Filter chain from the point in time it was created. 包装的请求仅对在其中创建包装请求的ServletContextFilter链有效,并且仅适用于从创建之时起执行的Filter链的其余部分。

A wrapped request will never apply to a standard Jetty Handler , as that's not participating in a ServletContext or Filter chain. 包装的请求永远不会应用于标准的Jetty Handler ,因为它不参与ServletContextFilter链。

It is also impossible to wrap the core Jetty Request object due to the needs of the context-less environment it executes within. 由于在其中执行的无上下文环境的需求,也无法包装核心Jetty Request对象。 You cannot change this behavior. 您无法更改此行为。

If you are wrapping requests and whatnot just to provide a custom request header, then stop doing ALL of the wrapping and nonsense you are dealing with right now. 如果要包装请求,而不仅仅是提供自定义请求标头,则立即停止处理您正在处理的所有包装和废话。

Note: The minute you stop wrapping HttpServletRequest , HttpServletResponse , or the Servlet streams is the minute you will have the ability to use features introduced for Servlet 3.0 and newer, such as AsyncContext and Async I/O. 注意:在停止包装HttpServletRequestHttpServletResponse或Servlet流的那一刻,您将可以使用为Servlet 3.0和更高版本引入的功能,例如AsyncContext和Async I / O。 The technique of wrapping these components is discouraged in modern usage because it limits your options for better performing webapps. 在现代用法中不鼓励使用包装这些组件的技术,因为它限制了您选择性能更好的Web应用程序的选择。

You have 2 choices, both modify the Request headers in-place. 您有2个选择,都可以就地修改Request标头。

  1. Modify the Request headers before dispatch. 分发前修改Request标头。
  2. Modify the Request headers during dispatch via a low level Jetty Handler. 通过低级Jetty处理程序在分发过程中修改Request标头。

If you choose to modify the headers before dispatch, there are 2 places you can do this. 如果选择在发送前修改标头,则可以在2个地方执行此操作。

  1. As a HttpConfiguration.Customizer 作为HttpConfiguration.Customizer
  2. During one of the pre-dispatch HttpChannel.Listener events 在预调度HttpChannel.Listener事件之一期间

If you choose to modify the headers during dispatch, then create a Jetty Handler that modifies the Request headers, and put it somewhere early in your server handler hierarchy. 如果您选择在分发期间修改标头,则创建一个Jetty Handler来修改Request标头,并将其放在服务器处理程序层次结构的早期。

The code that modifies the Request headers will all do the same thing, here's the Handler version as an example. 修改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");
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM