Gerry Mantha
Gerry Mantha

Reputation: 1098

Why does Camel convert header keys from REST DSL to lowercase in the exchange, when some Camel components using headers are case sensitive?

I'm getting headers into my exchange from a variety of endpoint sources, and in some cases being defined in-route. Only in the case of my REST endpoints are the header keys being converted to lowercase. I get that most things in Camel are case insensitive when referring to header keys and I'm aware of the HTTP spec, for instance this works just fine and case doesn't matter:

.process((exchange) -> {
    exchange.getIn().setHeader("blueMoonNight", "foo");
    System.out.println(exchange.getIn().getHeader("blueMoonNight"));
    System.out.println(exchange.getIn().getHeader("bluemoonnight"));

    })

It's all good. Now if I next use the xquery component this will work in my xquery:

declare variable $in.headers.blueMoonNight as xs:string external;

But this blows up:

declare variable $in.headers.bluemoonnight as xs:string external;

Although Camel's headers are case insensitive in use in many instances, the are not with all components; in this case the xQuery component. Under the covers though, Camel does preserve case in header keys except when using HTTP things like REST DSL where it converts it to lowercase.

For example, if I send a POST to REST DSL with the exact same "blueMoonNight: foo" as before in the HTTP header and later call the same xQuery component, the opposite is true. This blows up:

declare variable $in.headers.blueMoonNight as xs:string external;

But this works fine:

declare variable $in.headers.bluemoonnight as xs:string external;

This inconsistency has caused me some pain when I have many REST and JMS entry points into a route, and conditionally set some new headers in my route according to what headers were originally supplied, then use a Camel component that is picky about header key case like xQuery. Plus having to use $in.headers.myprettylongexternalvariable looks a bit ugly.

I've tried "resetting" headers in only my REST routes by doing something like this to get the case of all my entry points consistent:

.setHeader("blueMoon", simple("${header.blueMoon}"))

Although Camel doesn't complain, it doesn't work. It seems once the header is defined, the case stays the same! Any suggested workarounds?

Upvotes: 1

Views: 2588

Answers (1)

Claus Ibsen
Claus Ibsen

Reputation: 56082

Camel stores the headers in this map implementation

As you can see its JDK TreeMap with insensitive ordering.

So I suspect its xquery or other libraries that does not deal properly with this insensitive ordering of that TreeMap.

You can try to dive into how the xquery (saxon) does that, and ask on their user forums etc.

An alternative is in the latest Camel 2.20 where you can configure different headers map, by the new HeadersMapFactory (https://github.com/apache/camel/blob/master/camel-core/src/main/java/org/apache/camel/spi/HeadersMapFactory.java) where you can use a regular non insensitive HashMap etc, or try the new camel-headersmap component that you can drop on the classpath and Camel should automatic detect and use it (it logs if so) it has a different implementation than the JDK TreeMap so it may work with xquery.

Upvotes: 1

Related Questions