I have an angular app and as soon as I add a serviceWorker following these steps:
https://github.com/angular/angular-cli/blob/master/docs/documentation/build.md#service-worker https://angular.io/guide/service-worker-getting-started
…my API requests no longer have an Origin
request header, which seems to cause my API server to not return an Access-Control-Allow-Origin
response header, causing a browser error:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Simply removing the serviceWorker and unregistering it returns the behavior to normal.
How do I implement a serviceWorker while continuing to use my restful API?
All of the requests are affected but some are made "under the hood" by oidc-client
; all of the others look like:
public getBook(bookId: number): Observable<Book> {
const request = new HttpRequest(
'get',
`https://some-server.asurewebsites.net/api/book/${bookId}`,
{
reportProgress: true,
responseType: 'json'
}
);
return this.httpClient.request<any>(request).do(event => {
this.progressService.processEvent(event);
}).filter(event => event instanceof HttpResponse)
.map((response: HttpResponse<any>) => deserializeBook(response.body)).catch(error => {
if (error instanceof HttpErrorResponse) {
if (error.status === 404) {
return Observable.of(null);
}
}
return Observable.throw(error);
});
}
// note: other constraints require listening to progress from per-request level rather than using a HttpIntercepter.
Update1:
Manually setting Origin
I get:
Refused to set unsafe header "Origin"
Manually setting Access-Control-Allow-Origin
does nothing because it is a response header.
The Fetch API has a Request.mode
that when set to 'cors'
will send an OPTIONS
request with a Origin
header like normal. I'd try explicitly setting that but I'm having trouble researching or find the in the documentation how to set that with angular HttpClient
Update2:
I tried converting one of the requests to use the Fetch API. So I set Request.mode
to 'cors'
, but I still get no Origin
request header and no Access-Control-Allow-Origin
response header.
public getBookList(): Observable<BookList[]> {
const fetchHeaders = new Headers();
fetchHeaders.set('Authorization', 'Bearer ${token}');
const fetchRequest = new Request(`https://some-server.asurewebsites.net/api/book`, {
method: 'get',
headers: fetchHeaders,
mode: 'cors'
});
return Observable.fromPromise(fetch(fetchRequest).then(response => response.json()))
.map((results: any[]) => results.map(entity => deserializeBook(entity)));
}
TLDR
Once a service worker is registered the browser no longer uses CORS, even if mode: 'cors'
is explicitly set by the client. How do I use a service worker and CORS?
The reason for that is, as mentioned earlier in this answer, browsers always send the Origin header in all POST , PUT , PATCH , and DELETE requests. Also, for completeness here and to be clear: For navigations, browsers send no Origin header.
In short: you cannot. As described on MDN; Origin is a 'forbidden' header, meaning that you cannot change it programatically. You would need to configure the web server to allow CORS requests.
The Origin request header indicates the origin (scheme, hostname, and port) that caused the request. For example, if a user agent needs to request resources included in a page, or fetched by scripts that it executes, then the origin of the page may be included in the request.
" Origin: “null” is an invalid origin, and then get rejected by the server framework." if Origin in absent of the header, the request pass. if Origin is set to “null”, the request is rejected.
Go to the server that is hosting your API, and make the following change on the CORS configuration.
Change the allowed origin from this:
<AllowedOrigin>*</AllowedOrigin>
TO
<AllowedOrigin>http://*</AllowedOrigin>
<AllowedOrigin>https://*</AllowedOrigin>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With