Skip to content

FormFilter Issue: Incorrect Handling of URL-Encoded Parameters in Query String #3929

@Shawyeok

Description

@Shawyeok

Describe the bug
The FormFilter incorrectly handles POST requests with URL-encoded parameters in the query string, causing double encoding and parameter duplication.

Reproduction Steps

  1. Start a gateway server with the following route configuration:
@SpringBootApplication
public class GatewayServer {

    public static void main(String[] args) {
        SpringApplication.run(GatewayServer.class, args);
    }

    @Bean
    public RouterFunction<ServerResponse> getRoute() {
        return route()
                .POST("/anything", http("https://httpbin.org"))
                .build();
    }
}
  1. Send a POST request to the gateway server:
curl -X POST "http://localhost:8080/anything?foo=%7B%7D" \
  -H "Content-Type: application/x-www-form-urlencoded; charset=UTF-8"

Expected vs. Actual Behavior

Expected request sent to upstream:

POST /anything?foo=%7B%7D HTTP/1.1
Content-Type: application/x-www-form-urlencoded; charset=UTF-8

<empty body>

Actual request sent to upstream:

POST /anything?foo=%257B%257D HTTP/1.1
Content-Type: application/x-www-form-urlencoded; charset=UTF-8

foo=%7B%7D

Root Cause

The issue stems from a mismatch in parameter handling:

  • HttpServletRequest#getParameterMap() returns parameters that have already been URL-decoded by the servlet container
  • The existing queryParams contains raw (non-decoded) parameters
  • This causes the filter to incorrectly process the parameters, resulting in double encoding (%7B%7D becomes %257B%257D) and duplication of parameters in the request body

Map<String, String[]> form = request.getParameterMap();
String queryString = request.getQueryString();
StringBuffer requestURL = request.getRequestURL();
if (StringUtils.hasText(queryString)) {
requestURL.append('?').append(queryString);
}
UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUriString(requestURL.toString());
MultiValueMap<String, String> queryParams = uriComponentsBuilder.build().getQueryParams();

Solution

I will submit a pull request to address this parameter handling inconsistency in the FormFilter.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Status

    Done

    Status

    Done

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions