Cloudflare修改引用站点策略
感谢Cloudflare提供的免费服务,让本项目得以实现。
在此向Cloudflare致以最高的敬意。
前言
参考上一篇博客:使用 Cloudflare Workers 搭建随机图片 API,我搭建了随机P站图片API,结果博客上一直加载不出来。折腾了一个小时后搞定,记录一下方法。
问题
本地起Hexo服务器预览图片正常,本以为是缓存问题,强制刷新页面也没有用。
打开github.io托管版本是没有问题的,非常奇怪。
排查
请求分析
对比了一下图片的请求,发现:
- 来自blog.esing.dev的图片请求没有附带上自己的Referer,因此被workers内的请求头检测拦下;
- 来自zxis233.github.io的图片请求正常带上了自己的Referer,因此能正常显示。
这就很奇怪了,毕竟我访问blog-dsx.pages.dev时,图片也是能正常携带Referer的。问题可能出在HTTP的响应头上。
实际上Referer
是Referrer
的错误拼写。由于早期HTTP规范中的拼写错误,为了保持向下兼容,只好将错就错。
HTTP头中的Referrer-Policy
以及JavaScript和DOM中的referrer
属性是拼写正确的。
果不其然,对比了一下,发现两个请求的“常规”选项有区别:
- 来自blog.esing.dev的请求中,引用站点策略为
same-origin
; - 来自zxis233.github.io的请求中,引用站点策略为
strict-origin-when-cross-origin
。
这导致了两个请求非同源时,图片请求未带上自己的Referer。
何谓“同源”、何谓“同站”?
源(origin)= 协议(scheme)+ 主机名(hostname)+ 端口号(port)
站(site)= 有效顶级域名(eTLD)+1
其中,有效顶级域名即为dev/com/org这类,而 +1 表示的是和前面二级域名的组合,如baidu.com。
下面举个简单的例子。以https://www.esing.dev为例,下面网站的关系是:
对比网址 | 是否同源 | 是否同站 |
---|---|---|
https://www.baidu.com | 否,因为 主机名 不同 | 否,因为 eTLD+1 不同 |
https://esing.dev | 是,因为 子域名 不影响 | |
https://music.esing.dev | ||
http://www.esing.dev | 否,因为 协议 不同 | 是,因为 协议 不影响 |
www.esing.dev:80 | 否,因为 端口 不同 | 是,因为 端口号不影响 |
www.esing.dev:443 | 是,完全匹配 | |
www.esing.dev | 是,完全匹配(默认为HTTPS访问) | 是,因为 端口号 不影响 |
修改请求头
既然如此,我们修改一下主站为blog.esing.dev的请求头就行了。如何修改呢?
- 进入CF控制台,选择对应的域,我的是esing.dev
- 点击侧边栏的“规则—转换规则—修改响应头”
- 创建一个规则,表达式为
(http.request.full_uri wildcard "https://blog.esing.dev/*")
,将下列响应头设置为静态:cross-origin-resource-policy
:cross-origin
referrer-policy
:strict-origin-when-cross-origin
- 大功告成!
或者直接点击下面链接:https://dash.cloudflare.com/redirect?zone=rules/transform-rules/modify-response-header ,会自动跳转到配置的地方。
后记
想起来之前配置live2d的API时也遇到了跨域的问题:
Access to fetch at 'https://my.live2d.api/live2d/switch/?id=1' from origin 'https://blog.esing.dev' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
因此要设置一下对应的响应头,加上这三条:
Access-Control-Allow-Methods
:GET,HEAD,POST,OPTIONS
Access-Control-Allow-Origin
:*
(按理来说应当是注明允许的域,但是这个字段不支持多个域名,只能用*了)Access-Control-Max-Age
:86400
Cloudflare Snippet
CF之前在内测Snippet,这玩意可以看做是动态的Origin Rules + Cache Rules + Configuration Rules + Page Rules + Transform Rules + Redirect Rules + …
官方的例子中就有“动态配置CORS策略”:
1 | // Define CORS headers |
只能说功能实在太强了。虽然免费账户只能享受每个域5条Snippet规则,但是也足够了,毕竟这玩意一个顶六个。啥时候能把页面规则给到5个就好了
现在还在Beta测中,期待正式上线。
后记
2024.12.16
Snippet上线了,然而仅限Pro计划使用,可惜。不知道后续会不会给免费计划名额呢?