Home > Software engineering >  Preflight Access-Control-Expose-Headers ignored in CORS on HTTP locally
Preflight Access-Control-Expose-Headers ignored in CORS on HTTP locally

Time:10-23

I'm having trouble getting Access-Control-Expose-Headers from a preflight OPTIONS for a PUT request working in a local development environment - the browser seems to ignore it and doesn't expose the header listed to Javascript code.

Below is an example site that you can run locally, and look in the console to see that null is output rather than the my-value header value returned from the server.


In /etc/hosts add two domains:

127.0.0.1 locala.test
127.0.0.1 localb.test

save the below python program to cors.py, and run it by python cors.py

from http.server import BaseHTTPRequestHandler, HTTPServer

class MyServer(BaseHTTPRequestHandler):

    # Serves the website that makes the CORS request
    # View on http://locala.test:8080/
    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()
        self.wfile.write('''
            <html>
            <head><title>CORS Example</title></head>
            <body>
                <p>Web page that makes a CORS request</p>
                <script>
                    fetch('http://localb.test:8080/', {
                        method: 'PUT'
                    }).then((response) => {
                        // Outputs null, when it should output x-my-custom
                        console.log(response.headers.get('x-my-custom'));
                    })
                </script>
            </body>
            </html>
        '''.encode('utf-8'))

    # To be accessed via http://localb.test:8080/
    def do_OPTIONS(self):
        self.send_response(204)
        self.send_header("Access-Control-Allow-Origin", "http://locala.test:8080")
        self.send_header("Access-Control-Allow-Methods", "PUT")
        self.send_header("Access-Control-Expose-Headers", "x-my-custom")
        self.end_headers()

    # To be accessed via http://localb.test:8080/
    def do_PUT(self):
        self.send_response(200)
        self.send_header("Access-Control-Allow-Origin", "http://locala.test:8080")
        self.send_header("x-my-custom", 'my-value')
        self.end_headers()

webServer = HTTPServer(('127.0.0.1', 8080), MyServer)
print('Running. Press CTRL C to stop.')
try:
    webServer.serve_forever()
except KeyboardInterrupt:
    pass
webServer.server_close()
print('Stopped')

and then view it in http://locala.test:8080 in a browser.

CodePudding user response:

The Access-Control-Expose-Headers header belongs in the response to the actual request, not in the response to the associated preflight request. Adding it to the latter has no effect. See the relevant section of the Fetch standard:

An HTTP response to a CORS request that is not a CORS-preflight request can also include the following header:

Access-Control-Expose-Headers

Indicates which headers can be exposed as part of the response by listing their names.

(my emphasis)

  • Related