spring-web:5.5.8 https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.2 According to the RFC specification, a header does not allow multiple values, but multiple value lists separated by commas are allowed When there isContent-type: application/x-www-form-urlencoded, application/x-www-form-urlencoded Data cannot be read properly, but ifContent-type: ["application/x-www-form-urlencoded","application/x-www-form-urlencoded"], as shown in the following figure curl -X POST -d "a=1&b=2" 127.0.0.1:8088/test -H "Content-type: application/x-www-form-urlencoded" -H "Content-type: application/x-www-form-urlencoded" Spring When there are multiple content-type, it cannot be read accurately, resulting in the form data cannot be injected

In the following case, the test object will be a null value `curl -X POST -d "a=1&b=2" 127.0.0.1:8088/test -H "Content-type: application/x-www-form-urlencoded,application/x-www-form-urlencoded" Spring When there are multiple content-type, it cannot be read accurately, resulting in the form data cannot be injected

test case:

    @PostMapping("/test")
    @ResponseBody
    void test(Test test, @RequestHeader("Content-Type") String contentType){
        System.out.println(contentType);
        System.out.println(test.getA()!=null);
    }

    public static class Test{
        String a;
        String b;

        public String getA() {
            return a;
        }

        public void setA(String a) {
            this.a = a;
        }

        public String getB() {
            return b;
        }

        public void setB(String b) {
            this.b = b;
        }
    }

`

Comment From: bclozel

The @RequestHeader annotation merely resolves values from HTTP headers, but does not know about their actual meanings or conventions. It's up to you to parse them if needed. In this case, you can also use @RequestHeader("Content-Type") List<String> contentTypes to convert them automatically to lists. In short, what you're seeing in @RequestHeader does not represent internal content negotiation or how the web framework reasons about the incoming message.

Now according to the RFC, the Content-Type header must only include a single media-type value so the use case you are showing here is invalid. Because the web framework cannot parse properly the incoming content-type, form binding does not operate and this explains the behavior you are seeing.

I'm closing this issue as invalid.

Comment From: funky-eyes

The @RequestHeader annotation merely resolves values from HTTP headers, but does not know about their actual meanings or conventions. It's up to you to parse them if needed. In this case, you can also use @RequestHeader("Content-Type") List<String> contentTypes to convert them automatically to lists. In short, what you're seeing in @RequestHeader does not represent internal content negotiation or how the web framework reasons about the incoming message.

Now according to the RFC, the Content-Type header must only include a single media-type value so the use case you are showing here is invalid. Because the web framework cannot parse properly the incoming content-type, form binding does not operate and this explains the behavior you are seeing.

I'm closing this issue as invalid.

So why can adding multiple content-type in the form of an array read form data?

Comment From: bclozel

I don't know. Both cases are invalid anyway. Is there a improvement to be made or a bug here?

Comment From: funky-eyes

I don't know. Both cases are invalid anyway. Is there a improvement to be made or a bug here?

curl -X POST -d "a=1&b=2" 127.0.0.1:8088/test -H "Content-type: application/x-www-form-urlencoded" -H "Content-type: application/x-www-form-urlencoded" This example is obviously valid, the code I have provided, and the test results have also been provided

Comment From: bclozel

The very first line of your report states that this type of request is invalid according to the RFC

https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.2 According to the RFC specification, a header does not allow multiple values, but multiple value lists separated by commas are allowed

Comment From: bclozel

If you change your repro case to use the following:

    @PostMapping("/test")
    @ResponseBody
    void test(HttpServletRequest request, Test test) {
        System.out.println(request.getContentType());
        System.out.println(test.getA());
    }

You will see that it's actually the Servlet container that is enforcing the behavior you are describing, not Spring. I haven't seen anything special about this in the Servlet spec so I assume this is up to Servlet container implementations.

Comment From: funky-eyes

If you change your repro case to use the following:

java @PostMapping("/test") @ResponseBody void test(HttpServletRequest request, Test test) { System.out.println(request.getContentType()); System.out.println(test.getA()); }

You will see that it's actually the Servlet container that is enforcing the behavior you are describing, not Spring. I haven't seen anything special about this in the Servlet spec so I assume this is up to Servlet container implementations.

thx