1

I am sending a request to a third-party API, and their server (PHP 5.5) requires that the content-length header be uppercased 'Content-Length'.

However, I'm using Spring webclient, and it is sending out the 'Content-Length' in lowercased 'content-length', however I tried to send it out as uppercased.

webClient
                    .method(method)
                    .uri(uri)
                    .headers(headersConsumer)
                    .header("Content-Length-Test", Integer.toString(objectMapper.writeValueAsBytes(reqBody).length))
                    .header("Content-Length", Integer.toString(objectMapper.writeValueAsBytes(reqBody).length))
                    .bodyValue(Optional.ofNullable(reqBody).orElse(""))
                    .retrieve()
                    .bodyToMono(returnType)

result

POST /test/test HTTP/1.1
user-agent: ReactorNetty/1.0.12
Content-Type: application/json
Authorization: Basic 
Accept: */*
Host: 127.0.0.1:9999
Content-Length-Test: 202
content-length: 202

You can see that "Content-Length-Test" that I put in prints out as expected, but not for the actual "Content-Length" header.

I've read the following and related posts about how the HTTP standard specifies that all headers are case insensitive.

The problem is the API I need for my service is case-sensitive when it comes to processing headers. How to prevent of converting header name into lower case - Spring boot?

How can I prevent the Content-Length header from being lower cased?

Need help.

Thanks.

WiseDev
  • 13
  • 3

1 Answers1

0

WebClient by default is using Reactor Netty underneath, and that inserts the Content-Length header itself; you don't need to provide it at the WebClient level. As can be seen this is indeed in lower-case.

To fix this, you should configure a Netty HttpClient yourself and then pass it to the WebClient (via ReactorClientHttpConnector).

The HttpClient setup should include (note that it uses a fluent interface so you need to take the HttpClient that is returned from doOnConnected):

httpClient.doOnConnected(connection -> connection.addHandlerFirst(new MessageToMessageEncoder<HttpRequest>() {

            @Override
            protected void encode(ChannelHandlerContext ctx, HttpRequest msg, List<Object> out) {

                HttpHeaders requestHeaders = msg.headers();
                String value = requestHeaders.get("content-length");
                if (value != null) {
                    requestHeaders.remove("content-length")
                                  .set("Content-Length", value);
                } 

                if (msg instanceof ReferenceCounted)
                    ((ReferenceCounted)msg).retain();

                out.add(msg);
            }
))
MotiNK
  • 421
  • 2
  • 12
  • Thanks for the reply! I wasn't expecting an answer at this point. We solved the issue by using the HttpClient, which we didn't like because that would make us use two clients. Thanks! We'll refactor it using your code! – WiseDev Dec 20 '22 at 08:15