1

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?

a13e
  • 838
  • 2
  • 11
  • 27
  • Are asking how to extract a custom header on the server, or how to specify a custom header on the client? `HttpClient` is a Java class used by *clients*. `HttpServletRequest` is an interface used on *servers* for getting information sent by a client. Your question is very confusing, so please **edit** the question and clarify what you're asking about. – Andreas Jul 02 '21 at 23:56
  • @Andreas thank you for the request. Yes, this is essentially on the server. My handler code has httpServletRequest where I want to add the header. Sorry for the earlier confusion. I just edited the quesion as per your suggestion. – a13e Jul 03 '21 at 00:10
  • @Andreas I am aware of the fact that HttpServletRequest type is read-only and that is why I am confused about how to solve this. – a13e Jul 03 '21 at 00:14
  • What do you mean ‘add the header to the request on the server’? Do you want to send the header back to the client (put it on the response); or just add some context for the rest of your application (just add it to the environment in one of any number of ways: other arguments, threadlocals, a map of properties)? – BeUndead Jul 03 '21 at 00:29
  • @BeUndead Oh! I want to use it to do a response. What is actually happening is a request is made to my API X. X then does some operation and forwards the request to a different env running with Python. Python server responds to the request with 200 Ok but not with actual data request indented. instead it calls another method Y on my server. Y is not supposed to respond to the original request. But to make this happen, I need to do a look up on the request in Y's logic. Therefore I need to keep something in the header of the my request. Does this make the scenario clearer? – a13e Jul 03 '21 at 00:35
  • 1
    So you're saying that your Java web server is sending an HTTP request to a Python web server, and that you want to add a custom header to the request sent from Java to Python? If so, then understand that the Java `HttpServletRequest` and `HttpServletResponse` are not used for sending a request on to the Python web server, you'll be using `HttpClient` for that. --- If you want to send a custom header *back* to the original client, then you'd use `HttpServletResponse` for that. You would not be using `HttpServletRequest` for any of that. – Andreas Jul 03 '21 at 00:45

1 Answers1

1

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.

Joakim Erdfelt
  • 46,896
  • 7
  • 86
  • 136