When using Spring Cloud Gateway with custom request decorators that cache request bodies, the ‎EncoderHttpMessageWriter::write class (invoked by BodyInserters.insert() automatically calculates and sets the Content-Length header based on the buffered body content, even when the original request intentionally did not include this header.

The EncoderHttpMessageWriter always sets Content-Length for the upstream request, regardless of whether: - The original client request had Content-Length - The body is empty (length = 0) - The request method is GET

Environment: Spring Cloud Gateway version: 2023.0.3 Spring Boot version: 3.2.11 Java version: 17

Suggested fix: Update the logic in EncoderHttpMessageWriter to check byte count. ```if (inputStream instanceof Mono) { return body .singleOrEmpty() .switchIfEmpty( Mono.defer(() -> { message.getHeaders().setContentLength(0); return message.setComplete().then(Mono.empty()); }) ) .flatMap(buffer -> { Hints.touchDataBuffer(buffer, hints, logger); int contentLength = buffer.readableByteCount(); if (contentLength > 0) { message.getHeaders().setContentLength(contentLength); } return message.writeWith( Mono.just(buffer) .doOnDiscard(DataBuffer.class, DataBufferUtils::release) ); }) .doOnDiscard(DataBuffer.class, DataBufferUtils::release); }

Comment From: AtharvUrunkar

Hi @PawelTo, thanks for the detailed report.

Before I start working on a PR, I’d like to make sure I fully understand the expected behavior so the fix goes in the right direction.

Based on your description, can you please confirm the following?

  1. GET requests Should EncoderHttpMessageWriter avoid setting the Content-Length header for GET requests entirely, even if a custom decorator ends up buffering a non-empty body?

  2. Zero-length bodies If the encoded body size is 0 bytes, should the writer skip setting the Content-Length header (and not override an intentionally missing header)?

  3. Non-zero bodies For methods like POST/PUT/PATCH, the writer should set Content-Length only when the body has a positive size, and should avoid overwriting an intentionally omitted header — is that correct?

I plan to update EncoderHttpMessageWriter accordingly and include test coverage for these cases. Once you confirm the expected behavior, I’ll proceed with the implementation.

Thanks!

Comment From: bclozel

@AtharvUrunkar the issue is not triaged yet.

Comment From: PawelTo

yes, that is expected behavior.

Comment From: bclozel

I don't understand this issue @PawelTo, please elaborate. The EncoderHttpMessageWriter writes a body to a request. There is no concept of original request here, only Spring Cloud Gateway is in control of forwarding requests.

The current behavior seems OK to me, as we're only called if there is a body to be written. Maybe you can share a minimal sample (without Spring Gateway being involved) that demonstrates the problem. Please explain what behavior you are expecting and what you are seeing instead. You can also find tips here on how to get help and ask questions.

yes, that is expected behavior.

Are you saying nothing needs to be changed and that we should close this issue?

Comment From: PawelTo

In Spring Cloud Gateway I would like to fetch and store BODY from all request (POST, PUT, GET, etc.) before routing them to dedicated services. To achieve that I have created some custom RequestDecorator extends ServerHttpRequestDecorator, which invoke:

''' return BodyInserters .fromPublisher(...) .insert(outputMessage, new BodyInserterContext()) .then(chainFunction.apply(exchange.mutate().request(this).build())); ‎EncoderHttpMessageWriter::write is invoked by BodyInserters .fromPublisher(...).insert(), which modify orginal request by setting Content-Length header, what can caused some errors for GET request without body.

Comment From: bclozel

Sorry I don't understand. Maybe ask this question on StackOverflow. I don't have the required knowledge to answer cloud gateway questions.

Comment From: PawelTo

@bclozel it's similar to: https://github.com/reactor/reactor-netty/issues/3603

Comment From: bclozel

@PawelTo I don't think we are sending "Content-Length: 0" request headers with WebClient when sending GET requests. I don't think we're making progress here as you haven't demonstrated the behavior in Spring outside of Gateway. Have you considered raising this point to the Gateway team to get some advice? Once the situation is clearer, maybe we can consider a bug or enhancement in Spring Framework.