Skip to content

fix(service-worker): some fixes for real-world apps - #19519

Merged
alxhub merged 1 commit into
angular:masterfrom
alxhub:new-sw-fixes
Oct 5, 2017
Merged

alxhub merged 1 commit into
angular:masterfrom
alxhub:new-sw-fixes

Conversation

@alxhub

@alxhub alxhub commented Oct 2, 2017

Copy link
Copy Markdown
Member

No description provided.

@mary-poppins

Copy link
Copy Markdown

You can preview a09ae1f at https://pr19519-a09ae1f.ngbuilds.io/.

@mary-poppins

Copy link
Copy Markdown

You can preview 83ba832 at https://pr19519-83ba832.ngbuilds.io/.

@gkalpak gkalpak added the area: service-worker Issues related to the @angular/service-worker package label Oct 3, 2017

@gkalpak gkalpak left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The public API needs some changes.
(Also, how come there are no tests for the changes? 😕)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OOC, what is the purpose of this?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vestigial.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is supposed to only exclude /, then escaping is not necessary (since you are inside a character group): [^/]+.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I don't mind being explicit about it though :)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not directly related to this PR, but is it intentional that the generated RegExp will happily match a path as long as it can match a sub-path in it. For example, the RegExp for glob /foo/**/bar.js will match /baz/foo/qux/bar.js and /foo/qux/bar.jsx.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is intentional. ** means "0 or more directories", * means "1 directory".

@gkalpak gkalpak Oct 4, 2017 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was referring to the fact the two example paths (/baz/foo/qux/bar.js and /foo/qux/bar.jsx) would normally not be matched by the glob; the former because of the /baz prefix and the latter because of the x suffix (in .jsx). In both paths /foo/qux/bar.js would be matched, but it will only be a substring of the whole path.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh. Yes, that's expected. The expression is wrapped in^ and $ before being compiled. This function doesn't include those matchers because patterns need to be encoded into the manifest in an unwrapped state.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there other glob features supported that might need escaping (e.g. {...}, [...], ^)?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those are intentionally not handled for now. Long-term, I'd like to switch to use a glob-to-regex library that already exists.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

??

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need two of theses sha1 files? Is it for bundling purposes?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it's for build purposes. There's also a copy in Angular itself. :(

I want to extract it into a separate library at some point.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this need the this.bodyUsed = true; line?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The res.url !== '' part is redundant 😁

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed!

@gkalpak gkalpak Oct 3, 2017 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am a little confused with req.url vs getConfigUrl(req.url) 😕

For example, should line 450 below use url instead? Or what kind of URLs are used when initializing an AppVersion's hashTable (and if not "parsed" URLs, why not)?

https://github.com/alxhub/angular/blob/83ba8320e8937c5655d609cd2938295d724bec03/packages/service-worker/worker/src/app-version.ts#L54-L56

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue is that the config generator has no knowledge of which origin it will be running on. The SW knows its origin, but not whether requests will be made via HTTP or HTTPS.

Therefore there are two types of URLs tracked in the hashTable and other internal structures - fully qualified (with protocol, domain, and path for everything known at build time) and relative to the domain root (everything loaded from the same origin as the SW, and so not known at build time).

The URLs that come in Requests are always fully qualified. getConfigUrl will convert that fully-qualified URL to a domain-root-relative URL if the origin is the same as the SW. In other words, it determines for a given URL how it would be listed in the manifest.

In this case, it probably should use the config URL.

@mary-poppins

Copy link
Copy Markdown

You can preview f83e2e6 at https://pr19519-f83e2e6.ngbuilds.io/.

@mary-poppins

Copy link
Copy Markdown

You can preview 99c7768 at https://pr19519-99c7768.ngbuilds.io/.

@mary-poppins

Copy link
Copy Markdown

You can preview d639ad0 at https://pr19519-d639ad0.ngbuilds.io/.

@mary-poppins

Copy link
Copy Markdown

You can preview 5b3ca03 at https://pr19519-5b3ca03.ngbuilds.io/.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a Response, an error orundefined --> a Response or undefined (right?)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. Fixed.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is intentionally no await here, right?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. return foo; and return await foo; are identical.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think they are identical if this.scope.fetch(...) rejects 😕

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you mean debugLogB?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do indeed.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is origin guaranteed to end with a /? If not, then url would end up with a a double //.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is testing code, yes it is :)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this intentionally inside the while loop?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. It's only used for tests anyway - fixed.

@mary-poppins

Copy link
Copy Markdown

You can preview 86454df at https://pr19519-86454df.ngbuilds.io/.

@alxhub
alxhub force-pushed the new-sw-fixes branch 3 times, most recently from 5839d90 to 9be4f1d Compare October 5, 2017 15:35
@mary-poppins

Copy link
Copy Markdown

You can preview 5839d90 at https://pr19519-5839d90.ngbuilds.io/.

@mary-poppins

Copy link
Copy Markdown

You can preview 9be4f1d at https://pr19519-9be4f1d.ngbuilds.io/.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can't you console.error here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I try to avoid console logging for the SW - it's occasionally difficult to get to the SW debugging window. I prefer to expose debugging info via a special /ngsw/* URL namespace.

@IgorMinar IgorMinar left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgmt for api changes. please add tests as discussed in person.

This commit fixes several issues discovered through use in real apps.

* The sha1() function operated on text content, causing issues for binary-format files.
  A sha1Binary() function which operates on unparsed data now avoids any encoding issues.
* The characters '?' and '+' were not escaped in Glob-to-regex conversion previously, but
  are now.
* URLs from the browser contain the full origin, but were checked against the table of
  hashes from the manifest which only has the path for URLs from the same origin. Now the
  origin is checked and URLs are relativized to the domain root before comparison if
  appropriate.
* ngsw: prefix was missing from data groups, is now added.
* Occasionally servers will return a redirected response for an asset, and caching it could
  cause errors for navigation requests. The SW now handles this by detecting such responses
  and following the redirect manually, to avoid caching a redirected response.
* The request for known assets is now created from scratch from the URL before fetching from
  the network, in order to sanitize it and avoid carrying any special modes or headers that
  might result in opaque responses.
* Debugging log for troubleshooting.
* Avoid creating errors by returning 504 responses on error.
* Fix bug where idle queue doesn't run in some circumstances.
* Add tests for the above.
@mary-poppins

Copy link
Copy Markdown

You can preview bdeb92b at https://pr19519-bdeb92b.ngbuilds.io/.

@alxhub
alxhub merged commit f10f8db into angular:master Oct 5, 2017

private async safeFetch(req: Request): Promise<Response> {
try {
return this.scope.fetch(req);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAICT, this should also be return await this.scope.fetch(req).

@angular-automatic-lock-bot

Copy link
Copy Markdown

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot Bot locked and limited conversation to collaborators Sep 12, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area: service-worker Issues related to the @angular/service-worker package cla: yes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants