corswso2wso2-api-managercontent-disposition

WSO2 APIM 4.5.0 missing CORS headers in actual response – Content-Disposition not exposed


I have a web application that downloads a file by calling a REST API endpoint. This endpoint is behind WSO2 API Manager (WSO2 APIM).

After upgrading from WSO2 APIM 4.2.0 to 4.5.0, the CORS behavior changed. Specifically:

I can see the Content-Disposition header in the GET response using the browser’s developer tools (Network tab), but it is not accessible in JavaScript because Access-Control-Expose-Headers of the actual response is empty, even though it is configured in deployment.toml.

This worked as expected in version 4.2.0 — both preflight and actual requests had the proper CORS headers.

Here is our unchanged CORS configuration in deployment.toml:

[apim.cors]
enable = true
allow_origins = "*"
allow_methods = ["GET","PUT","POST","DELETE","PATCH","OPTIONS"]
allow_headers = ["authorization","Access-Control-Allow-Origin","Content-Type","SOAPAction","apikey","Internal-Key","X-serv-Sales-Channel-Code","X-serv-Terminal-Code","X-serv-APISYS,X-serv-Auth","X-serv-Device-Secret","X-serv-RenderNullFields"]
expose_headers = ["Content-Disposition", "Content-Type", "Content-Language", "WWW-Authenticate"]
allow_credentials = false

Has the behavior of CORS handling changed in 4.5.0? Is there a new configuration I need to set to expose headers like Content-Disposition in the actual response?


Solution

  • Yes, the behavior has changed on PR: Update cors_request_handler sequence to send only the necessary cors-headers values in non-preflight response calls #13691

    To fix that you have 2 options:

    1. (recommended): Add a Response-flow API Policy that sets Access-Control-Expose-Headers

    Use the Publisher → Policies → Add New Policy (Regular Gateway) flow to create a simple “Add Header” policy that sets a transport header. When attaching, pick the Response flow and configure:

    <property action="set"
              name="Access-Control-Expose-Headers"
              value="Content-Disposition,Content-Type,Content-Language,WWW-Authenticate"
              scope="transport"/>
    

    Attach the policy to the operations that return downloadable content (or at the API root if you want it for all operations). Common policies can be reused across many APIs.

    Or

    2. Customize the global _cors_request_handler_.xml sequence. If you want this for all APIs without attaching a policy each time:

    1. Copy the shipped _cors_request_handler_.xml from <APIM_HOME>/repository/resources/api_templates/.

    2. Add a mediation step that sets the Access-Control-Expose-Headers header (as above) on outgoing responses.

    3. Place the customized sequence in the same location (or override via custom product artifact packaging) and restart Gateways so the new template is used when APIs are deployed.