zastro-websockets-cloudflare 12.6.0 → 12.6.12-10
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/dist/entrypoints/image-endpoint.js +15 -1
- package/dist/entrypoints/image-service.js +2 -2
- package/dist/entrypoints/server.d.ts +0 -1
- package/dist/index.d.ts +18 -0
- package/dist/index.js +16 -33
- package/dist/utils/assets.js +1 -45
- package/dist/utils/handler.d.ts +0 -1
- package/dist/utils/handler.js +0 -5
- package/dist/websocket/middleware.js +1 -4
- package/dist/websocket/server.js +2 -10
- package/dist/websocket/websocket.d.ts +5 -6
- package/dist/websocket/websocket.js +9 -19
- package/package.json +11 -8
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { imageConfig } from "astro:assets";
|
|
2
|
+
import { isRemotePath } from "@astrojs/internal-helpers/path";
|
|
3
|
+
import { isRemoteAllowed } from "@astrojs/internal-helpers/remote";
|
|
1
4
|
const prerender = false;
|
|
2
5
|
const GET = (ctx) => {
|
|
3
6
|
const href = ctx.url.searchParams.get("href");
|
|
@@ -7,7 +10,18 @@ const GET = (ctx) => {
|
|
|
7
10
|
statusText: "Missing 'href' query parameter"
|
|
8
11
|
});
|
|
9
12
|
}
|
|
10
|
-
|
|
13
|
+
if (isRemotePath(href)) {
|
|
14
|
+
if (isRemoteAllowed(href, imageConfig) === false) {
|
|
15
|
+
return new Response("Forbidden", { status: 403 });
|
|
16
|
+
} else {
|
|
17
|
+
return Response.redirect(href, 302);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const proxied = new URL(href, ctx.url.origin);
|
|
21
|
+
if (proxied.origin !== ctx.url.origin) {
|
|
22
|
+
return new Response("Forbidden", { status: 403 });
|
|
23
|
+
}
|
|
24
|
+
return fetch(proxied);
|
|
11
25
|
};
|
|
12
26
|
export {
|
|
13
27
|
GET,
|
|
@@ -15,9 +15,9 @@ const service = {
|
|
|
15
15
|
if (isESMImportedImage(options.src)) {
|
|
16
16
|
imageSource = options.src.src;
|
|
17
17
|
} else if (isRemoteAllowed(options.src, imageConfig)) {
|
|
18
|
-
imageSource =
|
|
18
|
+
imageSource = options.src;
|
|
19
19
|
} else {
|
|
20
|
-
return
|
|
20
|
+
return options.src;
|
|
21
21
|
}
|
|
22
22
|
const imageEndpoint = joinPaths(
|
|
23
23
|
// @ts-expect-error Can't recognise import.meta.env
|
package/dist/index.d.ts
CHANGED
|
@@ -91,4 +91,22 @@ export type Options = {
|
|
|
91
91
|
namedExports?: string[];
|
|
92
92
|
};
|
|
93
93
|
};
|
|
94
|
+
declare global {
|
|
95
|
+
namespace App {
|
|
96
|
+
interface Locals {
|
|
97
|
+
isUpgradeRequest?: boolean;
|
|
98
|
+
upgradeWebSocket?: () => {
|
|
99
|
+
socket: import('./websocket/websocket.js').WebSocket;
|
|
100
|
+
response: Response;
|
|
101
|
+
};
|
|
102
|
+
runtime?: {
|
|
103
|
+
env: any;
|
|
104
|
+
cf: any;
|
|
105
|
+
ctx: any;
|
|
106
|
+
caches: any;
|
|
107
|
+
waitUntil: (promise: Promise<any>) => void;
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
94
112
|
export default function createIntegration(args?: Options): AstroIntegration;
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { createReadStream } from "node:fs";
|
|
|
2
2
|
import { appendFile, stat } from "node:fs/promises";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { createInterface } from "node:readline/promises";
|
|
5
|
-
import {
|
|
5
|
+
import { pathToFileURL } from "node:url";
|
|
6
6
|
import {
|
|
7
7
|
appendForwardSlash,
|
|
8
8
|
prependForwardSlash,
|
|
@@ -39,6 +39,7 @@ function createIntegration(args) {
|
|
|
39
39
|
args?.cloudflareModules ?? true
|
|
40
40
|
);
|
|
41
41
|
let _routes;
|
|
42
|
+
const SESSION_KV_BINDING_NAME = args?.sessionKVBindingName ?? "SESSION";
|
|
42
43
|
return {
|
|
43
44
|
name: "zastro-websockets-cloudflare",
|
|
44
45
|
hooks: {
|
|
@@ -48,34 +49,21 @@ function createIntegration(args) {
|
|
|
48
49
|
updateConfig,
|
|
49
50
|
logger,
|
|
50
51
|
addWatchFile,
|
|
51
|
-
addMiddleware
|
|
52
|
-
createCodegenDir
|
|
52
|
+
addMiddleware
|
|
53
53
|
}) => {
|
|
54
54
|
let session = config.session;
|
|
55
|
-
const isBuild = command === "build";
|
|
56
55
|
if (!session?.driver) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
`If you see the error "Invalid binding \`${bindingName}\`" in your build output, you need to add the binding to your wrangler config file.`
|
|
65
|
-
);
|
|
66
|
-
}
|
|
67
|
-
session = isBuild ? {
|
|
56
|
+
logger.info(
|
|
57
|
+
`Enabling sessions with Cloudflare KV with the "${SESSION_KV_BINDING_NAME}" KV binding.`
|
|
58
|
+
);
|
|
59
|
+
logger.info(
|
|
60
|
+
`If you see the error "Invalid binding \`${SESSION_KV_BINDING_NAME}\`" in your build output, you need to add the binding to your wrangler config file.`
|
|
61
|
+
);
|
|
62
|
+
session = {
|
|
68
63
|
...session,
|
|
69
64
|
driver: "cloudflare-kv-binding",
|
|
70
65
|
options: {
|
|
71
|
-
binding:
|
|
72
|
-
...session?.options
|
|
73
|
-
}
|
|
74
|
-
} : {
|
|
75
|
-
...session,
|
|
76
|
-
driver: "fs-lite",
|
|
77
|
-
options: {
|
|
78
|
-
base: fileURLToPath(new URL("sessions", sessionDir)),
|
|
66
|
+
binding: SESSION_KV_BINDING_NAME,
|
|
79
67
|
...session?.options
|
|
80
68
|
}
|
|
81
69
|
};
|
|
@@ -122,12 +110,7 @@ function createIntegration(args) {
|
|
|
122
110
|
"astro:routes:resolved": ({ routes }) => {
|
|
123
111
|
_routes = routes;
|
|
124
112
|
},
|
|
125
|
-
"astro:config:done": ({ setAdapter, config, buildOutput
|
|
126
|
-
if (buildOutput === "static") {
|
|
127
|
-
logger.warn(
|
|
128
|
-
"[@astrojs/cloudflare] This adapter is intended to be used with server rendered pages, which this project does not contain any of. As such, this adapter is unnecessary."
|
|
129
|
-
);
|
|
130
|
-
}
|
|
113
|
+
"astro:config:done": ({ setAdapter, config, buildOutput }) => {
|
|
131
114
|
_config = config;
|
|
132
115
|
finalBuildOutput = buildOutput;
|
|
133
116
|
let customWorkerEntryPoint;
|
|
@@ -142,7 +125,7 @@ function createIntegration(args) {
|
|
|
142
125
|
setAdapter({
|
|
143
126
|
name: "zastro-websockets-cloudflare",
|
|
144
127
|
serverEntrypoint: customWorkerEntryPoint ?? "zastro-websockets-cloudflare/entrypoints/server.js",
|
|
145
|
-
exports:
|
|
128
|
+
exports: [.../* @__PURE__ */ new Set(["default", ...args?.workerEntryPoint?.namedExports ?? []])],
|
|
146
129
|
adapterFeatures: {
|
|
147
130
|
edgeMiddleware: false,
|
|
148
131
|
buildOutput: "server"
|
|
@@ -170,6 +153,8 @@ function createIntegration(args) {
|
|
|
170
153
|
await platformProxy.dispose();
|
|
171
154
|
});
|
|
172
155
|
setProcessEnv(_config, platformProxy.env);
|
|
156
|
+
globalThis.__env__ ??= {};
|
|
157
|
+
globalThis.__env__[SESSION_KV_BINDING_NAME] = platformProxy.env[SESSION_KV_BINDING_NAME];
|
|
173
158
|
const clientLocalsSymbol = Symbol.for("astro.locals");
|
|
174
159
|
server.middlewares.use(async function middleware(req, _res, next) {
|
|
175
160
|
Reflect.set(req, clientLocalsSymbol, {
|
|
@@ -222,9 +207,7 @@ function createIntegration(args) {
|
|
|
222
207
|
vite.define = {
|
|
223
208
|
"process.env": "process.env",
|
|
224
209
|
// Allows the request handler to know what the binding name is
|
|
225
|
-
"globalThis.__ASTRO_SESSION_BINDING_NAME": JSON.stringify(
|
|
226
|
-
args?.sessionKVBindingName ?? "SESSION"
|
|
227
|
-
),
|
|
210
|
+
"globalThis.__ASTRO_SESSION_BINDING_NAME": JSON.stringify(SESSION_KV_BINDING_NAME),
|
|
228
211
|
...vite.define
|
|
229
212
|
};
|
|
230
213
|
}
|
package/dist/utils/assets.js
CHANGED
|
@@ -1,49 +1,5 @@
|
|
|
1
1
|
import { isRemotePath } from "@astrojs/internal-helpers/path";
|
|
2
|
-
|
|
3
|
-
if (!hostname) {
|
|
4
|
-
return true;
|
|
5
|
-
}
|
|
6
|
-
if (!allowWildcard || !hostname.startsWith("*")) {
|
|
7
|
-
return hostname === url.hostname;
|
|
8
|
-
}
|
|
9
|
-
if (hostname.startsWith("**.")) {
|
|
10
|
-
const slicedHostname = hostname.slice(2);
|
|
11
|
-
return slicedHostname !== url.hostname && url.hostname.endsWith(slicedHostname);
|
|
12
|
-
}
|
|
13
|
-
if (hostname.startsWith("*.")) {
|
|
14
|
-
const slicedHostname = hostname.slice(1);
|
|
15
|
-
const additionalSubdomains = url.hostname.replace(slicedHostname, "").split(".").filter(Boolean);
|
|
16
|
-
return additionalSubdomains.length === 1;
|
|
17
|
-
}
|
|
18
|
-
return false;
|
|
19
|
-
}
|
|
20
|
-
function matchPort(url, port) {
|
|
21
|
-
return !port || port === url.port;
|
|
22
|
-
}
|
|
23
|
-
function matchProtocol(url, protocol) {
|
|
24
|
-
return !protocol || protocol === url.protocol.slice(0, -1);
|
|
25
|
-
}
|
|
26
|
-
function matchPathname(url, pathname, allowWildcard) {
|
|
27
|
-
if (!pathname) {
|
|
28
|
-
return true;
|
|
29
|
-
}
|
|
30
|
-
if (!allowWildcard || !pathname.endsWith("*")) {
|
|
31
|
-
return pathname === url.pathname;
|
|
32
|
-
}
|
|
33
|
-
if (pathname.endsWith("/**")) {
|
|
34
|
-
const slicedPathname = pathname.slice(0, -2);
|
|
35
|
-
return slicedPathname !== url.pathname && url.pathname.startsWith(slicedPathname);
|
|
36
|
-
}
|
|
37
|
-
if (pathname.endsWith("/*")) {
|
|
38
|
-
const slicedPathname = pathname.slice(0, -1);
|
|
39
|
-
const additionalPathChunks = url.pathname.replace(slicedPathname, "").split("/").filter(Boolean);
|
|
40
|
-
return additionalPathChunks.length === 1;
|
|
41
|
-
}
|
|
42
|
-
return false;
|
|
43
|
-
}
|
|
44
|
-
function matchPattern(url, remotePattern) {
|
|
45
|
-
return matchProtocol(url, remotePattern.protocol) && matchHostname(url, remotePattern.hostname, true) && matchPort(url, remotePattern.port) && matchPathname(url, remotePattern.pathname, true);
|
|
46
|
-
}
|
|
2
|
+
import { matchHostname, matchPattern } from "@astrojs/internal-helpers/remote";
|
|
47
3
|
function isRemoteAllowed(src, {
|
|
48
4
|
domains = [],
|
|
49
5
|
remotePatterns = []
|
package/dist/utils/handler.d.ts
CHANGED
package/dist/utils/handler.js
CHANGED
|
@@ -20,11 +20,6 @@ async function handle(manifest, app, request, env, context) {
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
Reflect.set(request, Symbol.for("astro.clientAddress"), request.headers.get("cf-connecting-ip"));
|
|
23
|
-
process.env.ASTRO_STUDIO_APP_TOKEN ??= (() => {
|
|
24
|
-
if (typeof env.ASTRO_STUDIO_APP_TOKEN === "string") {
|
|
25
|
-
return env.ASTRO_STUDIO_APP_TOKEN;
|
|
26
|
-
}
|
|
27
|
-
})();
|
|
28
23
|
const locals = {
|
|
29
24
|
runtime: {
|
|
30
25
|
env,
|
|
@@ -9,15 +9,12 @@ const onRequest = async function cloudflareWebSocketMiddleware(context, next) {
|
|
|
9
9
|
}
|
|
10
10
|
const webSocketPair = new WebSocketPair();
|
|
11
11
|
const [client, server] = [webSocketPair[0], webSocketPair[1]];
|
|
12
|
+
server.accept();
|
|
12
13
|
const socket = new WebSocket(request.url);
|
|
13
14
|
attach(socket, server);
|
|
14
15
|
const response = new Response(null, {
|
|
15
16
|
status: 101,
|
|
16
17
|
statusText: "Switching Protocols",
|
|
17
|
-
headers: {
|
|
18
|
-
"Upgrade": "websocket",
|
|
19
|
-
"Connection": "Upgrade"
|
|
20
|
-
},
|
|
21
18
|
webSocket: client
|
|
22
19
|
});
|
|
23
20
|
return { socket, response };
|
package/dist/websocket/server.js
CHANGED
|
@@ -8,6 +8,7 @@ function createWebSocketHandler(app) {
|
|
|
8
8
|
}
|
|
9
9
|
const webSocketPair = new WebSocketPair();
|
|
10
10
|
const [client, server] = [webSocketPair[0], webSocketPair[1]];
|
|
11
|
+
server.accept();
|
|
11
12
|
const response = await app.render(request, {
|
|
12
13
|
locals: {
|
|
13
14
|
isUpgradeRequest: true,
|
|
@@ -17,10 +18,6 @@ function createWebSocketHandler(app) {
|
|
|
17
18
|
const upgradeResponse = new Response(null, {
|
|
18
19
|
status: 101,
|
|
19
20
|
statusText: "Switching Protocols",
|
|
20
|
-
headers: {
|
|
21
|
-
"Upgrade": "websocket",
|
|
22
|
-
"Connection": "Upgrade"
|
|
23
|
-
},
|
|
24
21
|
webSocket: client
|
|
25
22
|
});
|
|
26
23
|
return { socket, response: upgradeResponse };
|
|
@@ -34,15 +31,10 @@ function createWebSocketHandler(app) {
|
|
|
34
31
|
}
|
|
35
32
|
}
|
|
36
33
|
});
|
|
37
|
-
if (response.status === 101
|
|
38
|
-
server.accept();
|
|
34
|
+
if (response.status === 101) {
|
|
39
35
|
return new Response(null, {
|
|
40
36
|
status: 101,
|
|
41
37
|
statusText: "Switching Protocols",
|
|
42
|
-
headers: {
|
|
43
|
-
"Upgrade": "websocket",
|
|
44
|
-
"Connection": "Upgrade"
|
|
45
|
-
},
|
|
46
38
|
webSocket: client
|
|
47
39
|
});
|
|
48
40
|
}
|
|
@@ -6,17 +6,16 @@ export interface WebSocketUpgrade {
|
|
|
6
6
|
response: Response;
|
|
7
7
|
}
|
|
8
8
|
export declare class WebSocket extends EventTarget {
|
|
9
|
-
|
|
9
|
+
static readonly CONNECTING: 0;
|
|
10
|
+
static readonly OPEN: 1;
|
|
11
|
+
static readonly CLOSING: 2;
|
|
12
|
+
static readonly CLOSED: 3;
|
|
10
13
|
private _readyState;
|
|
11
14
|
private _binaryType;
|
|
12
15
|
private _url;
|
|
13
16
|
private _protocol;
|
|
14
17
|
private _extensions;
|
|
15
|
-
private
|
|
16
|
-
static readonly CONNECTING: 0;
|
|
17
|
-
static readonly OPEN: 1;
|
|
18
|
-
static readonly CLOSING: 2;
|
|
19
|
-
static readonly CLOSED: 3;
|
|
18
|
+
private _ws;
|
|
20
19
|
readonly CONNECTING: 0;
|
|
21
20
|
readonly OPEN: 1;
|
|
22
21
|
readonly CLOSING: 2;
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
class WebSocket extends EventTarget {
|
|
2
|
-
_ws;
|
|
3
|
-
_readyState = 0;
|
|
4
|
-
// Use numeric literal instead of static property
|
|
5
|
-
_binaryType = "blob";
|
|
6
|
-
_url = "";
|
|
7
|
-
_protocol = "";
|
|
8
|
-
_extensions = "";
|
|
9
|
-
_bufferedAmount = 0;
|
|
10
2
|
static CONNECTING = 0;
|
|
11
3
|
static OPEN = 1;
|
|
12
4
|
static CLOSING = 2;
|
|
13
5
|
static CLOSED = 3;
|
|
6
|
+
// CloudFlare doesn't use private fields - use simple approach
|
|
7
|
+
_readyState = WebSocket.CONNECTING;
|
|
8
|
+
_binaryType = "blob";
|
|
9
|
+
_url = "";
|
|
10
|
+
_protocol = "";
|
|
11
|
+
_extensions = "";
|
|
12
|
+
_ws;
|
|
14
13
|
// Instance constants
|
|
15
14
|
CONNECTING = 0;
|
|
16
15
|
OPEN = 1;
|
|
@@ -32,7 +31,7 @@ class WebSocket extends EventTarget {
|
|
|
32
31
|
return this._readyState;
|
|
33
32
|
}
|
|
34
33
|
get bufferedAmount() {
|
|
35
|
-
return
|
|
34
|
+
return 0;
|
|
36
35
|
}
|
|
37
36
|
get extensions() {
|
|
38
37
|
return this._extensions;
|
|
@@ -53,11 +52,6 @@ class WebSocket extends EventTarget {
|
|
|
53
52
|
this._readyState = WebSocket.CLOSING;
|
|
54
53
|
if (this._ws) {
|
|
55
54
|
this._ws.close(code, reason);
|
|
56
|
-
} else {
|
|
57
|
-
this._readyState = WebSocket.CLOSED;
|
|
58
|
-
const event = new CloseEvent("close", { code: code || 1e3, reason: reason || "", wasClean: true });
|
|
59
|
-
this.onclose?.(event);
|
|
60
|
-
this.dispatchEvent(event);
|
|
61
55
|
}
|
|
62
56
|
}
|
|
63
57
|
send(data) {
|
|
@@ -65,11 +59,7 @@ class WebSocket extends EventTarget {
|
|
|
65
59
|
throw new Error("WebSocket is not open");
|
|
66
60
|
}
|
|
67
61
|
if (this._ws) {
|
|
68
|
-
|
|
69
|
-
data.arrayBuffer().then((buffer) => this._ws.send(buffer));
|
|
70
|
-
} else {
|
|
71
|
-
this._ws.send(data);
|
|
72
|
-
}
|
|
62
|
+
this._ws.send(data);
|
|
73
63
|
}
|
|
74
64
|
}
|
|
75
65
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zastro-websockets-cloudflare",
|
|
3
3
|
"description": "Deploy your site to Cloudflare Workers/Pages with WebSocket support",
|
|
4
|
-
"version": "12.6.
|
|
4
|
+
"version": "12.6.12-10",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
7
7
|
"author": "Zach Handley <zach@zachhandley.com>",
|
|
@@ -23,20 +23,23 @@
|
|
|
23
23
|
"./image-endpoint": "./dist/entrypoints/image-endpoint.js",
|
|
24
24
|
"./handler": "./dist/utils/handler.js",
|
|
25
25
|
"./package.json": "./package.json",
|
|
26
|
-
"./websocket": "./dist/websocket/index.js"
|
|
26
|
+
"./websocket": "./dist/websocket/index.js",
|
|
27
|
+
"./websocket/middleware.js": "./dist/websocket/middleware.js",
|
|
28
|
+
"./websocket/websocket.js": "./dist/websocket/websocket.js",
|
|
29
|
+
"./websocket/server.js": "./dist/websocket/server.js"
|
|
27
30
|
},
|
|
28
31
|
"files": [
|
|
29
32
|
"dist"
|
|
30
33
|
],
|
|
31
34
|
"dependencies": {
|
|
32
|
-
"@astrojs/internal-helpers": "^0.
|
|
35
|
+
"@astrojs/internal-helpers": "^0.7.5",
|
|
33
36
|
"@astrojs/underscore-redirects": "^1.0.0",
|
|
34
|
-
"@cloudflare/workers-types": "^4.
|
|
35
|
-
"tinyglobby": "^0.2.
|
|
36
|
-
"vite": "^6.
|
|
37
|
-
"wrangler": "
|
|
37
|
+
"@cloudflare/workers-types": "^4.20260116.0",
|
|
38
|
+
"tinyglobby": "^0.2.15",
|
|
39
|
+
"vite": "^6.4.1",
|
|
40
|
+
"wrangler": "4.59.2"
|
|
38
41
|
},
|
|
39
42
|
"peerDependencies": {
|
|
40
|
-
"astro": "^5.
|
|
43
|
+
"astro": "^5.7.0"
|
|
41
44
|
}
|
|
42
45
|
}
|