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.