本地开发环境中PUT请求预检OPTIONS的Access-Control-Expose-Headers失效
CORS问题:PUT请求预检OPTIONS中的Access-Control-Expose-Headers被忽略,无法获取自定义响应头
问题说明
本地开发时遇到CORS相关问题:针对PUT请求的预检OPTIONS响应里的Access-Control-Expose-Headers被浏览器忽略,导致JavaScript代码无法获取指定的自定义响应头,控制台输出null而非服务器返回的my-value头值。
复现步骤
- 修改
/etc/hosts添加两个域名:127.0.0.1 locala.test 127.0.0.1 localb.test - 将以下代码保存为
cors.py,执行python cors.py启动服务:from http.server import BaseHTTPRequestHandler, HTTPServer class MyServer(BaseHTTPRequestHandler): # 提供发起CORS请求的页面,访问地址: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) => { // 预期输出x-my-custom的值,实际输出null console.log(response.headers.get('x-my-custom')); }) </script> </body> </html> '''.encode('utf-8')) # 处理预检OPTIONS请求,对应地址: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() # 处理PUT请求,对应地址: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') - 在浏览器访问
http://locala.test:8080即可复现问题。
解决方案
核心问题:Access-Control-Expose-Headers需要放在实际的PUT响应中,而非预检OPTIONS响应里。
浏览器仅会检查实际请求(此处为PUT)的响应头中的Access-Control-Expose-Headers,以此决定哪些自定义头可被JavaScript访问,预检OPTIONS响应中的该头是无效的。
修改do_PUT方法,添加Access-Control-Expose-Headers头:
def do_PUT(self): self.send_response(200) self.send_header("Access-Control-Allow-Origin", "http://locala.test:8080") self.send_header("Access-Control-Expose-Headers", "x-my-custom") # 新增此行 self.send_header("x-my-custom", 'my-value') self.end_headers()
修改后重启服务,再次访问页面,控制台会正确输出my-value。
内容的提问来源于stack exchange,提问作者Michal Charemza
相关产品推荐
相关产品推荐

