尝试通过 https 连接在节点 (koa) 服务器上请求静态 css 样式表失败。在 http 上运行良好。
HTTP 工作正常:
- http://www.example.com/assets/css/style.913142291ae94ed177988e5dfc67c66e.css提供文件,工作正常,样式表加载到应用程序。mime 类型是“文本/css”
HTTPS 失败
- https://www.example.com/assets/css/style.913142291ae94ed177988e5dfc67c66e.css下载文件,css 服务不正确。mime 类型为“应用程序/八位字节流”
问题仅发生在 Safari 浏览器、旧版 Chrome 浏览器上。但不会发生在最新的 Chrome 浏览器上。
这是怎么回事?
这是 Context 对象的日志,显示 https 协议上的响应 404:
koa: ctx at staticMiddlewareHandler { request:
{ method: 'GET',
url: '/assets/css/style.913142291ae94ed177988e5dfc67c66e.css',
header:
{ connection: 'upgrade',
host: 'www.mydomain.com',
'x-real-ip': '172.XX.XX.XXX',
'x-forwarded-for': '116.XX.X.XXX, 172.XX.XX.XXX',
'x-nginx-proxy': 'true',
accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'accept-encoding': 'gzip, deflate',
'accept-language': 'en-us',
dnt: '1',
'upgrade-insecure-requests': '1',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Safari/604.1.38',
'x-forwarded-port': '443',
'x-forwarded-proto': 'https' } },
response:
{ status: 404,
message: 'Not Found',
header:
{ 'x-dns-prefetch-control': 'off',
'x-frame-options': 'SAMEORIGIN',
'x-download-options': 'noopen',
'x-xss-protection': '1; mode=block' } },
app: { subdomainOffset: 2, proxy: false, env: 'development' },
originalUrl: '/assets/css/style.913142291ae94ed177988e5dfc67c66e.css',
req: '<original node req>',
res: '<original node res>',
socket: '<original node socket>' }
更新
通过 ReactQL 样板的 Node js 应用程序代码。完整代码在这里:https ://github.com/reactql/kit/blob/master/kit/entry/server.js#L131
// Static file middleware
export function staticMiddleware() {
return async function staticMiddlewareHandler(ctx, next) {
try {
if (ctx.path !== '/') {
return await koaSend(
ctx,
ctx.path,
process.env.NODE_ENV === 'production' ? {
root: PATHS.public,
immutable: true,
} : {
root: PATHS.distDev,
},
);
}
} catch (e) { /* Errors will fall through */ }
return next();
};
}
Nginx 配置
server {
listen 80;
server_name domain.com;
return 301 $scheme://www.$host$request_uri;
}
server {
listen 80;
server_name www.domain.com;
client_max_body_size 20M;
charset utf-8;
# ELB stores the protocol used between the client
# and the load balancer in the X-Forwarded-Proto request header.
# Check for 'https' and redirect if not
if ($http_x_forwarded_proto != 'https') {
return 301 https://$host$request_uri;
}
location / {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
# Bound to Docker my `react` container, exposed on port 4000.
# Set name from docker-compose.yml `volumes_from`
proxy_pass http://react:4000;
}
}
更新 2 我在 nginx 代理顶部有一个 AWS 负载均衡器,将所有 443 流量重定向到 80。