Nginx CORS跨域

场景

我们的资源来自网络的四面八方,所以难免需要用上跨域,业界也有非常多跨域的解决方案,这次我是来说说跨域与状态码之间的一个问题。

问题

当我们的 URL 地址返回的状态码是 400、403、404、500 的时候,跨域的资源是不会跟随返回的,也就是说,即便是 Nginx 上配置了 add_header 关键字,也不会随着内容返回而返回。

举个例子说:

add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods *;

当我们在请求对应地址的时候,理应是会返回已经配置好的头部信息,但是我们来看看最终的结果。

200
HTTP/1.1 200 OK
Server: openresty/1.11.2.2
Date: Fri, 26 Jan 2018 08:46:39 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 558
Last-Modified: Tue, 28 Mar 2017 01:13:24 GMT
Connection: keep-alive
ETag: "58d9b8b4-22e"
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: *
Accept-Ranges: bytes

内容无误。

404
HTTP/1.1 404 Not Found
Server: openresty/1.11.2.2
Date: Fri, 26 Jan 2018 08:47:18 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 175
Connection: keep-alive

神奇了,这里404状态码下面居然自定义的响应头消失了。

原因与解决方式

留意 Nginx 文档上说的:

Adds the specified field to a response header provided that the response code equals 200, 201 (1.3.10), 204, 206, 301, 302, 303, 304, 307 (1.1.16, 1.0.13), or 308 (1.13.0). The value can contain variables.

意思就是说,add_header 只会追加到以上响应状态码的响应头上面。

因为咱们的 API 有各种的状态码返回,那么其他状态码下,该怎么办? 大家留意文档上有一个参数。

Syntax:    add_trailer name value [**always**];
Default:    —
Context:    http, server, location, if in location
This directive appeared in version 1.13.2.

你会发现有个 [always] 参数,那么这个参数,就是让你的配置头,应用在所有的影响上面去。

将参数添加进去:

add_header Access-Control-Allow-Origin * always;
add_header Access-Control-Allow-Methods * always;

重启 nginx 服务器后重试一下.

200
HTTP/1.1 200 OK
Server: openresty/1.11.2.2
Date: Fri, 26 Jan 2018 09:01:36 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 558
Last-Modified: Tue, 28 Mar 2017 01:13:24 GMT
Connection: keep-alive
ETag: "58d9b8b4-22e"
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: *
Accept-Ranges: bytes

200请求没变化,一切正常。

404
HTTP/1.1 404 Not Found
Server: openresty/1.11.2.2
Date: Fri, 26 Jan 2018 09:02:12 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 175
Connection: keep-alive
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: *

现在 404 也正确了。我们的跨域也正是配置完成。

关于 OPTIONS 请求

当我们前端发起跨域请求的时候,会事先发起一次 OPTIONS 请求,以用来查询该接口是否支持跨域和对应的请求方法。

在配置方面可以这么做。

if ($request_method = OPTIONS) {
    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Methods *;
    add_header Access-Control-Allow-Credentials true;
    return 204;
   }

当然我这里的 * 这么用是不好的,你需要对应域名去配置。

另外PHP方面我们也提供了一个 CORS 的扩展库,可以直接在fastd中使用。

github: cors-provider


黄总
[链接]

不能因为菜刀能砍人你就以为菜刀只能砍人

778 声望
110 粉丝
0 条评论
推荐阅读
fastd3.2 稳定版发布
继3.1版本之后,经过半年断断续续的迭代,现在3.2版本终于迎来第一个稳定版,未来会继续对其进行研发,除了本身的功能特性外,还会对其能够提供的体系,生态进行完善。

黄总1阅读 1.6k评论 4

把 Go 放到 Nginx C module 之中
最近一段时间,我在做一件有趣的事情,让一个 Nginx C module 通过 Go 代码来访问 gRPC 服务。不得不感慨 Go 真的很流行,让人无法拒绝。之前我做 wasm-nginx-module 时就试图把 tinygo 跑在 Nginx 里面,这次则...

spacewander2阅读 2.1k评论 2

[nginx] 实现域名代理
业务场景有两个系统A、B,A、B两系统均有独立域名,但对外只想暴露A域名。需要实现通过 A域名+B系统子路由 访问 系统B的子页面,图示如下。

DiracKeeko阅读 870

使用Python查询国内 COVID-19 疫情
有时我们只是想要一个速的工具来告诉当前疫情的情况,我们只需要最少的数据。 使用Python语言和tkinter图形化显示数据。首先,我们使用 Tkinter 库使我们的脚本可以图形化显示。使用 requests 库从 丁香园 获取数...

刘遄阅读 824

封面图
前端跨域问题解决办法, Nginx配置为例
💡 Tips:可以将多个系统融合成一个系统,无技术壁垒,可以像iframe一样实现功能组合● qiankun (阿里支持)● micro-app (京东支持)● wujie (腾讯支持)本人推荐● lingjie 携程支持

smallStone阅读 824

gitlab-ce使用nginx做反向代理的方式启用https
由于某些未知的原因,gitlab-ce的https近期出现了问题,被chrome识别出是非安全的连接。索性我们将了gitlab-ce的https改为http。但当下https基本上已经成为了标准,不启用https好像有点说不过去。

myskies阅读 757

FastDFS配置Nginx访问
FastDFS配置Nginx访问FastDFS分布式文件系统安装和配置_亲测成功下载相关依赖软件包 {代码...} 安装Nginx {代码...} Nginx配置访问FastDFSvim /data/apps/nginx-download/conf/nginx.conf {代码...} 启动Nginxmkd...

阿亮说技术阅读 686

不能因为菜刀能砍人你就以为菜刀只能砍人

778 声望
110 粉丝
宣传栏