如何禁用 Angular 服务工作者的预检缓存控制标头(调用事件流时)?

Posted

技术标签:

【中文标题】如何禁用 Angular 服务工作者的预检缓存控制标头(调用事件流时)?【英文标题】:How to disable preflight cache-control headers for Angular service-worker (when calling event stream)? 【发布时间】:2019-01-10 13:33:05 【问题描述】:

更新 2:请参阅下面的答案。 504错误已修复

更新:这似乎不是由于 cache-control 标头,尽管有错误。如果我禁用服务工作者,标题仍然存在。相反,这是由于服务工作者在 API 上导致了504 (Gateway Timeout)。知道如何解决这个问题吗?

我已经构建了一个完整的 MEAN-stack 应用程序,在我使用服务工作者之前它运行良好。

我得到的主要错误是

Failed to load $apiUrl Request header field Cache-Control is not allowed by Access-Control-Allow-Headers in preflight response.

我在尝试访问外部 API (api.particle.io) 时遇到此问题,我无法控制其 CORS 设置。

我尝试通过将 API url 添加到 dataGroups 来调整我的 ngsw-config.json,但到目前为止,这只会增加一个额外的错误:

Uncaught (in promise) TypeError: Failed to fetch ngsw-worker.js

这仅在尝试使用以下方式获取事件流时发生:

watchStatus(url: string): Observable<eventResponse> 
        return new Observable<eventResponse>(obs => 
            const source = new EventSource(url);
            source.addEventListener('status', (event) => 
                obs.next(JSON.parse(event.data).data);
            );
            return () => source.close();
        );
    

有没有办法用 observable 调用它?如果没有 EventSource,我无法让服务器发送的事件正常工作,但也许我做错了。

我的ngsw-config.json


  "index": "/index.html",
  "assetGroups": [
    "name": "app",
    "installMode": "prefetch",
    "resources": 
      "files": [
        "/favicon.ico",
        "/index.html",
        "/*.css",
        "/*.js"
      ]
    
  , 
    "name": "assets",
    "installMode": "lazy",
    "updateMode": "prefetch",
    "resources": 
      "files": [
        "/assets/**"
      ]
    
  , 
    "name": "fonts",
    "resources": 
      "urls": [
        "https://fonts.googleapis.com/**",
        "https://fonts.gstatic.com/**"
      ]
    
],
  "dataGroups": [
      
          "name": "photon-api",
          "urls": [
              "http://api.particle.io/**",
              "https://api.particle.io/**"
          ],
          "cacheConfig" : 
              "strategy": "freshness",
              "maxSize": 0,
              "maxAge": "0u"
          
      
  ]

是否可以禁用预检 Cache-Control 标头更改我的 ngsw-config.json

【问题讨论】:

【参考方案1】:

知道了!

我根据a github issue answer found here 修复了它。

基本上,服务人员使用onFetch 捕获所有内容。为了将我的 API URL 列入白名单,我打开了 ngsw-worker.js 并将 onFetch(event) 更改为:

onFetch(event) 
    const req = event.request;
    // List of words in request URL to whitelist/bypass the service worker
    const whitelist = ['api', 'otherWhitelistWords...']
    // Check to see if request url contains any whitelisted words and skip the rest of onFetch if it does
    if (whitelist.some(word => req.url.toLowerCase().includes(word.toLowerCase()))) 
                return
    
   ...

您可以通过创建fix-sw.sh 来自动修复ng build:prod

#!/bin/bash
sed -i "/onFetch(event) /,/const req = event.request;/c onFetch(event)const req=event.request;const whitelist=['api','otherWhitelistWords...'];if(whitelist.some(word=>req.url.toLowerCase().includes(word.toLowerCase())))return" ./dist/$PROJECTNAME/ngsw-worker.js

然后,在 package.json 中,将您的 build:prod 更改为:

"build:prod": "ng build --prod && bash ./fix-sw.sh",

【讨论】:

【参考方案2】:

您使用的是 Angular 6 吗?如果是,CLI 6 支持代理配置,它将代理您的后端 API。请检查这是否有帮助。

https://github.com/angular/angular-cli/blob/master/docs/documentation/stories/proxy.md

【讨论】:

我使用的是 v6。不幸的是,代理支持仅适用于 ng serve 而不是 ng build,这是使用 service worker 的地方。 您可以创建一个可以与外部 API 通信的代理 Web 服务器(即中间件)。您的移动应用程序可以访问中间件,它将返回来自外部 api 的响应

以上是关于如何禁用 Angular 服务工作者的预检缓存控制标头(调用事件流时)?的主要内容,如果未能解决你的问题,请参考以下文章

即使 Rails 服务器配置为接受所有请求,Angular 发布请求也未通过预检

对预检请求的响应未通过访问控制检查 - Angular 5 + JWT OAuth

如何从 C# WebApi 禁用对 MarkLogic 服务器的预检请求

如何禁用通过 IIS 提供的单页应用程序 HTML 文件的缓存?

ASP.NET Core Web API + Angular 对预检请求的响应未通过访问控制检查:预检请求不允许重定向

在禁用 Web 安全模式下运行的 chrome 中,对预检请求的响应未通过访问控制检查