version: Spring Boot 2.2.5.RELEASE environment: java: Java(TM) SE Runtime Environment (build 1.8.0_172-b11) os: mac. os and linux contrainer: tomcat
the bug is related to here I have worked for days to reproduced the problem
https://github.com/spring-cloud/spring-cloud-gateway/issues/1600
when I create a controller and just return ResponseEntity there will be return
curl: (56) Illegal or missing hexadecimal sequence in chunked-encoding
my code
@RequestMapping("api/v1")
@RestController
public class ProxyController {
@GetMapping("/proxy500")
public ResponseEntity<?> proxy500(ProxyExchange<byte[]> proxy) {
MultiValueMap<String, String> multiValueMap = new HttpHeaders();
multiValueMap.put("Transfer-Encoding", Collections.singletonList("chunked"));
multiValueMap.put("Connection", Collections.singletonList("close"));
return new ResponseEntity<>("{", multiValueMap, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
detail
curl http://localhost:8080/api/v1/proxy500 -vvv
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /api/v1/proxy500 HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 500
< Transfer-Encoding: chunked
< Connection: close
< Content-Type: text/plain;charset=UTF-8
< Date: Sat, 14 Mar 2020 17:13:04 GMT
<
* Illegal or missing hexadecimal sequence in chunked-encoding
* stopped the pause stream!
* Closing connection 0
curl: (56) Illegal or missing hexadecimal sequence in chunked-encoding
reason maybe here , the header info send flush until message send
org.springframework.http.converter.StringHttpMessageConverter#writeInternal
@Override
protected void writeInternal(String str, HttpOutputMessage outputMessage) throws IOException {
HttpHeaders headers = outputMessage.getHeaders();
if (this.writeAcceptCharset && headers.get(HttpHeaders.ACCEPT_CHARSET) == null) {
headers.setAcceptCharset(getAcceptedCharsets());
}
Charset charset = getContentTypeCharset(headers.getContentType());
StreamUtils.copy(str, charset, outputMessage.getBody());
}
this my source code
https://github.com/taojiaenx/spring-chunk-bug.git
Comment From: rstoyanchev
Thanks for the sample.
If I remove Transfer-Encoding: chunked
, Spring MVC sets the Content-Length: 1
and the request works. However when both Transfer-Encoding: chunked
and Connection: Close
are set, I believe the server closes the connection too soon.
I don't think there is anything wrong with the code in StringHttpMessageConverter
. Setting headers, writing the body, and flushing is expected and normal use of the Servlet API. Also if I change the server to Jetty there is no problem So I suspect an issue in Tomcat and I was able to reproduce it with just a plain Servlet:
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.setStatus(500);
resp.setHeader("Transfer-Encoding", "chunked");
resp.setHeader("Connection", "close");
resp.getOutputStream().write('{');
}
}
So please open an issue in Tomcat's.
Comment From: vector20240801
@rstoyanchev thx, I am will keep working on it
Comment From: deanstef
Hi guys! I am facing the same problem. Did you figured out how to solve it?
Comment From: jgebauer
I am facing the same problem. Is there any solution or workaround that can be used until there is a fix in tomcat for that?
Comment From: rstoyanchev
@jgebauer as I mentioned in my https://github.com/spring-projects/spring-framework/issues/24699#issuecomment-600307198 this is demonstrable with a plain Servlet on Tomcat. Please, open an issue in Tomcat's issue tracker and leave a link here for others to find.
Comment From: jgebauer
I have created an issue on Tomcat's bugtracker that hopefully describes the situation properly Tomcat issue 65201.
Comment From: jgebauer
The issue has been rejected as an application bug.
Comment From: jaggerwang
Same problem! I think it should be solved in application framework not in servlet container.
Comment From: MateuszStefek
The issue is that spring-cloud-gateway-mvc implements the proxy by actually downloading the body of the response into byte[]
.
All downstream response headers that handle how the transport works don't make sense anymore. They should be dropped, because setting them in a controller causes troubles.
I'm manually removing transfer-encoding
, connection
and content-length
headers from ResponseEntity<byte[]>
to avoid any problems. Strange that this isn't done automatically by the library.