跨域ServiceWorker负载平衡

时间:2020-05-11 18:39:30

标签: javascript service-worker

我正在尝试使用ServiceWorker API来实现跨域负载平衡之类的smth。

我的概念是:

  1. 安装了提取事件的每个请求后,我尝试访问主域(https://example.com/
  2. 如果成功,我应该像event.respondWith(__response)一样将其退还给用户。
  3. 如果失败(超时或任何其他异常),我向其他服务器(https://balancer.com/)发出CORS请求,该服务器返回其他可访问域(https://mirror1.example.com)并重定向浏览器;

我被困在重定向步骤((( 所以我当前的代码在这里

self.oninstall = function (event) {
    event.waitUntil(self.skipWaiting());
};

self.onactivate = function (event) {
    event.waitUntil(self.clients.claim());
};

self.initialUrl = false;
self.onfetch = async function (event) {
    if (!self.initialUrl)
        self.initialUrl = event.request.url;


    if (self.initialUrl) {
        event.respondWith(self.tryAccess(event))
    } else {
        event.respondWith(fetch(event.request));
    }
};

self.tryAccess = async (event) => {
    return new Promise(async (resolve, reject) => {
        self.clients
            .matchAll({type: 'window'})
            .then(async (clients) => {
                for (var i in clients) {
                    var _c = clients[0];
                    if (_c.url === event.request.url) {
                        try {
                            let __tryResponse = await fetch(event.request);
                            resolve(__tryResponse);
                            return;
                        } catch (e) {
                            let __json = await (await fetch("https://balancer.com/")).json();
                            return _c.navigate(__json.path).then(client => client.focus());
                        }
                    } else {
                        resolve();
                    }
                }
            });
    });
};

1 个答案:

答案 0 :(得分:0)

获取对WindowClient的引用并从fetch处理程序内部强行更改其URL是重定向的正确方法。

相反,在fetch处理程序内部,您可以使用Response.redirect()创建的重定向响应进行响应。从浏览器的角度来看,这将与可能源自服务器的任何其他重定向一样对待。

要注意的一件事是,如果最初通过相同来源的URL请求子资源而导致重定向到跨来源响应,则可能会遇到一些问题。如果您最初的请求是针对跨域URL,并且您的潜在重定向也针对跨域URL,那么我认为您会没事的。

self.addEventListener('fetch', (event) => {
  const fetchWithRedirection = async () => {
    try {
      // Use fetch(), caches.match(), etc. to get a response.
      const response = await ...;

      // Optional: also check response.ok, but that
      // will always be false for opaque responses.
      if (response) {
        return response;
      }

      // If we don't have a valid response, trigger catch().
      throw new Error('Unable to get a response.');
    } catch (error) {
      // Use whatever logic you need to get the redirection URL.
      const redirectionURL = await ...;

      if (redirectionURL) {
        // HTTP 302 indicates a temporary redirect.
        return Response.redirect(redirectionURL, 302);
      }

      // If we get to this point, redirection isn't possible,
      // so just trigger a NetworkError.
      throw error;
    }
  };

  // You will probably want to wrap this in an if() to ensure
  // that it's a request that you want to handle with redirection.
  if (/* some routing criteria */) {
    event.respondWith(fetchWithRedirection());
  } else {
    // Optionally use different response generation logic.
    // Or just don't call event.respondWith(), and the
    // browser will proceed without service worker involvement.
  }
});