Skip to content

Instantly share code, notes, and snippets.

@noobnooc
Last active October 3, 2024 11:42
Show Gist options
  • Save noobnooc/d0407b5fb81cff9d36f981170b99d4e6 to your computer and use it in GitHub Desktop.
Save noobnooc/d0407b5fb81cff9d36f981170b99d4e6 to your computer and use it in GitHub Desktop.
cloudflare-worker-proxy
// Website you intended to retrieve for users.
const upstream = 'api.openai.com'
// Custom pathname for the upstream website.
const upstream_path = '/'
// Website you intended to retrieve for users using mobile devices.
const upstream_mobile = upstream
// Countries and regions where you wish to suspend your service.
const blocked_region = []
// IP addresses which you wish to block from using your service.
const blocked_ip_address = ['0.0.0.0', '127.0.0.1']
// Whether to use HTTPS protocol for upstream address.
const https = true
// Whether to disable cache.
const disable_cache = false
// Replace texts.
const replace_dict = {
'$upstream': '$custom_domain',
}
addEventListener('fetch', event => {
event.respondWith(fetchAndApply(event.request));
})
async function fetchAndApply(request) {
const region = request.headers.get('cf-ipcountry').toUpperCase();
const ip_address = request.headers.get('cf-connecting-ip');
const user_agent = request.headers.get('user-agent');
let response = null;
let url = new URL(request.url);
let url_hostname = url.hostname;
if (https == true) {
url.protocol = 'https:';
} else {
url.protocol = 'http:';
}
if (await device_status(user_agent)) {
var upstream_domain = upstream;
} else {
var upstream_domain = upstream_mobile;
}
url.host = upstream_domain;
if (url.pathname == '/') {
url.pathname = upstream_path;
} else {
url.pathname = upstream_path + url.pathname;
}
if (blocked_region.includes(region)) {
response = new Response('Access denied: WorkersProxy is not available in your region yet.', {
status: 403
});
} else if (blocked_ip_address.includes(ip_address)) {
response = new Response('Access denied: Your IP address is blocked by WorkersProxy.', {
status: 403
});
} else {
let method = request.method;
let request_headers = request.headers;
let new_request_headers = new Headers(request_headers);
new_request_headers.set('Host', upstream_domain);
new_request_headers.set('Referer', url.protocol + '//' + url_hostname);
let original_response = await fetch(url.href, {
method: method,
headers: new_request_headers,
body: request.body
})
connection_upgrade = new_request_headers.get("Upgrade");
if (connection_upgrade && connection_upgrade.toLowerCase() == "websocket") {
return original_response;
}
let original_response_clone = original_response.clone();
let original_text = null;
let response_headers = original_response.headers;
let new_response_headers = new Headers(response_headers);
let status = original_response.status;
if (disable_cache) {
new_response_headers.set('Cache-Control', 'no-store');
}
new_response_headers.set('access-control-allow-origin', '*');
new_response_headers.set('access-control-allow-credentials', true);
new_response_headers.delete('content-security-policy');
new_response_headers.delete('content-security-policy-report-only');
new_response_headers.delete('clear-site-data');
if (new_response_headers.get("x-pjax-url")) {
new_response_headers.set("x-pjax-url", response_headers.get("x-pjax-url").replace("//" + upstream_domain, "//" + url_hostname));
}
const content_type = new_response_headers.get('content-type');
if (content_type != null && content_type.includes('text/html') && content_type.includes('UTF-8')) {
original_text = await replace_response_text(original_response_clone, upstream_domain, url_hostname);
} else {
original_text = original_response_clone.body
}
response = new Response(original_text, {
status,
headers: new_response_headers
})
}
return response;
}
async function replace_response_text(response, upstream_domain, host_name) {
let text = await response.text()
var i, j;
for (i in replace_dict) {
j = replace_dict[i]
if (i == '$upstream') {
i = upstream_domain
} else if (i == '$custom_domain') {
i = host_name
}
if (j == '$upstream') {
j = upstream_domain
} else if (j == '$custom_domain') {
j = host_name
}
let re = new RegExp(i, 'g')
text = text.replace(re, j);
}
return text;
}
async function device_status(user_agent_info) {
var agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
var flag = true;
for (var v = 0; v < agents.length; v++) {
if (user_agent_info.indexOf(agents[v]) > 0) {
flag = false;
break;
}
}
return flag;
}
@wtta1812
Copy link

放到 cloudflare word 报错

@1194117884
Copy link

测试了,可以使用。
请求时需要设置几个请求头
1.“cf-ipcountry”
2.“cf-connecting-ip”
3.“user-agent”

分别完成 地区黑名单,IP黑名单和客户端设备识别

@gedageda
Copy link

gedageda commented Apr 8, 2023

怎么设置请求头?

@Hysian
Copy link

Hysian commented Apr 24, 2023

@zgbjmy2009
image
这样设置请求头

@OceanLcJ
Copy link

OceanLcJ commented May 5, 2023

你好最后一共请求头填什么
方便说一下嘛?@Hysian

@Hysian
Copy link

Hysian commented May 10, 2023

@OceanLcJ 按照我的截图那样填写就行,user-agent 你打开浏览器控制台,里面复制一下你的其他请求的 user-agent 就行

@OceanLcJ
Copy link

@Hysian 谢谢

@minisind
Copy link

Cannot find name 'connection_upgrade'.

@zhaobudaomingzi
Copy link

Cannot find name 'connection_upgrade'.

一样

@panhuabin1
Copy link

image

直接复制代码过去的

@XxSbyH
Copy link

XxSbyH commented Jul 7, 2023

image

直接复制代码过去的

解决了吗?我也是这样

@AQIU-MAX
Copy link

AQIU-MAX commented Jul 7, 2023

复制过来就这样,上图这样,添加标头了还是一样

@cssjidi
Copy link

cssjidi commented Jul 27, 2023

image

直接复制代码过去的

试试加const或者let去声明

@AndrosEt
Copy link

connection_upgrade 前面加个 var 声明:

var connection_upgrade = new ....

new_response_headers.set('access-control-allow-credentials', true); 这里的 true 要用字符串形式,变成

new_response_headers.set('access-control-allow-credentials', 'true');

@Chapoly1305
Copy link

connection_upgrade 前面加个 var 声明:

var connection_upgrade = new ....

new_response_headers.set('access-control-allow-credentials', true); 这里的 true 要用字符串形式,变成

new_response_headers.set('access-control-allow-credentials', 'true');

感谢更新,确实解决了部分报警,不过控制台仍然对于 clone() 的使用给出了Warning,认为资源浪费。
"Your worker created multiple branches of a single stream (for instance, by calling response.clone() or request.clone()) but did not read the body of both branches. This is wasteful, as it forces the system to buffer the entire stream of data in memory, rather than streaming it through. This may cause your worker to be unexpectedly terminated for going over the memory limit. If you only meant to copy the request or response headers and metadata (e.g. in order to be able to modify them), use the appropriate constructors instead (for instance, new Response(response.body, response), new Request(request), etc)."

以下代码修复了控制台报Warning,我自己进行了一下测试,没有发现异常。供有需要的朋友参考使用。
https://gist.github.com/Chapoly1305/c2f52e198a7cf870d9c0653c1f4d6a5d/revisions

@FreedBird
Copy link

connection_upgrade 前面加个 var 声明:

var connection_upgrade = new ....

new_response_headers.set('access-control-allow-credentials', true); 这里的 true 要用字符串形式,变成

new_response_headers.set('access-control-allow-credentials', 'true');

感谢更新,确实解决了部分报警,不过控制台仍然对于 clone() 的使用给出了Warning,认为资源浪费。 "Your worker created multiple branches of a single stream (for instance, by calling response.clone() or request.clone()) but did not read the body of both branches. This is wasteful, as it forces the system to buffer the entire stream of data in memory, rather than streaming it through. This may cause your worker to be unexpectedly terminated for going over the memory limit. If you only meant to copy the request or response headers and metadata (e.g. in order to be able to modify them), use the appropriate constructors instead (for instance, new Response(response.body, response), new Request(request), etc)."

以下代码修复了控制台报Warning,我自己进行了一下测试,没有发现异常。供有需要的朋友参考使用。 https://gist.github.com/Chapoly1305/c2f52e198a7cf870d9c0653c1f4d6a5d/revisions

非常感谢你,参考了你的js部署一遍就成功了!

@DeSireFire
Copy link

给worker使用自定义域名就会导致访问不到。
报 error 1011.
搞了个简单粗暴的解决方案

const region = request.headers.get('cf-ipcountry').toUpperCase();

改成

const region = 'US'

OK

@amapig
Copy link

amapig commented Feb 10, 2024

image
我上传之后,遇到这个问题,然后浏览器界面总是提示invalid url,请问大家遇到过这个问题吗

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment