Skip to content

Content-Disposition response header not overriden for failed StreamingResponseBody #35116

Open
@SergeyRukhlyadko

Description

@SergeyRukhlyadko

Spring Boot: 3.3.13; 3.4.7

If return type in Controller is ResponseEntity and Content-Disposition header is set, it's copied in error response which defined in ControllerAdvice.
if you also define Content-Disposition header in error response, the header is duplicated.

package com.example.demo;

import java.io.FileInputStream;

import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;

@RestController
public class DefaultController {

    @GetMapping("/")
    public ResponseEntity<StreamingResponseBody> getMethodName() {
        return ResponseEntity.ok()
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"report.txt\"")
                .body(out -> {
                    try (var in = new FileInputStream("C:\\template.txt")) {
                        byte[] buffer = new byte[1024];
                        int len;
                        while ((len = in.read(buffer)) > 0) {
                            out.write(buffer, 0, len);
                        }
                    }
                });
    }

}
package com.example.demo;

import java.io.FileNotFoundException;

import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class DefaultExceptionHandler {

    @ExceptionHandler
    ResponseEntity<String> handle(FileNotFoundException e) {
        return ResponseEntity.internalServerError()
                .contentType(MediaType.TEXT_PLAIN)
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; inline")
                .body("File not found");
    }
}

http request log

* Preparing request to http://localhost:8080/
* Current time is 2025-06-26T10:26:12.266Z
* Enable automatic URL encoding
* Using default HTTP version
* Enable timeout of 30000ms
* Disable SSL validation
* Hostname in DNS cache was stale, zapped
*   Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#13)

> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: insomnia/11.0.2
> Accept: */*

* Mark bundle as not supporting multiuse

< HTTP/1.1 500 
< Content-Disposition: attachment; filename="report.txt"
< Content-Disposition: attachment; inline
< Content-Type: text/plain
< Content-Length: 14
< Date: Thu, 26 Jun 2025 10:26:12 GMT
< Connection: close


* Received 14 B chunk
* Closing connection 13

I also attached demo project to reproduce it.

demo.zip

Metadata

Metadata

Assignees

No one assigned

    Labels

    in: webIssues in web modules (web, webmvc, webflux, websocket)status: waiting-for-triageAn issue we've not yet triaged or decided on

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions