Duplicate Request headers seem mishandled when case doesn't match

29 views
Skip to first unread message

Brad Wood

unread,
Dec 9, 2021, 2:46:14 PM12/9/21
to Undertow Dev
My understanding of the HTTP spec is that request header names are case insensitive.  And my quick review of the Undertow source is that it represents each header name as an HTTPString, which is supposed to be case insensitive per the comments.  Where I lose the plot a bit is when I try to make sense of the code in the HeaderMap class in regards to how it handles looking up header names.  :-)

Here's the behavior I'm having trouble making sense of.
  • When Undertow parses a request containing two request headers with the same name and the SAME case, it creates a header with two values, as expected.
  • When Undertow parses a request containing two request headers with the same name but DIFFERENT case, it appears to use only the last one encountered and assigns only one value to it.  
This appears to make it impossible for me to access both request values in my code when they do not use a consistent case even though the names are supposed to be case insensitive.  Is this working as designed?  Should I enter a ticket?

Thanks!

~Brad

Developer Advocate
Ortus Solutions, Corp 

ColdBox Platform: http://www.coldbox.org 

Stuart Douglas

unread,
Dec 9, 2021, 8:09:18 PM12/9/21
to Brad Wood, Undertow Dev
Do you have a reproducer? I added https://github.com/undertow-io/undertow/pull/1279 and it seems to work fine.

Stuart

--
You received this message because you are subscribed to the Google Groups "Undertow Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to undertow-dev...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/undertow-dev/CALbQ1o%3Do85b8eKwnvAB%3DvwKaknZ5Op8vkpys1k9St37AMA67_Q%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Brad Wood

unread,
Dec 10, 2021, 3:29:03 PM12/10/21
to Stuart Douglas, Undertow Dev
Hi Stuart, I whipped up a very simple standalone use case that demonstrates the issue.  I created a class with the following code:

import io.undertow.Undertow;
import io.undertow.util.Headers;
import io.undertow.util.HeaderValues;

public class UndertowSample {

    public static void main(String[] args) {

        Undertow server = Undertow.builder()
                .addHttpListener(8080, "localhost")
                .setHandler(exchange -> {
                    exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/html");
                    String response = "Here are the headers:<br>";
                    HeaderValues lowerHeader = exchange.getRequestHeaders().get("test-header");
                    if( lowerHeader != null ) {
                    response += "Number of 'test-header' headers found: " + lowerHeader.size() + "<br>";
                    response += "Values: " + lowerHeader.toString() + "<br>";
                    }
                    HeaderValues upperHeader = exchange.getRequestHeaders().get("TEST-HEADER");
                    if( upperHeader != null ) {
                    response += "Number of 'TEST-HEADER' headers found: " + upperHeader.size() + "<br>";
                    response += "Values: " + upperHeader.toString() + "<br>";
                    }
                    exchange.getResponseSender().send(response);
                }).build();

        server.start();
    }
}


I compiled the class and ran it, starting the server.  First I hit the server via PostMan with two headers of the same case and the output correctly shows both headers processed and available in Undertow regardless of whether they are accessed via uppercase or lowercase:

image.png
Next, I uppercased ONE of the header names and you can see that Undertow now only processes a single header, losing one of the values.  I only get back the second header value regardless of what case I use to access it.

image.png

Let me know if you're able to reproduce the issue with my test code above.

Thanks!

~Brad

Developer Advocate
Ortus Solutions, Corp 

ColdBox Platform: http://www.coldbox.org 


Stuart Douglas

unread,
Dec 13, 2021, 12:17:43 AM12/13/21
to Brad Wood, Undertow Dev
I still don't see it. I ran https://github.com/undertow-io/undertow/commit/1854e51c0efc5fd805cc6720f432aa35c5415bb3 and the output has two headers:

Here are the headers:<br>Number of 'test-header' headers found: 2<br>Values: [test1, test2]<br>Number of 'TEST-HEADER' headers found: 2<br>Values: [test1, test2]<br>

Are you sure it is not an issue with your client? Can you use Wireshark to have a look at what is actually going over the wire.

Stuart

Brad Wood

unread,
Dec 13, 2021, 12:23:26 AM12/13/21
to Stuart Douglas, Undertow Dev
I'm just hitting with Postman, which is pretty industry standard.  Can you try hitting your test server when postman?  I'll run a packet trace tomorrow to ensure it isn't an issue with Postman.  Is there a way to log the raw, unparsed request body in undertow?

Stuart Douglas

unread,
Dec 13, 2021, 12:30:39 AM12/13/21
to Brad Wood, Undertow Dev
I just checked and it is only sending the one header, so it is a bug in postman.

Stuart

Brad Wood

unread,
Dec 13, 2021, 12:33:39 AM12/13/21
to Stuart Douglas, Undertow Dev
Wow, I never would have suspected postman! Great news for undertow, lol.  Thanks for trying so hard to reproduce.  I'll search for a postman bug tomorrow and get one entered if needed.  

Flavia Rainone

unread,
Dec 13, 2021, 9:06:19 AM12/13/21
to Brad Wood, Stuart Douglas, Undertow Dev
This kind of corner case is always good to test, I just merged it. Thanks for your PR, @Stuart Douglas !


For more options, visit https://groups.google.com/d/optout.


--

Flavia Rainone

Principal Software Engineer

Red Hat

frai...@redhat.com   

Brad Wood

unread,
Dec 13, 2021, 7:16:35 PM12/13/21
to Flavia Rainone, Stuart Douglas, Undertow Dev
FYI: I confirmed this today via Wireshark and httpbin.org and have filed a support request with Postman.  

Thanks!

~Brad

Developer Advocate
Ortus Solutions, Corp 

ColdBox Platform: http://www.coldbox.org 


Reply all
Reply to author
Forward
0 new messages