javarequestjettyrequest-headershttp-request-parameters

How to add a custom header into coming request on server?


I am using a Jetty 11 server which has a GET method called getObject().

When I receive a request on the server, I want to add a custom header to create a unique identify for the request. So I am trying to add something like x-request-id with value obtained using UUID into the header.

I tried doing a pseudo search in the header itself using -

        final String requestId;
        if (!StringUtil.isEmpty(request.getHeader("request-id")) && !StringUtil.isEmpty(request.getHeader("request-id"))) {
            requestId = request.getHeader(request.getHeader("request-id"));
        }
        else {
            requestId = UUID.randomUUID().toString().toUpperCase(); //.replace("-", "");
        }
        request.setAttribute("Request-ID", requestId);
        System.out.println("requestId - " + requestId);

But this does not seem to get added into the header of the request.

My ultimate target is to forward this request outside the server with this x-request-id as my request switched the environment. Once I receive a response, I want to do some lookup on this request later.

My method looks like this -

public void handle(String target, Request jettyReq, HttpServletRequest request, HttpServletResponse response) {

        // Redirect API control based on HTTP method type
        if (request.getMethod().equals(constGetRequest)) {
            doGetObject(jettyReq, request, response);
        }
        jettyReq.setHandled(true);
    }

How do I achieve this with the HttpServletRequest request in jetty?


Solution

  • Since you are using embedded Jetty, use the built in org.eclipse.jetty.server.HttpChannel.Listener.

    You'll have access to the raw internal Jetty org.eclipse.jetty.server.Request object that has the HTTP Fields for that request.

    To use it, you'll create an instance of that HttpChannel.Listener, and add it as a bean to your connectors.

    MyChannelListener channelListener = new MyChannelListener();
    connector.addBean(channelListener);
    

    There are many events that the listener exposes, you'll probably want to set the X-Request-ID during the void onRequestBegin(Request request) event.

    If using Jetty 9.x you can use the following ...

    @Override
    public void onRequestBegin(Request request)
    {
        request.getHttpFields().put("X-Request-ID", UUID.randomUUID().toString());
    }
    

    If using Jetty 10.0.0+ (including Jetty 11), the request.getHttpFields() is an immutable object. You'll just have to intentionally yank it out, modify it, and replace it, like this ..

    @Override
    public void onRequestBegin(Request request)
    {
        HttpFields.Mutable replacement = HttpFields.build(request.getHttpFields())
            .put("X-Request-ID", UUID.randomUUID().toString().toUpperCase());
        request.setHttpFields(replacement);
    }
    
    

    Read the javadoc on HttpChannel.Listener and pick other things that might fit your needs.

    Then all other access of that request, be it internal components of Jetty, a webapp, a specific servlet, filters, forwarding, includes, error handling in the servlet spec, error handling outside of a servlet context, etc can all see it.

    The only types of requests you wont see on this, are ones that fail the Request line and/or low level Header/Field parsing steps, those will be reported as BadMessageExceptions to the server level error handler.