Cloudflare workers反向代理解决前端跨域问题以及将http转为https
const whiteListSuffixs = [
'*', // allow all domain suffix
]
async function handleRequest(request) {
const urlReq = new URL(request?.url)
let url = urlReq.href?.replace(urlReq.origin+'/', '').trim()
if (!url) {
return new Response(`error code 1, usage: ${urlReq.origin}/http(s)://api.example.com`, {status: 400})
}
if (0!==url.indexOf('https://') && 0===url.indexOf('https:')) {
url = url.replace('https:/', 'https://')
} else if (0!==url.indexOf('http://') && 0===url.indexOf('http:')) {
url = url.replace('http:/', 'http://')
}
let urlTarget
try {
urlTarget = new URL(url)
} catch(e) {
return new Response(`error code 2, usage: ${urlReq.origin}/http(s)://api.example.com`, {status: 400})
}
if (urlTarget?.port) {
return new Response('port is not allowed', {status: 400})
}
const hostname = urlTarget?.hostname
if (!hostname) {
return new Response(`error code 3, usage: ${urlReq.origin}/http(s)://api.example.com`, {status: 400})
}
let inWhiteList = false
for (const suffix of whiteListSuffixs) {
if (hostname.indexOf(suffix) > -1 || '*'===suffix.trim()) {
inWhiteList = true
break
}
}
if (!inWhiteList) {
return new Response( `${urlTarget.hostname} not in white list`, {status: 403} )
}
const response = await fetch(url, {
headers: request.headers,
body: request.body,
method: request.method
})
let respHeaders = {}
response.headers.forEach((value, key)=>respHeaders[key] = value)
if ('*'!==respHeaders['Access-Control-Allow-Origin']?.trim() && '*'!==respHeaders['access-control-allow-origin']?.trim()) {
respHeaders['Access-Control-Allow-Origin'] = '*'
}
return new Response( await response.body , {
headers: respHeaders,
status: response.status
})
}
addEventListener('fetch', event => {
return event.respondWith(handleRequest(event.request))
})
已知Bug:如果你反代带端口的url,例如http(s)://example.com:3000/path?query=string,它会自动去除端口再请求,变成请求http(s)://example.com/path?query=string