使用cf的worker功能实现cors反代
使用cf的worker功能对外站api接口进行反代,避免出现CORS头‘Access-Control-Allow-Origin’不匹配的问题。
# 业务场景
想要做一个浏览器本地化提交cloudflare api的页面,不走网站后端进行请求(避免流量比较大的时候本站ip被禁用api),直接从浏览器发出请求到cloudflare的api接口。这样势必会产生CORS头不匹配的问题,从页面js代码寻求解决方案无果后,想到了用cf自己的worker进行请求。由于worker无固定ip,因此不容易被禁。
# worker脚本
addEventListener(fetch, async event=>{
event.respondWith((async function() {
isOPTIONS = (event.request.method == OPTIONS);
var origin_url = new URL(event.request.url);
function fix(myHeaders) {
// myHeaders.set(Access-Control-Allow-Origin, 需要被代理的请求来源Origin);
myHeaders.set(Access-Control-Allow-Origin, event.request.headers.get(Origin));
if (isOPTIONS) {
myHeaders.set(Access-Control-Allow-Methods, event.request.headers.get(access-control-request-method));
acrh = event.request.headers.get(access-control-request-headers);
//myHeaders.set(Access-Control-Allow-Credentials, true);
if (acrh) {
myHeaders.set(Access-Control-Allow-Headers, acrh);
}
myHeaders.delete(X-Content-Type-Options);
}
return myHeaders;
}
var fetch_url = unescape(origin_url).replace(origin_url.host,api.cloudflare.com/client/v4); //替换为cloudflare api地址
var orig = event.request.headers.get(Origin);
var remIp = event.request.headers.get(CF-Connecting-IP);
var xheaders = event.request.headers.get(x-cors-headers);
if (xheaders != null) {
try {
xheaders = JSON.parse(xheaders);
} catch (e) {}
}
recv_headers = {};
for (var pair of event.request.headers.entries()) {
if ((pair[0].match(^origin) == null) &&
(pair[0].match(eferer) == null) &&
(pair[0].match(^cf-) == null) &&
(pair[0].match(^x-forw) == null) &&
(pair[0].match(^x-cors-headers) == null)
) recv_headers[pair[0]] = pair[1];
}
if (xheaders != null) {
Object.entries(xheaders).forEach((c)=>recv_headers[c[0]] = c[1]);
}
newreq = new Request(event.request,{
headers: recv_headers
});
var response = await fetch(fetch_url,newreq);
var myHeaders = new Headers(response.headers);
cors_headers = [];
allh = {};
for (var pair of response.headers.entries()) {
cors_headers.push(pair[0]);
allh[pair[0]] = pair[1];
}
cors_headers.push(cors-received-headers);
myHeaders = fix(myHeaders);
myHeaders.set(Access-Control-Expose-Headers, cors_headers.join(,));
myHeaders.set(cors-received-headers, JSON.stringify(allh));
if (isOPTIONS) {
var body = null;
} else {
var body = await response.arrayBuffer();
}
var init = {
headers: myHeaders,
status: (isOPTIONS ? 200 : response.status),
statusText: (isOPTIONS ? OK : response.statusText)
};
return new Response(body,init);
}
)());
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
上次更新: 2024/03/11, 23:50:27