spring-cloud / spring-cloud/spring-cloud-gateway

OPTIONS requests failing with Spring Cloud Gateway MVC/HttpClient.

Open
#3,875 5 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

waiting-for-triage
Dominant language
Java
Stars
4.9k
Forks
3.5k
Avg merge
20h 57m
Merged PRs (30d)
8

Description

Describe the bug
Using 4.3.0 version of Spring Cloud Gateway MVC, OPTIONS requests without any request body are failing with the latest version of apache httcomponents HttpClient (5.5.5).

Scenario:

  • Client's OPTIONs is sent without a RequestBody or a content-type header.
  • Spring Cloud Gateway MVC code tries to copy the inbound request body to the outbound request and in the process converts a non-existent/null body to an empty body.
  • HttpClient reads the request and validates it, the latest version of the HttpClient library expect a content-type header to be passed in if there is a request body. In this case it see an empty body (set by Gateway MVC code) and expects content-type header to be passed in....and fails the request.

Exception stack trace:

org.apache.hc.core5.http.ProtocolException: OPTIONS request must have Content-Type header
at org.apache.hc.core5.http.protocol.RequestContent.validateOptionsContentType(RequestContent.java:164) ~[httpcore5-5.3.4.jar!/:5.3.4]
... suppressed lines
at com.erac.edgesvc.gateway.functions.route.CustomProxyExchangeHandlerFunction.handle(CustomProxyExchangeHandlerFunction.java:122)

Possible bug at https://github.com/spring-cloud/spring-cloud-gateway/blob/f33e0270bc25c1973848f1eaae10cfd368831cd2/spring-cloud-gateway-server-webmvc/src/main/java/org/springframework/cloud/gateway/server/mvc/handler/ClientHttpRequestFactoryProxyExchange.java#L48

On the ClientHttpRequest object after copy the value of bodystream attribute is

Image

This causes HttpClient to read a non-null body causing the failure.

Reproduction is simple:

curl -v -i -X OPTIONS http://localhost:8080/test will do it, if you are using the latest apache httcomponents HttpClient version. I also checked HttpClient's validation logic is correct according to HttpSpec:

If the OPTIONS request includes an entity-body (as indicated by the
presence of Content-Length or Transfer-Encoding), then the media type
MUST be indicated by a Content-Type field.

https://datatracker.ietf.org/doc/html/rfc2616#section-9.2

Thanks,
GatewayNovice

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with spring-cloud-gateway-server-webmvc/src/main/java/org/springframework/cloud/gateway/server/mvc/handler/ClientHttpRequestFactoryProxyExchange.java at the linked line, then reproduce with curl -v -i -X OPTIONS http://localhost:8080/test. Trace how the inbound body is copied into the outbound request and verify the request succeeds with the latest Apache HttpClient when no body or Content-Type is supplied.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring
Domain
api, backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
56/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.