- From: Arthur Stolyar <notifications@github.com>
- Date: Fri, 19 Aug 2016 15:41:38 -0700
- To: slightlyoff/ServiceWorker <ServiceWorker@noreply.github.com>
- Message-ID: <slightlyoff/ServiceWorker/issues/920/241153009@github.com>
_(My kind-of a proposal for this case, a bit rethinked/reworked)_
## The `requests`
This API is supposed to solve this issue and the race issue for `link=preload` https://github.com/slightlyoff/ServiceWorker/issues/959
### Preflight
First, here are some scetches of the _"pre-flight opt-in"_ which are based on what was writting here and decided on F2F meeting:
##### Registration, preflight is opt-in
Each preflight request will have `Service-Worker-Preflight: something` header.
```js
navigator.serviceWorker.register('/sw.js', {
preflight: {
// Preflight interval. Is it really needed?
// There was some mentions that HTTP cached would solve this.
// Will `Vary: Service-Worker-Preflight` on response work fine here? CDN?
ttl: 1000 * 60
}
});
```
##### Pre-flight data
```js
// Naming not final of course
self.registration.setPreflightProperties([
headers: {
'X-Status': 'Y'
}
]).then(() => {
console.log('Done');
});
```
This is what is related to preflight, following API is for general use cases which may solve Facebook/Google Docs issue with ServiceWorker.
### API
(_in TypeScript format, not spec format_)
```ts
interface RequestsStorage {
match(Request | string): Promise<Response>;
putUntil(Request | string, Promise<Response>): void;
}
interface ServiceWorkerGlobalScope {
readonly requests: RequestsStorage;
}
```
* `RequestsStorage#putUntil`: Puts a request to the storage until `Promise<Response>` settled.
_For the case of preflight, UA need to hold the request in the store until `fetch` event ends_
* `RequestsStorage#match`: Macthes passed request agains stored ones. Requests should be differentiated by `Service-Worker-Preflight` header too.
### Example
The website. It wants to preflight requests and wants to handle them differently based on the requested page. It also sends `Link` preload headers for some pages.
```js
self.addEventListener('fetch', event => {
const request = event.request;
const url = new URL(request.url);
// Detect if it's a preflight request
if (request.mode === 'navigate' && request.header.get('Service-Worker-Preflight')) {
let result;
// Note that self.request.match() should take into account
// existence of Service-Worker-Preflight header
// Case A: Construct the page on the fly (FB case)
if (url.pathname === '/newsfeed') {
result = self.requests.match(request).then(res => {
// `res` returns dynamic data, the shell is cached.
// Streaming rendering could be used here too
return constructThePage(res);
});
}
// Case B: Simple race with response for simple page
else if (url.pathname === '/about') {
const fetching = fetchRequest(request);
const result = Promise.race([
fetching,
self.requests.match(request).catch(() => fetching)
]);
}
// Case C: Canceling huge **response**
else if (url.pathname.endsWith('.mp4')) {
self.requests.match(request).then(res => {
res.body.cancel();
});
}
event.respondWith(result);
return;
}
// Handle normal and preload requests. They are going here too
// and if page requests same preload assets which are now _ingligh_
// then the same request is reused.
const result = self.requests.match(request).then(inflight => {
return inflight || self.caches.match(request);
}).then(res => {
if (res) return res;
return fetch(request).then(res => {
if (res && res.ok) {
putCache(request, res);
}
return res;
});
});
event.respondWith(result);
});
function fetchRequest(request) {
return caches.match(request, {
cacheName: 'cache'
}).then(res => {
if (res) return res;
return fetch(request).then(res => {
if (res && res.ok) {
putCache(request, res);
}
return res;
});
});
}
function putCache(req, res) {
return caches.open('cache').then(cache => {
return cache.put(req, res);
});
}
```
_____________________________
This is how I think it may work. I hope it isn't very stupud :-)
--
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/slightlyoff/ServiceWorker/issues/920#issuecomment-241153009
Received on Friday, 19 August 2016 22:42:07 UTC