首页 > 解决方案 > 是否可以将 Cloudflare Service Worker 用作代理 Web 服务器?

问题描述

这只是一个初学者级别的问题,寻求一些建议,以下可能由于缺乏知识而误用了一些关键术语,但希望可以将关键信息传递给大家:

背景:
我的公司在 AWS 上托管一个网站,一切正常,除了它无法在中国加载,因为众所周知的中国防火墙将阻止中国以外的所有未注册/未经许可的网站;最好的解决方案可能是在中国托管服务器并获得中国政府批准的 ICP 许可证,但这需要时间和许多其他因素。因此,我们现在正在寻找一些替代方案,让我们的中国客户能够阅读我们网站上的内容。

主要思想:
使用 Cloudflare Service Worker 先从给定的网页获取 HTTP 资源,然后通过 Service Worker 将 HTTP 内容发送给用户(因为 Cloudflare 在中国可以访问)

示例:
让 Cloudflare 注册的 Service Worker URL 为:sample.workers.dev
要服务的目标网站内容:google.com
当用户尝试访问此域(sample.workers.dev)时,Service Worker 应尝试加载所有 HTTP 内容,包括来自 google.com 的图片、脚本和 css 在后端,然后直接将 HTTP 内容返回给用户

这将适用于我公司的客户,因为我们通常会生成一个 url 并通过电子邮件或其他方式发送给用户,因此我们可以向他们发送一个在中国可访问的第三方 url,同时实际从我们的原始网站加载内容。

我已经尝试了 Cloudflare 给出的所有示例:https ://developers.cloudflare.com/workers/templates/ 但到目前为止,我还没有准确地归档我想要的内容。

有什么想法吗?

标签: node.jsservice-workerserverlessnodejs-streamcloudflare-workers

解决方案


是的,这是可能的。我记得 Cloudflare 的某个人将它作为示例来实现。

找到它:https ://github.com/lebinh/cloudflare-workers/blob/master/src/proxy.ts

但是,Cloudflare 工作人员现在确实支持流 API IIRC,因此有更好的方法来做到这一点。

/**
 * HTTP Proxy to arbitrary URL with Cloudflare Worker.
 */

/**
 * Cloudflare Worker entrypoint
 */
if (typeof addEventListener === 'function') {
    addEventListener('fetch', (e: Event): void => {
        // work around as strict typescript check doesn't allow e to be of type FetchEvent
        const fe = e as FetchEvent
        fe.respondWith(proxyRequest(fe.request))
    });
}

async function proxyRequest(r: Request): Promise<Response> {
    const url = new URL(r.url)
    const prefix = '/worker/proxy/'
    if (url.pathname.startsWith(prefix)) {
        const remainingUrl = url.pathname.replace(new RegExp('^' + prefix), '')
        let targetUrl = decodeURIComponent(remainingUrl)
        if (!targetUrl.startsWith('http://') && !targetUrl.startsWith('https://')) {
            targetUrl = url.protocol + '//' + targetUrl
        }
        return fetch(targetUrl)
    } else {
        return new Response('Bad Request', {status: 400, statusText: 'Bad Request'})
    }
}

interface FetchEvent extends Event {
    request: Request;

    respondWith(r: Promise<Response> | Response): Promise<Response>;
}

推荐阅读