如何禁用 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 文件的缓存?