15

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)));
}

enter image description here

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?

Wilhelmina Lohan
  • 2,803
  • 2
  • 29
  • 58
  • did you try adding 'Access-Control-Allow-Origin' in the request header like “Access-Control-Allow-Origin”, “*” – VithuBati Jan 06 '18 at 01:25
  • It would help if you added your request code to the question — but regardless, try making the requests using the Fetch API directly, and manually constructing the request object with `mode: 'cors'` specified – sideshowbarker Jan 06 '18 at 02:37
  • @VithuBati isn't `Access-Control-Allow-Origin` a response header not a request header? – Wilhelmina Lohan Jan 08 '18 at 16:28
  • @sideshowbarker some request are made with 3rd party libraries and some with `HttpClient`. I didn't think the request code was relevant when all of the requests work w/o a service worker installed and all of them no longer have a header normally added by the browser once the a service work is registered. I will update the with examples though. – Wilhelmina Lohan Jan 08 '18 at 16:34
  • @sideshowbarker I'm having trouble researching how to set the `mode: 'cors'` with angular HttpClient – Wilhelmina Lohan Jan 08 '18 at 18:49
  • I don’t know if/how the request mode can be set with angular HttpClient. Is there a reason you can’t instead use the Fetch API directly? – sideshowbarker Jan 08 '18 at 22:12
  • @sideshowbarker it'd be a lot of work, HttpClient is used though out the app and we depend on the HttpInterceptor API to add Authorization header and query strings that are based on the app state, but i'll test one request using Fetch API to see if it works. – Wilhelmina Lohan Jan 08 '18 at 23:04
  • @sideshowbarker doesn't work. – Wilhelmina Lohan Jan 09 '18 at 01:02
  • About the responses that lack the `Access-Control-Allow-Origin` response header, are the HTTP status codes 2xx? – sideshowbarker Jan 09 '18 at 01:48
  • https://stackoverflow.com/questions/44800431/caching-effect-on-cors-no-access-control-allow-origin-header-is-present-on-th/45081016#45081016 may or may not be relevant. See also https://fetch.spec.whatwg.org/#cors-protocol-and-http-caches – sideshowbarker Jan 09 '18 at 16:59
  • I experienced this again, strangely it is resolved by longing out and back in to my OS (stopping all chrome processes) with out publishing or any changes to the service worker config. – Wilhelmina Lohan Aug 01 '18 at 19:06

1 Answers1

1

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>
Leon Grin
  • 889
  • 8
  • 10
  • Everything we do is https, can I just have that? What is the explanation / do you know why this works? – Wilhelmina Lohan Sep 25 '20 at 16:29
  • So you could set your AllowedOrigin to: https://www.example.com https://* Example.com being your domain. I use AWS. Here is some discussion about this issue on AWS Developer Forums => https://forums.aws.amazon.com/message.jspa?messageID=519678#519678 AWS changed the original behavior of echoing the requesting domain if * is being used for AllowedOrigin. – Leon Grin Sep 26 '20 at 18:37