简体   繁体   中英

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. Most of the information/parameters needed by the server is sent by the client through HTTP headers. We are now prototyping the use of REST API calls using Jersey where the same parameters are provided as JSON inputs. 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:

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.

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? 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.

A wrapped request will never apply to a standard Jetty Handler , as that's not participating in a ServletContext or Filter chain.

It is also impossible to wrap the core Jetty Request object due to the needs of the context-less environment it executes within. 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. The technique of wrapping these components is discouraged in modern usage because it limits your options for better performing webapps.

You have 2 choices, both modify the Request headers in-place.

  1. Modify the Request headers before dispatch.
  2. Modify the Request headers during dispatch via a low level Jetty Handler.

If you choose to modify the headers before dispatch, there are 2 places you can do this.

  1. As a HttpConfiguration.Customizer
  2. During one of the pre-dispatch HttpChannel.Listener events

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.

The code that modifies the Request headers will all do the same thing, here's the Handler version as an example.

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");
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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