@statewalker/webrun-http-browser 0.3.3 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +406 -51
- package/demo/demo-1.html +109 -194
- package/demo/demo-2.html +118 -299
- package/dist/core/data-calls.d.ts +5 -0
- package/dist/core/data-calls.d.ts.map +1 -0
- package/dist/core/data-channels.d.ts +17 -0
- package/dist/core/data-channels.d.ts.map +1 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/message-target.d.ts +2 -0
- package/dist/core/message-target.d.ts.map +1 -0
- package/dist/core/registry.d.ts +18 -0
- package/dist/core/registry.d.ts.map +1 -0
- package/dist/http/http-send-recieve.d.ts +36 -0
- package/dist/http/http-send-recieve.d.ts.map +1 -0
- package/dist/http/index.d.ts +4 -0
- package/dist/http/index.d.ts.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2670 -807
- package/dist/relay/index-sw.d.ts +7 -0
- package/dist/relay/index-sw.d.ts.map +1 -0
- package/dist/relay/index.d.ts +69 -0
- package/dist/relay/index.d.ts.map +1 -0
- package/dist/relay/split-service-url.d.ts +13 -0
- package/dist/relay/split-service-url.d.ts.map +1 -0
- package/dist/relay-sw.d.ts +2 -0
- package/dist/relay-sw.d.ts.map +1 -0
- package/dist/relay-sw.js +1660 -0
- package/dist/sw/http-sw-dispatcher.d.ts +28 -0
- package/dist/sw/http-sw-dispatcher.d.ts.map +1 -0
- package/dist/sw/index.d.ts +3 -0
- package/dist/sw/index.d.ts.map +1 -0
- package/dist/sw/sw-dispatcher.d.ts +74 -0
- package/dist/sw/sw-dispatcher.d.ts.map +1 -0
- package/dist/sw-worker.d.ts +2 -0
- package/dist/sw-worker.d.ts.map +1 -0
- package/dist/sw-worker.js +1597 -0
- package/dist/sw.d.ts +2 -0
- package/dist/sw.d.ts.map +1 -0
- package/dist/sw.js +1883 -0
- package/package.json +51 -37
- package/public/index.html +61 -97
- package/public/index.js +7 -4
- package/public/sw-worker.js +4 -0
- package/public-relay/heartbeat.js +4 -3
- package/public-relay/relay-sw.js +4 -6
- package/public-relay/relay.html +16 -11
- package/src/core/data-calls.ts +46 -0
- package/src/core/data-channels.ts +262 -0
- package/src/core/index.ts +9 -0
- package/src/core/message-target.ts +8 -0
- package/src/core/registry.ts +54 -0
- package/src/http/http-send-recieve.ts +94 -0
- package/src/http/index.ts +7 -0
- package/src/index.ts +3 -0
- package/src/relay/index-sw.ts +145 -0
- package/src/relay/index.ts +261 -0
- package/src/relay/split-service-url.ts +30 -0
- package/src/relay-sw.ts +7 -0
- package/src/sw/http-sw-dispatcher.ts +122 -0
- package/src/sw/index.ts +2 -0
- package/src/sw/sw-dispatcher.ts +332 -0
- package/src/sw-worker.ts +7 -0
- package/src/sw.ts +1 -0
- package/CHANGELOG.md +0 -1
- package/LICENSE +0 -21
- package/demo/demo-2 copy.html +0 -598
- package/demo/demo-3.html +0 -167
- package/dist/index-sw-umd.js +0 -798
- package/dist/index-sw-umd.min.js +0 -2
- package/dist/index-sw.js +0 -791
- package/dist/index-sw.min.js +0 -2
- package/dist/index-umd.js +0 -853
- package/dist/index-umd.min.js +0 -2
- package/dist/index.min.js +0 -2
- package/index.js +0 -1
- package/src/core/data-calls.js +0 -36
- package/src/core/data-channels.js +0 -192
- package/src/core/data-send-recieve.js +0 -28
- package/src/core/errors.js +0 -13
- package/src/core/index.js +0 -4
- package/src/http/HttpError.js +0 -59
- package/src/http/http-send-recieve.js +0 -40
- package/src/http/http-stubs.js +0 -135
- package/src/http/index.js +0 -3
- package/src/http/readable-streams.js +0 -33
- package/src/index.js +0 -7
- package/src/relay/index-sw.js +0 -216
- package/src/relay/index.js +0 -263
- package/src/relay/splitServiceUrl.js +0 -24
- package/src/sw/http-sw-dispatcher.js +0 -128
- package/src/sw/sw-dispatcher.js +0 -264
package/src/relay/index-sw.js
DELETED
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
import { newRegistry } from "@statewalker/utils";
|
|
2
|
-
import { get, set } from "idb-keyval";
|
|
3
|
-
import { callChannel, handleChannelCalls } from "../core/data-calls.js";
|
|
4
|
-
import { sendHttpRequest } from "../http/http-send-recieve.js";
|
|
5
|
-
import { splitServiceUrl } from "./splitServiceUrl.js";
|
|
6
|
-
import { HttpError } from "../http/HttpError.js";
|
|
7
|
-
|
|
8
|
-
export function startRelayServiceWorker(self) {
|
|
9
|
-
const [register, clear] = newRegistry();
|
|
10
|
-
|
|
11
|
-
if (typeof self.skipWaiting === "function") {
|
|
12
|
-
console.log("self.skipWaiting() is supported.");
|
|
13
|
-
self.addEventListener("install", (e) => {
|
|
14
|
-
// See https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#service-worker-global-scope-skipwaiting
|
|
15
|
-
e.waitUntil(self.skipWaiting());
|
|
16
|
-
});
|
|
17
|
-
} else {
|
|
18
|
-
console.log("self.skipWaiting() is not supported.");
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
if (self.clients && (typeof self.clients.claim === "function")) {
|
|
22
|
-
console.log("self.clients.claim() is supported.");
|
|
23
|
-
self.addEventListener("activate", (e) => {
|
|
24
|
-
// See https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#clients-claim-method
|
|
25
|
-
e.waitUntil(self.clients.claim());
|
|
26
|
-
});
|
|
27
|
-
} else {
|
|
28
|
-
console.log("self.clients.claim() is not supported.");
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const clientsRegistry = newClientsRegistry({
|
|
32
|
-
self,
|
|
33
|
-
get,
|
|
34
|
-
set,
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
// This listener handles the following message types:
|
|
38
|
-
// * registration: registers new clients as service providers
|
|
39
|
-
// * handles service calls rounting:
|
|
40
|
-
// - it gets the clientKey defined in the call
|
|
41
|
-
// - it uses the serviceKey to get the service-specifc channel
|
|
42
|
-
// - it creates a new message channel and sent its ports to peers
|
|
43
|
-
|
|
44
|
-
register(handleChannelCalls(self, "REGISTER", async (event, data) => {
|
|
45
|
-
return await clientsRegistry.addClient(data.key, event.source);
|
|
46
|
-
}));
|
|
47
|
-
register(handleChannelCalls(self, "UNREGISTER", async (event, data) => {
|
|
48
|
-
return await clientsRegistry.removeClient(data.key);
|
|
49
|
-
}));
|
|
50
|
-
|
|
51
|
-
// Transfers all parameters (and ports) to the target client.
|
|
52
|
-
register(handleChannelCalls(self, "CONNECT", async (event, data, port) => {
|
|
53
|
-
const { key } = data;
|
|
54
|
-
const client = await clientsRegistry.getClient(key);
|
|
55
|
-
if (!client) {
|
|
56
|
-
throw new Error(`Target client was not found. Target key: "${key}".`);
|
|
57
|
-
}
|
|
58
|
-
return await callChannel(client, "CONNECT", data, port);
|
|
59
|
-
}));
|
|
60
|
-
|
|
61
|
-
const fetchListener = (event) => {
|
|
62
|
-
const request = event.request;
|
|
63
|
-
const params = splitServiceUrl(request.url);
|
|
64
|
-
const { key } = params;
|
|
65
|
-
if (key) {
|
|
66
|
-
const handler = async () => {
|
|
67
|
-
try {
|
|
68
|
-
const channel = new MessageChannel();
|
|
69
|
-
const client = await clientsRegistry.getClient(key);
|
|
70
|
-
if (!client) {
|
|
71
|
-
throw HttpError.errorResourceGone(params);
|
|
72
|
-
}
|
|
73
|
-
const data = {
|
|
74
|
-
type: "http",
|
|
75
|
-
key,
|
|
76
|
-
};
|
|
77
|
-
if (!await callChannel(client, "CONNECT", data, channel.port2)) {
|
|
78
|
-
throw HttpError.errorForbidden(params);
|
|
79
|
-
}
|
|
80
|
-
return await sendHttpRequest(channel.port1, request);
|
|
81
|
-
} catch (error) {
|
|
82
|
-
error = HttpError.fromError(error);
|
|
83
|
-
const options = error.getResponseOptions(params);
|
|
84
|
-
return new Response(JSON.stringify(options), {
|
|
85
|
-
...options,
|
|
86
|
-
headers: {
|
|
87
|
-
"Content-Type": "text/javascript",
|
|
88
|
-
},
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
};
|
|
92
|
-
event.respondWith(handler());
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
|
-
self.addEventListener("fetch", fetchListener);
|
|
96
|
-
register(() => self.removeEventListener("fetch", fetchListener));
|
|
97
|
-
|
|
98
|
-
return clear;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// --------------------------------------------
|
|
102
|
-
// errors.js
|
|
103
|
-
|
|
104
|
-
// --------------------------------------------
|
|
105
|
-
|
|
106
|
-
function newClientsRegistry({
|
|
107
|
-
self,
|
|
108
|
-
key = "clientsIds",
|
|
109
|
-
get,
|
|
110
|
-
set,
|
|
111
|
-
}) {
|
|
112
|
-
let _index;
|
|
113
|
-
async function loadClientsIndex() {
|
|
114
|
-
if (!_index) {
|
|
115
|
-
const entries = (await get(key)) || [];
|
|
116
|
-
_index = Object.fromEntries(entries);
|
|
117
|
-
}
|
|
118
|
-
return _index;
|
|
119
|
-
}
|
|
120
|
-
async function storeClientsIndex() {
|
|
121
|
-
const index = await loadClientsIndex();
|
|
122
|
-
const entries = Object.entries(index);
|
|
123
|
-
await set(key, entries);
|
|
124
|
-
return index;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
async function addClient(clientKey, client) {
|
|
128
|
-
const index = await loadClientsIndex();
|
|
129
|
-
const clientId = client.id;
|
|
130
|
-
let result = false;
|
|
131
|
-
if (!(clientId in index)) {
|
|
132
|
-
index[clientKey] = clientId;
|
|
133
|
-
await storeClientsIndex();
|
|
134
|
-
result = true;
|
|
135
|
-
}
|
|
136
|
-
return result;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
async function removeClient(clientKey) {
|
|
140
|
-
const index = await loadClientsIndex();
|
|
141
|
-
let result = false;
|
|
142
|
-
if (clientKey in index) {
|
|
143
|
-
delete index[clientKey];
|
|
144
|
-
await storeClientsIndex();
|
|
145
|
-
result = true;
|
|
146
|
-
}
|
|
147
|
-
return result;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
async function getClient(clientKey) {
|
|
151
|
-
const index = await loadClientsIndex();
|
|
152
|
-
const clientId = index[clientKey];
|
|
153
|
-
const client = await self.clients.get(clientId);
|
|
154
|
-
if (!client) {
|
|
155
|
-
delete index[clientKey];
|
|
156
|
-
await storeClientsIndex();
|
|
157
|
-
}
|
|
158
|
-
return client;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
return {
|
|
162
|
-
getClient,
|
|
163
|
-
addClient,
|
|
164
|
-
removeClient,
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
// ----------------------------------------------------
|
|
168
|
-
// Content of the "idb-keyval" package
|
|
169
|
-
// import { get, set } from "idb-keyval";
|
|
170
|
-
|
|
171
|
-
// function promisifyRequest(request) {
|
|
172
|
-
// return new Promise((resolve, reject) => {
|
|
173
|
-
// // @ts-ignore - file size hacks
|
|
174
|
-
// request.oncomplete = request.onsuccess = () => resolve(request.result);
|
|
175
|
-
// // @ts-ignore - file size hacks
|
|
176
|
-
// request.onabort = request.onerror = () => reject(request.error);
|
|
177
|
-
// });
|
|
178
|
-
// }
|
|
179
|
-
// function createStore(dbName, storeName) {
|
|
180
|
-
// const request = indexedDB.open(dbName);
|
|
181
|
-
// request.onupgradeneeded = () => request.result.createObjectStore(storeName);
|
|
182
|
-
// const dbp = promisifyRequest(request);
|
|
183
|
-
// return (txMode, callback) =>
|
|
184
|
-
// dbp.then((db) =>
|
|
185
|
-
// callback(db.transaction(storeName, txMode).objectStore(storeName))
|
|
186
|
-
// );
|
|
187
|
-
// }
|
|
188
|
-
// let defaultGetStoreFunc;
|
|
189
|
-
// function defaultGetStore() {
|
|
190
|
-
// if (!defaultGetStoreFunc) {
|
|
191
|
-
// defaultGetStoreFunc = createStore("keyval-store", "keyval");
|
|
192
|
-
// }
|
|
193
|
-
// return defaultGetStoreFunc;
|
|
194
|
-
// }
|
|
195
|
-
// /**
|
|
196
|
-
// * Get a value by its key.
|
|
197
|
-
// *
|
|
198
|
-
// * @param key
|
|
199
|
-
// * @param customStore Method to get a custom store. Use with caution (see the docs).
|
|
200
|
-
// */
|
|
201
|
-
// function get(key, customStore = defaultGetStore()) {
|
|
202
|
-
// return customStore("readonly", (store) => promisifyRequest(store.get(key)));
|
|
203
|
-
// }
|
|
204
|
-
// /**
|
|
205
|
-
// * Set a value with a key.
|
|
206
|
-
// *
|
|
207
|
-
// * @param key
|
|
208
|
-
// * @param value
|
|
209
|
-
// * @param customStore Method to get a custom store. Use with caution (see the docs).
|
|
210
|
-
// */
|
|
211
|
-
// function set(key, value, customStore = defaultGetStore()) {
|
|
212
|
-
// return customStore("readwrite", (store) => {
|
|
213
|
-
// store.put(value, key);
|
|
214
|
-
// return promisifyRequest(store.transaction);
|
|
215
|
-
// });
|
|
216
|
-
// }
|
package/src/relay/index.js
DELETED
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
import { newRegistry } from "@statewalker/utils";
|
|
2
|
-
import { callChannel, handleChannelCalls } from "../core/data-calls.js";
|
|
3
|
-
import {
|
|
4
|
-
handleHttpRequests,
|
|
5
|
-
sendHttpRequest,
|
|
6
|
-
} from "../http/http-send-recieve.js";
|
|
7
|
-
export * from "./splitServiceUrl.js";
|
|
8
|
-
|
|
9
|
-
export function newServiceWorkerPort() {
|
|
10
|
-
// Bind the service worker to
|
|
11
|
-
const channel = new MessageChannel();
|
|
12
|
-
channel.port1.onmessage = (event) => {
|
|
13
|
-
navigator.serviceWorker.controller.postMessage(event.data, event.ports);
|
|
14
|
-
};
|
|
15
|
-
navigator.serviceWorker.addEventListener("message", (event) => {
|
|
16
|
-
channel.port1.postMessage(event.data, event.ports);
|
|
17
|
-
});
|
|
18
|
-
return channel.port2;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export async function initServiceWorker1({ swUrl, scopeUrl, type }) {
|
|
22
|
-
const {
|
|
23
|
-
installing,
|
|
24
|
-
waiting,
|
|
25
|
-
active,
|
|
26
|
-
} = await navigator.serviceWorker.register(swUrl, {
|
|
27
|
-
// type: "module",
|
|
28
|
-
scope: scopeUrl,
|
|
29
|
-
});
|
|
30
|
-
(installing || waiting || active).addEventListener("statechange", (e) => {
|
|
31
|
-
console.log("state", e.target.state);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
const serviceWorker = navigator.serviceWorker;
|
|
35
|
-
await new Promise((resolve) => {
|
|
36
|
-
// Resolve right away if this page is already controlled.
|
|
37
|
-
if (serviceWorker.controller) {
|
|
38
|
-
resolve();
|
|
39
|
-
} else {
|
|
40
|
-
const onChange = () => {
|
|
41
|
-
resolve();
|
|
42
|
-
serviceWorker.removeEventListener("controllerchange", onChange);
|
|
43
|
-
serviceWorker.oncontrollerchange = null;
|
|
44
|
-
};
|
|
45
|
-
serviceWorker.addEventListener("controllerchange", onChange);
|
|
46
|
-
serviceWorker.oncontrollerchange = onChange;
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
const worker = serviceWorker.controller;
|
|
50
|
-
const isActivated = () => worker.state === "activated";
|
|
51
|
-
return await new Promise(async (resolve) => {
|
|
52
|
-
if (isActivated()) resolve(worker);
|
|
53
|
-
else {
|
|
54
|
-
worker.onstatechange = () => {
|
|
55
|
-
if (!isActivated()) return;
|
|
56
|
-
worker.onstatechange = null;
|
|
57
|
-
resolve(worker);
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export async function initServiceWorker({ swUrl, scopeUrl, type }) {
|
|
64
|
-
await navigator.serviceWorker.register(swUrl, {
|
|
65
|
-
type,
|
|
66
|
-
scope: scopeUrl,
|
|
67
|
-
});
|
|
68
|
-
const worker = await getServiceWorkerController();
|
|
69
|
-
await awaitServiceWorkerActivation(worker);
|
|
70
|
-
return worker;
|
|
71
|
-
|
|
72
|
-
async function getServiceWorkerController() {
|
|
73
|
-
return await new Promise((resolve) => {
|
|
74
|
-
// Resolve right away if this page is already controlled.
|
|
75
|
-
const serviceWorker = navigator.serviceWorker;
|
|
76
|
-
if (serviceWorker.controller) {
|
|
77
|
-
resolve(serviceWorker.controller);
|
|
78
|
-
} else {
|
|
79
|
-
const onChange = () => {
|
|
80
|
-
resolve(serviceWorker.controller);
|
|
81
|
-
serviceWorker.removeEventListener("controllerchange", onChange);
|
|
82
|
-
serviceWorker.oncontrollerchange = null;
|
|
83
|
-
};
|
|
84
|
-
serviceWorker.addEventListener("controllerchange", onChange);
|
|
85
|
-
serviceWorker.oncontrollerchange = onChange;
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// ------------------------------
|
|
91
|
-
// Await until the service is ready
|
|
92
|
-
async function awaitServiceWorkerActivation(worker) {
|
|
93
|
-
const isActivated = () => worker.state === "activated";
|
|
94
|
-
await new Promise(async (resolve) => {
|
|
95
|
-
if (isActivated()) resolve();
|
|
96
|
-
else {
|
|
97
|
-
worker.onstatechange = () => {
|
|
98
|
-
if (!isActivated()) return;
|
|
99
|
-
worker.onstatechange = null;
|
|
100
|
-
resolve();
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export async function initHttpService(handler, {
|
|
108
|
-
key,
|
|
109
|
-
port,
|
|
110
|
-
}) {
|
|
111
|
-
return await registerConnectionsHandler({
|
|
112
|
-
key,
|
|
113
|
-
communicationPort: port,
|
|
114
|
-
handler: async (event, data, callPort) => {
|
|
115
|
-
handleHttpRequests(callPort, handler);
|
|
116
|
-
return true;
|
|
117
|
-
},
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
export async function callHttpService(request, {
|
|
122
|
-
key,
|
|
123
|
-
port,
|
|
124
|
-
}) {
|
|
125
|
-
const callPort = await initializeConnection({
|
|
126
|
-
key,
|
|
127
|
-
communicationPort: port,
|
|
128
|
-
});
|
|
129
|
-
const result = await sendHttpRequest(callPort, request);
|
|
130
|
-
return result;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export function getRelayWindowMessageHandler({
|
|
134
|
-
swUrl = new URL("./index-sw.js", import.meta.url) + "",
|
|
135
|
-
scopeUrl = new URL("../", import.meta.url) + "",
|
|
136
|
-
} = {}) {
|
|
137
|
-
let externalPort;
|
|
138
|
-
return async (ev) => {
|
|
139
|
-
if (ev.data.type === "CONNECT") {
|
|
140
|
-
const newExternalPort = (ev.ports || [])[0];
|
|
141
|
-
if (externalPort) {
|
|
142
|
-
newExternalPort.close();
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
|
-
externalPort = newExternalPort;
|
|
146
|
-
await initServiceWorker({
|
|
147
|
-
swUrl,
|
|
148
|
-
scopeUrl,
|
|
149
|
-
});
|
|
150
|
-
const serviceWorkerPort = newServiceWorkerPort();
|
|
151
|
-
serviceWorkerPort.onmessage = (event) => {
|
|
152
|
-
externalPort.postMessage(event.data, event.ports);
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
externalPort.onmessage = (event) => {
|
|
156
|
-
serviceWorkerPort.postMessage(event.data, event.ports);
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
export async function newRemoteRelayChannel({
|
|
163
|
-
baseUrl = new URL("../public-relay/", import.meta.url),
|
|
164
|
-
url = new URL("relay.html", baseUrl),
|
|
165
|
-
container = document.body,
|
|
166
|
-
} = {}) {
|
|
167
|
-
const messageChannel = new MessageChannel();
|
|
168
|
-
const { iframe, promise } = await newIFrame(url);
|
|
169
|
-
Object.assign(iframe.style, {
|
|
170
|
-
// height: "100px"
|
|
171
|
-
position: "fixed",
|
|
172
|
-
width: "1px",
|
|
173
|
-
height: "1px",
|
|
174
|
-
top: "-1000",
|
|
175
|
-
left: "-1000",
|
|
176
|
-
display: "block",
|
|
177
|
-
opacity: "0",
|
|
178
|
-
border: "none",
|
|
179
|
-
outline: "none",
|
|
180
|
-
});
|
|
181
|
-
container.appendChild(iframe);
|
|
182
|
-
promise.then(() => {
|
|
183
|
-
iframe.contentWindow.postMessage(
|
|
184
|
-
{
|
|
185
|
-
type: "CONNECT",
|
|
186
|
-
},
|
|
187
|
-
"*",
|
|
188
|
-
[messageChannel.port1],
|
|
189
|
-
);
|
|
190
|
-
});
|
|
191
|
-
return {
|
|
192
|
-
baseUrl,
|
|
193
|
-
port: messageChannel.port2,
|
|
194
|
-
close: () => {
|
|
195
|
-
iframe.parentElement && iframe.parentElement.removeChild(iframe);
|
|
196
|
-
messageChannel.port1.close();
|
|
197
|
-
messageChannel.port2.close();
|
|
198
|
-
},
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
async function newIFrame(url) {
|
|
202
|
-
const iframe = document.createElement("iframe");
|
|
203
|
-
iframe.src = url;
|
|
204
|
-
Object.assign(iframe.style, {
|
|
205
|
-
padding: 0,
|
|
206
|
-
margin: 0,
|
|
207
|
-
border: "none",
|
|
208
|
-
outline: "none",
|
|
209
|
-
width: "100%",
|
|
210
|
-
height: "100%",
|
|
211
|
-
});
|
|
212
|
-
return {
|
|
213
|
-
iframe,
|
|
214
|
-
promise: new Promise((resolve, reject) => {
|
|
215
|
-
try {
|
|
216
|
-
iframe.onerror = reject;
|
|
217
|
-
iframe.onload = () => resolve(iframe);
|
|
218
|
-
} catch (error) {
|
|
219
|
-
reject(error);
|
|
220
|
-
}
|
|
221
|
-
}),
|
|
222
|
-
};
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
// -------------------------------------------------------
|
|
226
|
-
|
|
227
|
-
export async function initializeConnection({
|
|
228
|
-
key,
|
|
229
|
-
communicationPort,
|
|
230
|
-
...options
|
|
231
|
-
}) {
|
|
232
|
-
const channel = new MessageChannel();
|
|
233
|
-
const accepted = await callChannel(
|
|
234
|
-
communicationPort,
|
|
235
|
-
"CONNECT",
|
|
236
|
-
{ key, ...options },
|
|
237
|
-
channel.port2,
|
|
238
|
-
);
|
|
239
|
-
if (!accepted) {
|
|
240
|
-
channel.port1.close();
|
|
241
|
-
channel.port2.close();
|
|
242
|
-
return null;
|
|
243
|
-
}
|
|
244
|
-
return channel.port1;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
export async function registerConnectionsHandler({
|
|
248
|
-
key,
|
|
249
|
-
handler,
|
|
250
|
-
communicationPort,
|
|
251
|
-
}) {
|
|
252
|
-
const [register, cleanup] = newRegistry();
|
|
253
|
-
await callChannel(communicationPort, "REGISTER", { key });
|
|
254
|
-
register(() => callChannel(communicationPort, "UNREGISTER", { key }));
|
|
255
|
-
register(
|
|
256
|
-
handleChannelCalls(
|
|
257
|
-
communicationPort,
|
|
258
|
-
"CONNECT",
|
|
259
|
-
handler,
|
|
260
|
-
),
|
|
261
|
-
);
|
|
262
|
-
return cleanup;
|
|
263
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
export function splitServiceUrl(url, separator = "~") {
|
|
2
|
-
let key = "";
|
|
3
|
-
let path = "";
|
|
4
|
-
let str = url + "";
|
|
5
|
-
const idx = str.indexOf(separator);
|
|
6
|
-
let baseUrl = "";
|
|
7
|
-
if (idx >= 0) {
|
|
8
|
-
baseUrl = str.substring(0, idx + separator.length);
|
|
9
|
-
str.substring(idx + separator.length)
|
|
10
|
-
.replace(/^([^\/]+)/, (match, $1) => {
|
|
11
|
-
baseUrl += match;
|
|
12
|
-
if (baseUrl.length < str.length) baseUrl += "/";
|
|
13
|
-
key = $1;
|
|
14
|
-
path = str.substring(baseUrl.length);
|
|
15
|
-
return "";
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
return {
|
|
19
|
-
url,
|
|
20
|
-
key,
|
|
21
|
-
baseUrl,
|
|
22
|
-
path,
|
|
23
|
-
};
|
|
24
|
-
}
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import { handleHttpRequests, sendHttpRequest } from "../http/http-send-recieve.js";
|
|
2
|
-
import { SwPortDispatcher, SwPortHandler } from "./sw-dispatcher.js";
|
|
3
|
-
|
|
4
|
-
export class SwHttpAdapter extends SwPortHandler {
|
|
5
|
-
constructor(options) {
|
|
6
|
-
super(options);
|
|
7
|
-
this._handlers = new Map();
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
async _setCommunicationPort(port) {
|
|
11
|
-
if (this._cleanupRequestChannel) {
|
|
12
|
-
this._cleanupRequestChannel();
|
|
13
|
-
}
|
|
14
|
-
this._cleanupRequestChannel = handleHttpRequests(
|
|
15
|
-
port,
|
|
16
|
-
this._handleHttpRequest.bind(this),
|
|
17
|
-
);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
async _handleHttpRequest(request) {
|
|
21
|
-
const requestUrl = request.url;
|
|
22
|
-
let handler;
|
|
23
|
-
for (let entry of this._handlers.entries()) {
|
|
24
|
-
const [urlPrefix] = entry;
|
|
25
|
-
if (requestUrl.indexOf(urlPrefix) === 0) {
|
|
26
|
-
handler = entry[1];
|
|
27
|
-
break;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return !handler
|
|
31
|
-
? new Response(null, {
|
|
32
|
-
status: 404,
|
|
33
|
-
statusMessage: "Error 404: Not found",
|
|
34
|
-
})
|
|
35
|
-
: handler(request);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Registers the given request handler.
|
|
40
|
-
* @param {string} prefix unique base URL prefix used to register the specified handler
|
|
41
|
-
* @param {*} handler the request handler
|
|
42
|
-
* @return {string} full URL of the resulting endpoint
|
|
43
|
-
*/
|
|
44
|
-
async register(prefix, handler) {
|
|
45
|
-
prefix = "./" + (prefix || "").replace(/^[\.\/]+/, "");
|
|
46
|
-
const rootUrl = this.rootUrl;
|
|
47
|
-
const baseUrl = new URL(prefix, rootUrl) + "";
|
|
48
|
-
this._handlers.set(baseUrl, handler);
|
|
49
|
-
return {
|
|
50
|
-
baseUrl,
|
|
51
|
-
prefix,
|
|
52
|
-
async remove() {
|
|
53
|
-
this._handlers.delete(baseUrl);
|
|
54
|
-
},
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export class SwHttpDispatcher extends SwPortDispatcher {
|
|
60
|
-
constructor(options) {
|
|
61
|
-
super(options);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
start() {
|
|
65
|
-
super.start();
|
|
66
|
-
this.self.addEventListener("fetch", this._handleFetchEvent.bind(this));
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
_handleFetchEvent(event) {
|
|
70
|
-
event.respondWith((async () => {
|
|
71
|
-
const request = event.request;
|
|
72
|
-
try {
|
|
73
|
-
const requestUrl = request.url;
|
|
74
|
-
const rootUrl = this.scope;
|
|
75
|
-
let channelInfo;
|
|
76
|
-
if (requestUrl.indexOf(rootUrl) === 0) {
|
|
77
|
-
const key = requestUrl
|
|
78
|
-
.substring(rootUrl.length)
|
|
79
|
-
.replace(/^\/?([^\/]+).*$/, "$1");
|
|
80
|
-
// console.log(`* rootUrl="${rootUrl}" requestUrl="${requestUrl}" key="${key}"`);
|
|
81
|
-
channelInfo = await this.loadChannelInfo(key);
|
|
82
|
-
}
|
|
83
|
-
if (channelInfo && channelInfo.port) {
|
|
84
|
-
return await sendHttpRequest(channelInfo.port, request);
|
|
85
|
-
} else {
|
|
86
|
-
const newRequest = new Request(requestUrl, {
|
|
87
|
-
method: request.method,
|
|
88
|
-
headers: request.headers,
|
|
89
|
-
body: request.body,
|
|
90
|
-
referrer: request.referrer,
|
|
91
|
-
referrerPolicy: request.referrerPolicy,
|
|
92
|
-
// mode: request.mode,
|
|
93
|
-
credentials: request.credentials,
|
|
94
|
-
cache: request.cache,
|
|
95
|
-
redirect: request.redirect,
|
|
96
|
-
integrity: request.integrity,
|
|
97
|
-
});
|
|
98
|
-
return await fetch(newRequest);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// const requestUrl = request.url;
|
|
102
|
-
// let url = requestUrl.replace(
|
|
103
|
-
// /^.*\/[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}(.*)$/,
|
|
104
|
-
// "$1",
|
|
105
|
-
// );
|
|
106
|
-
// if (url !== requestUrl) {
|
|
107
|
-
// url = new URL(
|
|
108
|
-
// "/packages/webrun-http-browser/src" + url,
|
|
109
|
-
// self.location.href,
|
|
110
|
-
// );
|
|
111
|
-
// }
|
|
112
|
-
} catch (error) {
|
|
113
|
-
console.error(error);
|
|
114
|
-
return new Response(null, {
|
|
115
|
-
status: 500,
|
|
116
|
-
statusText: "Error 500: Internal error",
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
})());
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
export function startHttpDispatcher({ self, log }) {
|
|
123
|
-
const dispatcher = new SwHttpDispatcher({ self, log });
|
|
124
|
-
dispatcher.start();
|
|
125
|
-
return () => {
|
|
126
|
-
dispatcher.stop();
|
|
127
|
-
};
|
|
128
|
-
}
|