kopia lustrzana https://gitlab.com/rysiekpl/libresilient
Subresource Integrity exposed to plugins from Service Worker
rodzic
0d5db7e2a0
commit
4f528a4123
|
@ -134,6 +134,62 @@ describe("plugin: alt-fetch", () => {
|
||||||
expect(response.url).toEqual('https://resilient.is/test.json')
|
expect(response.url).toEqual('https://resilient.is/test.json')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("it should pass the Request() init data to fetch() for all used endpoints", async () => {
|
||||||
|
|
||||||
|
init = {
|
||||||
|
name: 'alt-fetch',
|
||||||
|
endpoints: [
|
||||||
|
'https://alt.resilient.is/test.json',
|
||||||
|
'https://error.resilientis/test.json',
|
||||||
|
'https://timeout.resilientis/test.json',
|
||||||
|
'https://alt2.resilient.is/test.json',
|
||||||
|
'https://alt3.resilient.is/test.json',
|
||||||
|
'https://alt4.resilient.is/test.json'
|
||||||
|
]}
|
||||||
|
|
||||||
|
require("../../plugins/alt-fetch.js");
|
||||||
|
|
||||||
|
global.fetch.mockImplementation((url, init) => {
|
||||||
|
const response = new Response(
|
||||||
|
new Blob(
|
||||||
|
[JSON.stringify({ test: "success" })],
|
||||||
|
{type: "application/json"}
|
||||||
|
),
|
||||||
|
{
|
||||||
|
status: 200,
|
||||||
|
statusText: "OK",
|
||||||
|
headers: {
|
||||||
|
'ETag': 'TestingETagHeader'
|
||||||
|
},
|
||||||
|
url: url
|
||||||
|
});
|
||||||
|
return Promise.resolve(response);
|
||||||
|
});
|
||||||
|
|
||||||
|
var initTest = {
|
||||||
|
method: "GET",
|
||||||
|
headers: new Headers({"x-stub": "STUB"}),
|
||||||
|
mode: "mode-stub",
|
||||||
|
credentials: "credentials-stub",
|
||||||
|
cache: "cache-stub",
|
||||||
|
referrer: "referrer-stub",
|
||||||
|
// these are not implemented by service-worker-mock
|
||||||
|
// https://github.com/zackargyle/service-workers/blob/master/packages/service-worker-mock/models/Request.js#L20
|
||||||
|
redirect: undefined,
|
||||||
|
integrity: undefined,
|
||||||
|
cache: undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await LibResilientPluginConstructors.get('alt-fetch')(LR, init).fetch('https://resilient.is/test.json', initTest);
|
||||||
|
|
||||||
|
expect(fetch).toHaveBeenCalledTimes(3);
|
||||||
|
expect(fetch).toHaveBeenNthCalledWith(1, expect.stringContaining('/test.json'), initTest);
|
||||||
|
expect(fetch).toHaveBeenNthCalledWith(2, expect.stringContaining('/test.json'), initTest);
|
||||||
|
expect(fetch).toHaveBeenNthCalledWith(3, expect.stringContaining('/test.json'), initTest);
|
||||||
|
expect(await response.json()).toEqual({test: "success"})
|
||||||
|
expect(response.url).toEqual('https://resilient.is/test.json')
|
||||||
|
})
|
||||||
|
|
||||||
test("it should set the LibResilient headers", async () => {
|
test("it should set the LibResilient headers", async () => {
|
||||||
require("../../plugins/alt-fetch.js");
|
require("../../plugins/alt-fetch.js");
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,31 @@ describe("plugin: any-of", () => {
|
||||||
expect(response.url).toEqual('https://resilient.is/test.json')
|
expect(response.url).toEqual('https://resilient.is/test.json')
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("it should return data from fetch()", async () => {
|
||||||
|
require("../../plugins/any-of.js");
|
||||||
|
|
||||||
|
var initTest = {
|
||||||
|
method: "GET",
|
||||||
|
headers: new Headers({"x-stub": "STUB"}),
|
||||||
|
mode: "mode-stub",
|
||||||
|
credentials: "credentials-stub",
|
||||||
|
cache: "cache-stub",
|
||||||
|
referrer: "referrer-stub",
|
||||||
|
// these are not implemented by service-worker-mock
|
||||||
|
// https://github.com/zackargyle/service-workers/blob/master/packages/service-worker-mock/models/Request.js#L20
|
||||||
|
redirect: undefined,
|
||||||
|
integrity: undefined,
|
||||||
|
cache: undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await LibResilientPluginConstructors.get('any-of')(LR, init).fetch('https://resilient.is/test.json', initTest);
|
||||||
|
|
||||||
|
expect(fetch).toHaveBeenCalled();
|
||||||
|
expect(fetch).toHaveBeenCalledWith('https://resilient.is/test.json', initTest);
|
||||||
|
expect(await response.json()).toEqual({test: "success"})
|
||||||
|
expect(response.url).toEqual('https://resilient.is/test.json')
|
||||||
|
});
|
||||||
|
|
||||||
test("it should throw an error when HTTP status is >= 400", async () => {
|
test("it should throw an error when HTTP status is >= 400", async () => {
|
||||||
|
|
||||||
global.fetch.mockImplementation((url, init) => {
|
global.fetch.mockImplementation((url, init) => {
|
||||||
|
|
|
@ -3,7 +3,9 @@ const makeServiceWorkerEnv = require('service-worker-mock');
|
||||||
global.fetch = require('node-fetch');
|
global.fetch = require('node-fetch');
|
||||||
jest.mock('node-fetch')
|
jest.mock('node-fetch')
|
||||||
|
|
||||||
global.fetch.mockImplementation((url, init) => {
|
describe("plugin: fetch", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
global.fetch.mockImplementation((url, init) => {
|
||||||
const response = new Response(
|
const response = new Response(
|
||||||
new Blob(
|
new Blob(
|
||||||
[JSON.stringify({ test: "success" })],
|
[JSON.stringify({ test: "success" })],
|
||||||
|
@ -20,8 +22,6 @@ global.fetch.mockImplementation((url, init) => {
|
||||||
return Promise.resolve(response);
|
return Promise.resolve(response);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("plugin: fetch", () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
Object.assign(global, makeServiceWorkerEnv());
|
Object.assign(global, makeServiceWorkerEnv());
|
||||||
jest.resetModules();
|
jest.resetModules();
|
||||||
global.LibResilientPluginConstructors = new Map()
|
global.LibResilientPluginConstructors = new Map()
|
||||||
|
@ -31,6 +31,7 @@ describe("plugin: fetch", () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
test("it should register in LibResilientPluginConstructors", () => {
|
test("it should register in LibResilientPluginConstructors", () => {
|
||||||
require("../../plugins/fetch.js");
|
require("../../plugins/fetch.js");
|
||||||
expect(LibResilientPluginConstructors.get('fetch')().name).toEqual('fetch');
|
expect(LibResilientPluginConstructors.get('fetch')().name).toEqual('fetch');
|
||||||
|
@ -46,6 +47,30 @@ describe("plugin: fetch", () => {
|
||||||
expect(response.url).toEqual('https://resilient.is/test.json')
|
expect(response.url).toEqual('https://resilient.is/test.json')
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("it should pass the Request() init data to fetch()", async () => {
|
||||||
|
require("../../plugins/fetch.js");
|
||||||
|
|
||||||
|
var initTest = {
|
||||||
|
method: "GET",
|
||||||
|
headers: new Headers({"x-stub": "STUB"}),
|
||||||
|
mode: "mode-stub",
|
||||||
|
credentials: "credentials-stub",
|
||||||
|
cache: "cache-stub",
|
||||||
|
referrer: "referrer-stub",
|
||||||
|
// these are not implemented by service-worker-mock
|
||||||
|
// https://github.com/zackargyle/service-workers/blob/master/packages/service-worker-mock/models/Request.js#L20
|
||||||
|
redirect: undefined,
|
||||||
|
integrity: undefined,
|
||||||
|
cache: undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await LibResilientPluginConstructors.get('fetch')(LR).fetch('https://resilient.is/test.json', initTest);
|
||||||
|
|
||||||
|
expect(fetch).toHaveBeenCalledWith('https://resilient.is/test.json', initTest);
|
||||||
|
expect(await response.json()).toEqual({test: "success"})
|
||||||
|
expect(response.url).toEqual('https://resilient.is/test.json')
|
||||||
|
});
|
||||||
|
|
||||||
test("it should set the LibResilient headers", async () => {
|
test("it should set the LibResilient headers", async () => {
|
||||||
require("../../plugins/fetch.js");
|
require("../../plugins/fetch.js");
|
||||||
|
|
||||||
|
|
|
@ -169,6 +169,76 @@ describe("service-worker", () => {
|
||||||
expect(await response.json()).toEqual({ test: "success" })
|
expect(await response.json()).toEqual({ test: "success" })
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("plugins should receive the Request() init data", async () => {
|
||||||
|
self.LibResilientConfig = {
|
||||||
|
plugins: [{
|
||||||
|
name: 'reject-all'
|
||||||
|
},{
|
||||||
|
name: 'resolve-all'
|
||||||
|
}],
|
||||||
|
loggedComponents: [
|
||||||
|
'service-worker'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
let rejectingFetch = jest.fn((request, init)=>{ return Promise.reject(request); })
|
||||||
|
let resolvingFetch = jest.fn((request, init)=>{
|
||||||
|
return Promise.resolve(
|
||||||
|
new Response(
|
||||||
|
new Blob(
|
||||||
|
[JSON.stringify({ test: "success" })],
|
||||||
|
{type: "application/json"}
|
||||||
|
),
|
||||||
|
{
|
||||||
|
status: 200,
|
||||||
|
statusText: "OK",
|
||||||
|
headers: {
|
||||||
|
'ETag': 'TestingETagHeader'
|
||||||
|
},
|
||||||
|
url: self.location.origin + '/test.json'
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
global.LibResilientPluginConstructors.set('reject-all', ()=>{
|
||||||
|
return {
|
||||||
|
name: 'reject-all',
|
||||||
|
description: 'Reject all requests.',
|
||||||
|
version: '0.0.1',
|
||||||
|
fetch: rejectingFetch
|
||||||
|
}
|
||||||
|
})
|
||||||
|
global.LibResilientPluginConstructors.set('resolve-all', ()=>{
|
||||||
|
return {
|
||||||
|
name: 'resolve-all',
|
||||||
|
description: 'Resolve all requests.',
|
||||||
|
version: '0.0.1',
|
||||||
|
fetch: resolvingFetch
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
var initTest = {
|
||||||
|
method: "GET",
|
||||||
|
headers: new Headers({"x-stub": "STUB"}),
|
||||||
|
mode: "mode-stub",
|
||||||
|
credentials: "credentials-stub",
|
||||||
|
cache: "cache-stub",
|
||||||
|
referrer: "referrer-stub",
|
||||||
|
// these are not implemented by service-worker-mock
|
||||||
|
// https://github.com/zackargyle/service-workers/blob/master/packages/service-worker-mock/models/Request.js#L20
|
||||||
|
redirect: undefined,
|
||||||
|
integrity: undefined,
|
||||||
|
cache: undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
require("../service-worker.js");
|
||||||
|
|
||||||
|
var response = await self.trigger('fetch', new Request('/test.json', initTest))
|
||||||
|
expect(rejectingFetch).toHaveBeenCalled();
|
||||||
|
expect(resolvingFetch).toHaveBeenCalled();
|
||||||
|
expect(await response.json()).toEqual({ test: "success" })
|
||||||
|
expect(rejectingFetch).toHaveBeenCalledWith('https://www.test.com/test.json', initTest)
|
||||||
|
expect(resolvingFetch).toHaveBeenCalledWith('https://www.test.com/test.json', initTest)
|
||||||
|
});
|
||||||
|
|
||||||
test("defaultPluginTimeout should be respected", async () => {
|
test("defaultPluginTimeout should be respected", async () => {
|
||||||
jest.useFakeTimers()
|
jest.useFakeTimers()
|
||||||
self.LibResilientConfig = {
|
self.LibResilientConfig = {
|
||||||
|
@ -575,6 +645,110 @@ describe("service-worker", () => {
|
||||||
})).toEqual({ test: "success" })
|
})).toEqual({ test: "success" })
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("after a retrieval from a stashing plugin, background plugin should receive the Request() init data", async () => {
|
||||||
|
self.LibResilientConfig = {
|
||||||
|
plugins: [{
|
||||||
|
name: 'stashing-test'
|
||||||
|
},{
|
||||||
|
name: 'resolve-all'
|
||||||
|
}],
|
||||||
|
loggedComponents: [
|
||||||
|
'service-worker'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
let resolvingFetch = jest.fn((request, init)=>{
|
||||||
|
return Promise.resolve(
|
||||||
|
new Response(
|
||||||
|
new Blob(
|
||||||
|
[JSON.stringify({ test: "success" })],
|
||||||
|
{type: "application/json"}
|
||||||
|
),
|
||||||
|
{
|
||||||
|
status: 200,
|
||||||
|
statusText: "OK",
|
||||||
|
headers: {
|
||||||
|
'X-LibResilient-Method': 'resolve-all',
|
||||||
|
'X-LibResilient-ETag': 'TestingETagHeader'
|
||||||
|
},
|
||||||
|
url: self.location.origin + '/test.json'
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
let resolvingFetch2 = jest.fn((request, init)=>{
|
||||||
|
return Promise.resolve(
|
||||||
|
new Response(
|
||||||
|
new Blob(
|
||||||
|
[JSON.stringify({ test: "success2" })],
|
||||||
|
{type: "application/json"}
|
||||||
|
),
|
||||||
|
{
|
||||||
|
status: 200,
|
||||||
|
statusText: "OK",
|
||||||
|
headers: {
|
||||||
|
'ETag': 'NewTestingETagHeader'
|
||||||
|
},
|
||||||
|
url: self.location.origin + '/test.json'
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
let stashingStash = jest.fn(async (response, url)=>{
|
||||||
|
expect(await response.json()).toEqual({ test: "success2" })
|
||||||
|
expect(response.headers.get('ETag')).toEqual('NewTestingETagHeader')
|
||||||
|
})
|
||||||
|
|
||||||
|
global.LibResilientPluginConstructors.set('stashing-test', ()=>{
|
||||||
|
return {
|
||||||
|
name: 'stashing-test',
|
||||||
|
description: 'Mock stashing plugin.',
|
||||||
|
version: '0.0.1',
|
||||||
|
fetch: resolvingFetch,
|
||||||
|
stash: stashingStash
|
||||||
|
}
|
||||||
|
})
|
||||||
|
global.LibResilientPluginConstructors.set('resolve-all', ()=>{
|
||||||
|
return {
|
||||||
|
name: 'resolve-all',
|
||||||
|
description: 'Resolve all requests.',
|
||||||
|
version: '0.0.1',
|
||||||
|
fetch: resolvingFetch2
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
var testClient = new Client()
|
||||||
|
self.clients.clients.push(testClient)
|
||||||
|
var fetchedDiffersFound = false
|
||||||
|
testClient.addEventListener('message', event => {
|
||||||
|
if (event.data.fetchedDiffers) {
|
||||||
|
fetchedDiffersFound = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
require("../service-worker.js");
|
||||||
|
|
||||||
|
var initTest = {
|
||||||
|
method: "GET",
|
||||||
|
headers: new Headers({"x-stub": "STUB"}),
|
||||||
|
mode: "mode-stub",
|
||||||
|
credentials: "credentials-stub",
|
||||||
|
cache: "cache-stub",
|
||||||
|
referrer: "referrer-stub",
|
||||||
|
// these are not implemented by service-worker-mock
|
||||||
|
// https://github.com/zackargyle/service-workers/blob/master/packages/service-worker-mock/models/Request.js#L20
|
||||||
|
redirect: undefined,
|
||||||
|
integrity: undefined,
|
||||||
|
cache: undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
var response = await self.trigger('fetch', {
|
||||||
|
request: new Request('/test.json', initTest),
|
||||||
|
clientId: testClient.id
|
||||||
|
})
|
||||||
|
expect(resolvingFetch).toHaveBeenCalled();
|
||||||
|
expect(await response.json()).toEqual({ test: "success" })
|
||||||
|
expect(resolvingFetch).toHaveBeenCalledWith('https://www.test.com/test.json', initTest);
|
||||||
|
expect(resolvingFetch2).toHaveBeenCalledWith('https://www.test.com/test.json', initTest);
|
||||||
|
});
|
||||||
|
|
||||||
test("unstashing content explicitly should work", async () => {
|
test("unstashing content explicitly should work", async () => {
|
||||||
self.LibResilientConfig = {
|
self.LibResilientConfig = {
|
||||||
plugins: [{
|
plugins: [{
|
||||||
|
|
|
@ -62,12 +62,16 @@
|
||||||
/**
|
/**
|
||||||
* getting content using regular HTTP(S) fetch()
|
* getting content using regular HTTP(S) fetch()
|
||||||
*/
|
*/
|
||||||
let fetchContentFromAlternativeEndpoints = (url) => {
|
let fetchContentFromAlternativeEndpoints = (url, init={}) => {
|
||||||
|
|
||||||
// we're going to try a random endpoint and building an URL of the form:
|
// we're going to try a random endpoint and building an URL of the form:
|
||||||
// https://<endpoint_address>/<pubkey>/<rest_of_URL>
|
// https://<endpoint_address>/<pubkey>/<rest_of_URL>
|
||||||
var path = url.replace(/https?:\/\/[^/]+\//, '')
|
var path = url.replace(/https?:\/\/[^/]+\//, '')
|
||||||
|
|
||||||
|
// we really want to make fetch happen, Regina!
|
||||||
|
// TODO: this change should *probably* be handled on the Service Worker level
|
||||||
|
init.cache = 'reload'
|
||||||
|
|
||||||
// we don't want to modify the original endpoints array
|
// we don't want to modify the original endpoints array
|
||||||
var sourceEndpoints = [...config.endpoints]
|
var sourceEndpoints = [...config.endpoints]
|
||||||
|
|
||||||
|
@ -91,7 +95,7 @@
|
||||||
|
|
||||||
return Promise.any(
|
return Promise.any(
|
||||||
useEndpoints.map(
|
useEndpoints.map(
|
||||||
u=>fetch(u, {cache: "reload"})
|
u=>fetch(u, init)
|
||||||
))
|
))
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
// 4xx? 5xx? that's a paddlin'
|
// 4xx? 5xx? that's a paddlin'
|
||||||
|
|
|
@ -32,10 +32,10 @@
|
||||||
/**
|
/**
|
||||||
* getting content using regular HTTP(S) fetch()
|
* getting content using regular HTTP(S) fetch()
|
||||||
*/
|
*/
|
||||||
let fetchContent = (url) => {
|
let fetchContent = (url, init={}) => {
|
||||||
LR.log(pluginName, `using: [${config.uses.map(p=>p.name).join(', ')}]!`)
|
LR.log(pluginName, `using: [${config.uses.map(p=>p.name).join(', ')}]!`)
|
||||||
return Promise.any(
|
return Promise.any(
|
||||||
config.uses.map(p=>p.fetch(url))
|
config.uses.map(p=>p.fetch(url, init))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
/**
|
/**
|
||||||
* getting content from cache
|
* getting content from cache
|
||||||
*/
|
*/
|
||||||
let getContentFromCache = (url) => {
|
let getContentFromCache = (url, init={}) => {
|
||||||
LR.log(pluginName, `getting from cache: ${url}`)
|
LR.log(pluginName, `getting from cache: ${url}`)
|
||||||
return caches.open('v1')
|
return caches.open('v1')
|
||||||
.then((cache) => {
|
.then((cache) => {
|
||||||
|
|
|
@ -24,9 +24,13 @@
|
||||||
/**
|
/**
|
||||||
* getting content using regular HTTP(S) fetch()
|
* getting content using regular HTTP(S) fetch()
|
||||||
*/
|
*/
|
||||||
let fetchContent = (url) => {
|
let fetchContent = (url, init={}) => {
|
||||||
LR.log(pluginName, `regular fetch: ${url}`)
|
LR.log(pluginName, `regular fetch: ${url}`)
|
||||||
return fetch(url, {cache: "reload"})
|
// we really want to make fetch happen, Regina!
|
||||||
|
// TODO: this change should *probably* be handled on the Service Worker level
|
||||||
|
init.cache = 'reload'
|
||||||
|
// run built-in regular fetch()
|
||||||
|
return fetch(url, init)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
// 4xx? 5xx? that's a paddlin'
|
// 4xx? 5xx? that's a paddlin'
|
||||||
if (response.status >= 400) {
|
if (response.status >= 400) {
|
||||||
|
|
|
@ -165,7 +165,7 @@ if (typeof window === 'undefined') {
|
||||||
/**
|
/**
|
||||||
* the workhorse of this plugin
|
* the workhorse of this plugin
|
||||||
*/
|
*/
|
||||||
async function getContentFromGunAndIPFS(url) {
|
async function getContentFromGunAndIPFS(url, init={}) {
|
||||||
|
|
||||||
await setup_gun_ipfs();
|
await setup_gun_ipfs();
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,7 @@
|
||||||
/**
|
/**
|
||||||
* the workhorse of this plugin
|
* the workhorse of this plugin
|
||||||
*/
|
*/
|
||||||
async function getContentFromIPNSAndIPFS(url) {
|
async function getContentFromIPNSAndIPFS(url, init={}) {
|
||||||
return new Error("Not implemented yet.")
|
return new Error("Not implemented yet.")
|
||||||
|
|
||||||
var urlArray = url.replace(/https?:\/\//, '').split('/')
|
var urlArray = url.replace(/https?:\/\//, '').split('/')
|
||||||
|
|
|
@ -398,15 +398,35 @@ let LibResilientResourceInfo = class {
|
||||||
|* === Main Brain of LibResilient === *|
|
|* === Main Brain of LibResilient === *|
|
||||||
\* ========================================================================= */
|
\* ========================================================================= */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* generate Request()-compatible init object from an existing Request
|
||||||
|
*
|
||||||
|
* req - the request to work off of
|
||||||
|
*/
|
||||||
|
let initFromRequest = (req) => {
|
||||||
|
return {
|
||||||
|
method: req.method,
|
||||||
|
headers: req.headers,
|
||||||
|
mode: req.mode,
|
||||||
|
credentials: req.credentials,
|
||||||
|
cache: req.cache,
|
||||||
|
redirect: req.redirect,
|
||||||
|
referrer: req.referrer,
|
||||||
|
integrity: req.integrity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* run a plugin's fetch() method
|
* run a plugin's fetch() method
|
||||||
* while handling all the auxiliary stuff like saving info in reqInfo
|
* while handling all the auxiliary stuff like saving info in reqInfo
|
||||||
*
|
*
|
||||||
* plugin - the plugin to use
|
* plugin - the plugin to use
|
||||||
* url - string containing the URL to fetch
|
* url - string containing the URL to fetch
|
||||||
|
* init - Request() initialization parameters
|
||||||
* reqInfo - instance of LibResilientResourceInfo
|
* reqInfo - instance of LibResilientResourceInfo
|
||||||
*/
|
*/
|
||||||
let libresilientFetch = (plugin, url, reqInfo) => {
|
let libresilientFetch = (plugin, url, init, reqInfo) => {
|
||||||
|
|
||||||
// status of the plugin
|
// status of the plugin
|
||||||
reqInfo.update({
|
reqInfo.update({
|
||||||
|
@ -416,11 +436,13 @@ let libresilientFetch = (plugin, url, reqInfo) => {
|
||||||
|
|
||||||
// log stuff
|
// log stuff
|
||||||
self.log('service-worker', "LibResilient Service Worker handling URL:", url,
|
self.log('service-worker', "LibResilient Service Worker handling URL:", url,
|
||||||
'\n+-- using method(s):', plugin.name)
|
'\n+-- init:', Object.getOwnPropertyNames(init).map(p=>`\n - ${p}: ${init[p]}`).join(''),
|
||||||
|
'\n+-- using method(s):', plugin.name
|
||||||
|
)
|
||||||
|
|
||||||
// race the plugin(s) vs. a timeout
|
// race the plugin(s) vs. a timeout
|
||||||
return Promise.race([
|
return Promise.race([
|
||||||
plugin.fetch(url),
|
plugin.fetch(url, init),
|
||||||
promiseTimeout(
|
promiseTimeout(
|
||||||
self.LibResilientConfig.defaultPluginTimeout,
|
self.LibResilientConfig.defaultPluginTimeout,
|
||||||
false,
|
false,
|
||||||
|
@ -464,6 +486,9 @@ let getResourceThroughLibResilient = (request, clientId, useStashed=true, doStas
|
||||||
// clean the URL, removing any fragment identifier
|
// clean the URL, removing any fragment identifier
|
||||||
var url = request.url.replace(/#.+$/, '');
|
var url = request.url.replace(/#.+$/, '');
|
||||||
|
|
||||||
|
// get the init object from Request
|
||||||
|
var init = initFromRequest(request)
|
||||||
|
|
||||||
// set-up reqInfo for the fetch event
|
// set-up reqInfo for the fetch event
|
||||||
var reqInfo = new LibResilientResourceInfo(url, clientId)
|
var reqInfo = new LibResilientResourceInfo(url, clientId)
|
||||||
|
|
||||||
|
@ -503,14 +528,14 @@ let getResourceThroughLibResilient = (request, clientId, useStashed=true, doStas
|
||||||
state: "error",
|
state: "error",
|
||||||
fetchError: error.toString()
|
fetchError: error.toString()
|
||||||
})
|
})
|
||||||
return libresilientFetch(currentPlugin, url, reqInfo)
|
return libresilientFetch(currentPlugin, url, init, reqInfo)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// this libresilientFetch() will run first
|
// this libresilientFetch() will run first
|
||||||
// all other promises generated by LibResilientPlugins[] will be chained on it
|
// all other promises generated by LibResilientPlugins[] will be chained on it
|
||||||
// using the catch() in reduce() above
|
// using the catch() in reduce() above
|
||||||
// skipping this very first plugin by way of slice(1)
|
// skipping this very first plugin by way of slice(1)
|
||||||
libresilientFetch(LibResilientPluginsRun[0], url, reqInfo)
|
libresilientFetch(LibResilientPluginsRun[0], url, init, reqInfo)
|
||||||
)
|
)
|
||||||
.then((response)=>{
|
.then((response)=>{
|
||||||
// we got a successful response
|
// we got a successful response
|
||||||
|
@ -532,6 +557,7 @@ let getResourceThroughLibResilient = (request, clientId, useStashed=true, doStas
|
||||||
self.log('service-worker', 'starting background no-stashed fetch for:', url);
|
self.log('service-worker', 'starting background no-stashed fetch for:', url);
|
||||||
// event.waitUntil?
|
// event.waitUntil?
|
||||||
// https://stackoverflow.com/questions/37902441/what-does-event-waituntil-do-in-service-worker-and-why-is-it-needed/37906330#37906330
|
// https://stackoverflow.com/questions/37902441/what-does-event-waituntil-do-in-service-worker-and-why-is-it-needed/37906330#37906330
|
||||||
|
// TODO: perhaps don't use the `request` again? some wrapper?
|
||||||
getResourceThroughLibResilient(request, clientId, false, true, response.clone()).catch((e)=>{
|
getResourceThroughLibResilient(request, clientId, false, true, response.clone()).catch((e)=>{
|
||||||
self.log('service-worker', 'background no-stashed fetch failed for:', url);
|
self.log('service-worker', 'background no-stashed fetch failed for:', url);
|
||||||
})
|
})
|
||||||
|
|
Ładowanie…
Reference in New Issue