spring-projects / spring-boot

Spring Boot helps you to create Spring-powered, production-grade applications and services with absolute minimum fuss.
https://spring.io/projects/spring-boot
Apache License 2.0
75.08k stars 40.67k forks source link

Upgrading to Spring Boot 1.4.4 caused "MIME type may not contain reserved characters" #8123

Closed ksambhav closed 7 years ago

ksambhav commented 7 years ago

I am working on a Spring Boot app that uses "spring-cloud-starter-zuul". After upgrading to version 1.4.4 I am getting following exception for HTTP POST requests. HTTP GET request seems to be working fine.

2017-01-27 14:28:21.329 WARN 6792 --- [ XNIO-2 task-11] o.s.c.n.z.filters.post.SendErrorFilter : Error during filtering

java.lang.IllegalArgumentException: MIME type may not contain reserved characters
    at org.apache.http.util.Args.check(Args.java:36) ~[httpcore-4.4.6.jar:4.4.6]
    at org.apache.http.entity.ContentType.create(ContentType.java:206) ~[httpcore-4.4.6.jar:4.4.6]
    at org.apache.http.entity.ContentType.create(ContentType.java:218) ~[httpcore-4.4.6.jar:4.4.6]
    at org.springframework.cloud.netflix.zuul.filters.route.SimpleHostRoutingFilter.forward(SimpleHostRoutingFilter.java:278) ~[spring-cloud-netflix-core-1.2.4.RELEASE.jar:1.2.4.RELEASE]
    at org.springframework.cloud.netflix.zuul.filters.route.SimpleHostRoutingFilter.run(SimpleHostRoutingFilter.java:180) ~[spring-cloud-netflix-core-1.2.4.RELEASE.jar:1.2.4.RELEASE]
    at com.netflix.zuul.ZuulFilter.runFilter(ZuulFilter.java:112) ~[zuul-core-1.3.0.jar:1.3.0]
    at com.netflix.zuul.FilterProcessor.processZuulFilter(FilterProcessor.java:193) ~[zuul-core-1.3.0.jar:1.3.0]
    at com.netflix.zuul.FilterProcessor.runFilters(FilterProcessor.java:157) ~[zuul-core-1.3.0.jar:1.3.0]
    at com.netflix.zuul.FilterProcessor.route(FilterProcessor.java:118) ~[zuul-core-1.3.0.jar:1.3.0]
    at com.netflix.zuul.ZuulRunner.route(ZuulRunner.java:96) ~[zuul-core-1.3.0.jar:1.3.0]
    at com.netflix.zuul.http.ZuulServlet.route(ZuulServlet.java:116) ~[zuul-core-1.3.0.jar:1.3.0]
    at com.netflix.zuul.http.ZuulServlet.service(ZuulServlet.java:81) ~[zuul-core-1.3.0.jar:1.3.0]
    at org.springframework.web.servlet.mvc.ServletWrappingController.handleRequestInternal(ServletWrappingController.java:157) [spring-webmvc-4.3.6.RELEASE.jar:4.3.6.RELEASE]

HTTP headers:-

Request URL:http://localhost/a/b/c
Request Method:POST
Status Code:500 Internal Server Error
Remote Address:[::1]:80
Response Headers
view source
Cache-Control:no-cache, no-store, max-age=0, must-revalidate
Connection:keep-alive
Content-Type:application/json;charset=UTF-8
Date:Fri, 27 Jan 2017 09:16:14 GMT
Expires:0
Pragma:no-cache
Transfer-Encoding:chunked
X-Application-Context:admin-portal:80
X-Content-Type-Options:nosniff
X-Frame-Options:DENY
X-XSS-Protection:1; mode=block

Request Headers
view source
Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate, br
Accept-Language:en-US,en;q=0.8,hi;q=0.6,ms;q=0.4
Connection:keep-alive
Content-Length:64
Content-Type:application/json;charset=UTF-8
Cookie:JSESSIONID=OtTN2U_QDLcOixJuvdzfDKt_Skc9yGvZgwoHo-JB; XSRF-TOKEN=4ce7fc1f-874b-44c6-a7f9-ee7094f14bd8
DNT:1
Host:localhost
Origin:http://localhost
Referer:http://localhost/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
X-Requested-With:XMLHttpRequest
X-XSRF-TOKEN:4ce7fc1f-874b-44c6-a7f9-ee7094f14bd8

Looks like the ';' character in Content-Type header value is causing the issue. Reverting to 1.4.3.RELEASE does not cause this problem.

wilkinsona commented 7 years ago

AFAICT, that's a bug in Spring Cloud Netflix. It's calling ContentType.create("application/JSON;charset=UTF-8"). If it wants to specify a charset, it should be calling the overloaded variant of that method that takes the charset as a separate argument. Can you please open an issue here for that? /cc @dsyer @spencergibb

As for why the charset is now there, I think that's a change in Spring Framework 4.3.6. @bclozel will know for sure.

bclozel commented 7 years ago

The charset is, by default, par of the JSON media type as of SPR-13631 which was fixed with Spring Framework 4.3.0. So this change was shipped with the first Boot 1.4.x.

In a nutshell, many clients (including popular browsers) don't decode JSON properly if the encoding is not set in the content-type response header. The JSON spec says that the charset should be automatically detected by clients (and limited to UTF-8 and UTF-16), but this is not the case in practice.

spencergibb commented 7 years ago

I fixed this the other day in master https://github.com/spring-cloud/spring-cloud-netflix/commit/d76bd84466616f53e5eee6879fee9a823d767841, but it needs to be ported to Camden

spencergibb commented 7 years ago

Now back-ported to Camden https://github.com/spring-cloud/spring-cloud-netflix/commit/234c4c65ae6566e300b36e35ef637e14a9a7c562