Skip to content

Commit

Permalink
baseURL from scope or origin
Browse files Browse the repository at this point in the history
  • Loading branch information
fabiancook committed Dec 3, 2023
1 parent 82a387d commit 8014253
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 44 deletions.
21 changes: 2 additions & 19 deletions src/tests/worker/service-worker/routes.example.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,8 @@
import {FetchEvent} from "../../../fetch";
import {isRouteMatchCondition, RouterRule} from "../../../worker/service-worker/router";
import {isRouteMatchCondition, RouterRule, URLPatternInit} from "../../../worker/service-worker/router";
import {DurableServiceWorkerScope} from "../../../worker/service-worker/types";
import {URLPattern} from "urlpattern-polyfill";

export interface URLPatternInit {
baseURL?: string;
username?: string;
password?: string;
protocol?: string;
hostname?: string;
port?: string;
pathname?: string;
search?: string;
hash?: string;
}

declare var self: DurableServiceWorkerScope;

export type RouterRequestMethodLower = "get" | "put" | "post" | "delete" | "options" | "patch"
Expand Down Expand Up @@ -54,14 +42,9 @@ function makeAddRequestMethodRouteAndHandler(requestMethod: RouterRequestMethodL

function addRequestMethodRouteAndHandler(
requestMethod: string,
pathnameOrInit: string | URLPatternInit,
urlPattern: string | URLPatternInit,
onRequest: OnRequestFn
) {
const urlPattern = new URLPattern(
typeof pathnameOrInit === "string" ? {
pathname: pathnameOrInit
} : pathnameOrInit
);
const rule: RouterRule = {
condition: [
{
Expand Down
15 changes: 15 additions & 0 deletions src/worker/service-worker/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {addEventListener} from "../../events/schedule/schedule";
import {dispatchEvent} from "../../events";
import {DurablePeriodicSyncManager} from "../../periodic-sync";
import {getInternalStorageBucket, InternalBucket} from "../../storage-buckets/internal";
import {getOrigin} from "../../listen";

export type DurableServiceWorkerRegistrationState = "pending" | "installing" | "installed" | "activating" | "activated";

Expand All @@ -18,6 +19,8 @@ export interface DurableServiceWorkerRegistrationData {
registeredAt: string;
initialUrl: string;
url: string;
origin: string;
baseURL: string;
options?: RegistrationOptions;
}

Expand Down Expand Up @@ -265,6 +268,16 @@ export class DurableServiceWorkerContainer {
}
return instance;
}
const workerOrigin = instance.protocol === "file:" ?
getOrigin() :
instance.origin;
const origin = options?.scope ?
new URL(options.scope, workerOrigin).origin :
workerOrigin;
const baseURL = options?.scope ?
new URL(options.scope, origin).toString() :
new URL(url, origin).toString();

const registeredAt = new Date().toISOString();
const registration: DurableServiceWorkerRegistrationData = {
serviceWorkerId,
Expand All @@ -274,6 +287,8 @@ export class DurableServiceWorkerContainer {
registrationStateAt: registeredAt,
initialUrl: url.toString(),
url: instance.toString(),
origin,
baseURL,
options
};
await store.set(serviceWorkerId, registration);
Expand Down
78 changes: 53 additions & 25 deletions src/worker/service-worker/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,18 @@ export type RouterSourceEnum = "network" | "cache" | "fetch-event" | "race-netwo
export type RunningStatusEnum = "running" | "stopped";
export type RouterSourceBehaviorEnum = "finish-with-success" | "continue-discarding-latter-results";

export interface URLPatternInit {
baseURL?: string;
username?: string;
password?: string;
protocol?: string;
hostname?: string;
port?: string;
pathname?: string;
search?: string;
hash?: string;
}

export interface RouterSource {
type: RouterSourceEnum;
behaviorEnum?: RouterSourceBehaviorEnum;
Expand All @@ -23,15 +35,15 @@ export interface RouterNetworkSource extends RouterSource {

export interface RouterCacheSource extends RouterSource {
cacheName?: string;
request?: Request;
request?: RequestInfo;
}

export interface RouterFetchEventSource extends RouterSource {
id?: string;
}

export interface RouterURLPatternCondition {
urlPattern: URLPattern | string;
urlPattern: URLPattern | string | URLPatternInit;
}

export interface RouterRequestMethodCondition {
Expand Down Expand Up @@ -258,15 +270,18 @@ export function isRouteMatchCondition(serviceWorker: DurableServiceWorkerRegistr
// For a USVString input, a ServiceWorker script's URL is used as a base URL.
//
// My current assumption is we are completely comparing the URL and search params here
const matchInstance = new URL(url, serviceWorker.durable.url);
const patternInstance = new URL(urlPattern, serviceWorker.durable.url);
const matchInstance = new URL(url, serviceWorker.durable.baseURL);
const patternInstance = new URL(urlPattern, serviceWorker.durable.baseURL);
return matchInstance.toString() === patternInstance.toString();
} else {
if (urlPattern.test) {
return urlPattern.test(url, serviceWorker.durable.url);
if ("test" in urlPattern && urlPattern.test) {
return urlPattern.test(url, serviceWorker.durable.baseURL);
} else {
const pattern = new URLPattern(urlPattern);
return pattern.test(url, serviceWorker.durable.url);
const pattern = new URLPattern(
urlPattern,
typeof urlPattern === "string" ? serviceWorker.durable.baseURL : undefined
);
return pattern.test(url, serviceWorker.durable.baseURL);
}
}
}
Expand Down Expand Up @@ -436,46 +451,59 @@ export async function createRouter(serviceWorkers?: DurableServiceWorkerRegistra
}
const { serviceWorker, route } = found;

const serviceWorkerFetch = fetchers.get(serviceWorker);
ok(serviceWorkerFetch, "Expected to find fetcher for service worker, internal state corrupt");

return sources(route.source);

async function sources(ruleSource: RouterRuleSource | RouterRuleSource[]) {
if (Array.isArray(ruleSource)) {
let returningResponse: Response;
let firstResponse: Response,
lastError: unknown = undefined;
for (const singleRuleSource of ruleSource) {
try {
const response = await source(singleRuleSource);
// TODO, should response.ok be true here as well

// TODO behaviorEnum
// if (returningResponse) {
// continue;
// }
// if (isRouterSourceObject(singleRuleSource)) {
// if (singleRuleSource.behaviorEnum === "continue-discarding-latter-results") {
// returningResponse = returningResponse || response;
// continue;
// }
// }
if (firstResponse) {
continue;
}
if (isRouterSourceObject(singleRuleSource)) {
if (singleRuleSource.behaviorEnum === "continue-discarding-latter-results") {
if (!firstResponse) {
firstResponse = response;
}
continue;
}
}

if (response) {
return response;
}
} catch {
} catch (error) {
// Source failed, or could not match
lastError = error;
}
}
if (returningResponse) {
return returningResponse;
if (firstResponse) {
return firstResponse;
}
if (lastError) {
// Using promise reject here will give an original error stack for user...
throw await Promise.reject(lastError);
}
throw new Error("Could not resolve response");
} else {
return source(ruleSource)
}
}

async function serviceWorkerFetch() {
// TODO check if any fetch event handlers added.
const fetch = fetchers.get(serviceWorker);
ok(fetch, "Expected to find fetcher for service worker, internal state corrupt");
return fetch(clone(), init);
}

async function source(ruleSource: RouterRuleSource): Promise<Response | undefined> {
if (isRouterSourceType(ruleSource, "network")) {
const response = await fetch(clone(), init);
Expand All @@ -490,12 +518,12 @@ export async function createRouter(serviceWorkers?: DurableServiceWorkerRegistra
return response;
}
if (isRouterSourceType(ruleSource, "fetch-event")) {
return serviceWorkerFetch(clone(), init);
return serviceWorkerFetch();
}
if (isRouterSourceType(ruleSource, "race-network-and-fetch-handler")) {
return Promise.race([
source("network"),
source("fetch-event")
serviceWorkerFetch()
]);
}
if (isRouterSourceType(ruleSource, "cache")) {
Expand Down

0 comments on commit 8014253

Please sign in to comment.