@appwarden/middleware 3.11.4 → 3.11.6
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 +1 -1
- package/chunk-G6BMPIYD.js +11 -0
- package/{chunk-XFG6SUSV.js → chunk-UFWJYCX6.js} +15 -0
- package/cloudflare/astro.d.ts +3 -3
- package/cloudflare/astro.js +58 -51
- package/cloudflare/nextjs.d.ts +2 -2
- package/cloudflare/nextjs.js +5 -6
- package/cloudflare/react-router.d.ts +3 -3
- package/cloudflare/react-router.js +53 -46
- package/cloudflare/tanstack-start.d.ts +2 -2
- package/cloudflare/tanstack-start.js +56 -69
- package/package.json +1 -1
- package/chunk-X7WZVYQS.js +0 -6
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
[](https://github.com/appwarden/middleware)
|
|
5
5
|
[](https://www.npmjs.com/package/@appwarden/middleware)
|
|
6
6
|
[](https://docs.npmjs.com/generating-provenance-statements)
|
|
7
|
-

|
|
8
8
|
[](https://opensource.org/licenses/MIT)
|
|
9
9
|
|
|
10
10
|
## Core Features
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// src/utils/get-now.ts
|
|
2
|
+
var getNowMs = () => typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
3
|
+
var getElapsedMs = (startTime) => Math.round(getNowMs() - startTime);
|
|
4
|
+
var logElapsed = (debug, startTime) => {
|
|
5
|
+
debug(`Middleware executed in ${getElapsedMs(startTime)}ms`);
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export {
|
|
9
|
+
getNowMs,
|
|
10
|
+
logElapsed
|
|
11
|
+
};
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useContentSecurityPolicy
|
|
3
|
+
} from "./chunk-WBWF3PPX.js";
|
|
4
|
+
|
|
5
|
+
// src/utils/apply-content-security-policy-to-response.ts
|
|
6
|
+
var applyContentSecurityPolicyToResponse = async ({
|
|
7
|
+
contentSecurityPolicy,
|
|
8
|
+
...context
|
|
9
|
+
}) => {
|
|
10
|
+
await useContentSecurityPolicy(contentSecurityPolicy)(context, async () => {
|
|
11
|
+
});
|
|
12
|
+
return context.response;
|
|
13
|
+
};
|
|
14
|
+
|
|
1
15
|
// src/utils/is-response-like.ts
|
|
2
16
|
var isResponseLike = (value) => {
|
|
3
17
|
if (!value || typeof value !== "object") return false;
|
|
@@ -7,5 +21,6 @@ var isResponseLike = (value) => {
|
|
|
7
21
|
};
|
|
8
22
|
|
|
9
23
|
export {
|
|
24
|
+
applyContentSecurityPolicyToResponse,
|
|
10
25
|
isResponseLike
|
|
11
26
|
};
|
package/cloudflare/astro.d.ts
CHANGED
|
@@ -270,8 +270,8 @@ declare const AstroCloudflareConfigSchema: z.ZodObject<{
|
|
|
270
270
|
};
|
|
271
271
|
}>>>;
|
|
272
272
|
}, "strip", z.ZodTypeAny, {
|
|
273
|
-
lockPageSlug: string;
|
|
274
273
|
debug: boolean;
|
|
274
|
+
lockPageSlug: string;
|
|
275
275
|
appwardenApiToken: string;
|
|
276
276
|
contentSecurityPolicy?: {
|
|
277
277
|
mode: "disabled" | "report-only" | "enforced";
|
|
@@ -308,6 +308,7 @@ declare const AstroCloudflareConfigSchema: z.ZodObject<{
|
|
|
308
308
|
}, {
|
|
309
309
|
lockPageSlug: string;
|
|
310
310
|
appwardenApiToken: string;
|
|
311
|
+
debug?: string | boolean | undefined;
|
|
311
312
|
contentSecurityPolicy?: {
|
|
312
313
|
mode: "disabled" | "report-only" | "enforced";
|
|
313
314
|
directives: string | {
|
|
@@ -339,7 +340,6 @@ declare const AstroCloudflareConfigSchema: z.ZodObject<{
|
|
|
339
340
|
"require-trusted-types-for"?: string | boolean | string[] | undefined;
|
|
340
341
|
};
|
|
341
342
|
} | undefined;
|
|
342
|
-
debug?: string | boolean | undefined;
|
|
343
343
|
appwardenApiHostname?: string | undefined;
|
|
344
344
|
}>;
|
|
345
345
|
type AstroCloudflareConfig = z.infer<typeof AstroCloudflareConfigSchema>;
|
|
@@ -383,7 +383,7 @@ type AstroConfigFn = (runtime: AstroCloudflareRuntime) => AstroCloudflareConfigI
|
|
|
383
383
|
* ```typescript
|
|
384
384
|
* // src/middleware.ts
|
|
385
385
|
* import { sequence } from "astro:middleware"
|
|
386
|
-
* import { createAppwardenMiddleware } from "@appwarden/middleware/astro"
|
|
386
|
+
* import { createAppwardenMiddleware } from "@appwarden/middleware/cloudflare/astro"
|
|
387
387
|
*
|
|
388
388
|
* const appwarden = createAppwardenMiddleware(({ env }) => ({
|
|
389
389
|
* lockPageSlug: env.APPWARDEN_LOCK_PAGE_SLUG,
|
package/cloudflare/astro.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
|
+
applyContentSecurityPolicyToResponse,
|
|
2
3
|
isResponseLike
|
|
3
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-UFWJYCX6.js";
|
|
5
|
+
import "../chunk-WBWF3PPX.js";
|
|
4
6
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
getNowMs
|
|
9
|
-
} from "../chunk-X7WZVYQS.js";
|
|
7
|
+
getNowMs,
|
|
8
|
+
logElapsed
|
|
9
|
+
} from "../chunk-G6BMPIYD.js";
|
|
10
10
|
import {
|
|
11
11
|
checkLockStatus
|
|
12
12
|
} from "../chunk-QC2ZUZWY.js";
|
|
@@ -53,6 +53,31 @@ function createAppwardenMiddleware(configFn) {
|
|
|
53
53
|
return async (context, next) => {
|
|
54
54
|
const startTime = getNowMs();
|
|
55
55
|
const { request } = context;
|
|
56
|
+
let config;
|
|
57
|
+
let debugFn;
|
|
58
|
+
let requestUrl;
|
|
59
|
+
const applyCspToResponse = async (response2) => {
|
|
60
|
+
if (!config.contentSecurityPolicy || !isResponseLike(response2)) {
|
|
61
|
+
return response2;
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
return await applyContentSecurityPolicyToResponse({
|
|
65
|
+
request,
|
|
66
|
+
response: response2,
|
|
67
|
+
hostname: requestUrl.hostname,
|
|
68
|
+
waitUntil,
|
|
69
|
+
debug: debugFn,
|
|
70
|
+
contentSecurityPolicy: config.contentSecurityPolicy
|
|
71
|
+
});
|
|
72
|
+
} catch (error) {
|
|
73
|
+
console.error(
|
|
74
|
+
printMessage(
|
|
75
|
+
`Failed to apply content security policy: ${error instanceof Error ? error.message : String(error)}`
|
|
76
|
+
)
|
|
77
|
+
);
|
|
78
|
+
return response2;
|
|
79
|
+
}
|
|
80
|
+
};
|
|
56
81
|
const locals = context.locals;
|
|
57
82
|
try {
|
|
58
83
|
const runtime = locals.runtime;
|
|
@@ -74,9 +99,9 @@ function createAppwardenMiddleware(configFn) {
|
|
|
74
99
|
);
|
|
75
100
|
return next();
|
|
76
101
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
102
|
+
config = validationResult.data;
|
|
103
|
+
debugFn = debug(config.debug);
|
|
104
|
+
requestUrl = new URL(request.url);
|
|
80
105
|
const isHTML = isHTMLRequest(request);
|
|
81
106
|
debugFn(
|
|
82
107
|
`Appwarden middleware invoked for ${requestUrl.pathname}`,
|
|
@@ -86,51 +111,29 @@ function createAppwardenMiddleware(configFn) {
|
|
|
86
111
|
return next();
|
|
87
112
|
}
|
|
88
113
|
if (isOnLockPage(config.lockPageSlug, request.url)) {
|
|
89
|
-
debugFn("Already on lock page - skipping");
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const result = await checkLockStatus({
|
|
93
|
-
request,
|
|
94
|
-
appwardenApiToken: config.appwardenApiToken,
|
|
95
|
-
appwardenApiHostname: config.appwardenApiHostname,
|
|
96
|
-
debug: config.debug,
|
|
97
|
-
lockPageSlug: config.lockPageSlug,
|
|
98
|
-
waitUntil
|
|
99
|
-
});
|
|
100
|
-
if (result.isLocked) {
|
|
101
|
-
const lockPageUrl = buildLockPageUrl(config.lockPageSlug, request.url);
|
|
102
|
-
debugFn(`Website is locked - redirecting to ${lockPageUrl.pathname}`);
|
|
103
|
-
if (context.redirect) {
|
|
104
|
-
return context.redirect(
|
|
105
|
-
lockPageUrl.toString(),
|
|
106
|
-
TEMPORARY_REDIRECT_STATUS
|
|
107
|
-
);
|
|
108
|
-
}
|
|
109
|
-
return createRedirect(lockPageUrl);
|
|
110
|
-
}
|
|
111
|
-
debugFn("Website is unlocked");
|
|
112
|
-
const response = await next();
|
|
113
|
-
if (config.contentSecurityPolicy && isResponseLike(response)) {
|
|
114
|
-
const cspContext = {
|
|
114
|
+
debugFn("Already on lock page - skipping lock status check");
|
|
115
|
+
} else {
|
|
116
|
+
const result = await checkLockStatus({
|
|
115
117
|
request,
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
118
|
+
appwardenApiToken: config.appwardenApiToken,
|
|
119
|
+
appwardenApiHostname: config.appwardenApiHostname,
|
|
120
|
+
debug: config.debug,
|
|
121
|
+
lockPageSlug: config.lockPageSlug,
|
|
122
|
+
waitUntil
|
|
123
|
+
});
|
|
124
|
+
if (result.isLocked) {
|
|
125
|
+
const lockPageUrl = buildLockPageUrl(config.lockPageSlug, request.url);
|
|
126
|
+
debugFn(`Website is locked - redirecting to ${lockPageUrl.pathname}`);
|
|
127
|
+
if (context.redirect) {
|
|
128
|
+
return context.redirect(
|
|
129
|
+
lockPageUrl.toString(),
|
|
130
|
+
TEMPORARY_REDIRECT_STATUS
|
|
131
|
+
);
|
|
124
132
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
debugFn(`Middleware executed in ${elapsed2}ms`);
|
|
129
|
-
return cspContext.response;
|
|
133
|
+
return createRedirect(lockPageUrl);
|
|
134
|
+
}
|
|
135
|
+
debugFn("Website is unlocked");
|
|
130
136
|
}
|
|
131
|
-
const elapsed = Math.round(getNowMs() - startTime);
|
|
132
|
-
debugFn(`Middleware executed in ${elapsed}ms`);
|
|
133
|
-
return response;
|
|
134
137
|
} catch (error) {
|
|
135
138
|
if (isResponseLike(error)) {
|
|
136
139
|
throw error;
|
|
@@ -142,6 +145,10 @@ function createAppwardenMiddleware(configFn) {
|
|
|
142
145
|
);
|
|
143
146
|
return next();
|
|
144
147
|
}
|
|
148
|
+
const response = await next();
|
|
149
|
+
const finalResponse = await applyCspToResponse(response);
|
|
150
|
+
logElapsed(debugFn, startTime);
|
|
151
|
+
return finalResponse;
|
|
145
152
|
};
|
|
146
153
|
}
|
|
147
154
|
export {
|
package/cloudflare/nextjs.d.ts
CHANGED
|
@@ -329,8 +329,8 @@ declare const NextJsCloudflareConfigSchema: z.ZodObject<{
|
|
|
329
329
|
};
|
|
330
330
|
}>>>;
|
|
331
331
|
}, "strip", z.ZodTypeAny, {
|
|
332
|
-
lockPageSlug: string;
|
|
333
332
|
debug: boolean;
|
|
333
|
+
lockPageSlug: string;
|
|
334
334
|
appwardenApiToken: string;
|
|
335
335
|
contentSecurityPolicy?: {
|
|
336
336
|
mode: "disabled" | "report-only" | "enforced";
|
|
@@ -367,6 +367,7 @@ declare const NextJsCloudflareConfigSchema: z.ZodObject<{
|
|
|
367
367
|
}, {
|
|
368
368
|
lockPageSlug: string;
|
|
369
369
|
appwardenApiToken: string;
|
|
370
|
+
debug?: string | boolean | undefined;
|
|
370
371
|
contentSecurityPolicy?: {
|
|
371
372
|
mode: "disabled" | "report-only" | "enforced";
|
|
372
373
|
directives: string | {
|
|
@@ -398,7 +399,6 @@ declare const NextJsCloudflareConfigSchema: z.ZodObject<{
|
|
|
398
399
|
"require-trusted-types-for"?: string | boolean | string[] | undefined;
|
|
399
400
|
};
|
|
400
401
|
} | undefined;
|
|
401
|
-
debug?: string | boolean | undefined;
|
|
402
402
|
appwardenApiHostname?: string | undefined;
|
|
403
403
|
}>;
|
|
404
404
|
type NextJsCloudflareConfig = z.infer<typeof NextJsCloudflareConfigSchema>;
|
package/cloudflare/nextjs.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
-
getNowMs
|
|
3
|
-
|
|
2
|
+
getNowMs,
|
|
3
|
+
logElapsed
|
|
4
|
+
} from "../chunk-G6BMPIYD.js";
|
|
4
5
|
import {
|
|
5
6
|
checkLockStatus
|
|
6
7
|
} from "../chunk-QC2ZUZWY.js";
|
|
@@ -112,12 +113,10 @@ function createAppwardenMiddleware(configFn) {
|
|
|
112
113
|
);
|
|
113
114
|
const response = NextResponse.next();
|
|
114
115
|
response.headers.set(headerName, headerValue);
|
|
115
|
-
|
|
116
|
-
debugFn(`Middleware executed in ${elapsed2}ms`);
|
|
116
|
+
logElapsed(debugFn, startTime);
|
|
117
117
|
return response;
|
|
118
118
|
}
|
|
119
|
-
|
|
120
|
-
debugFn(`Middleware executed in ${elapsed}ms`);
|
|
119
|
+
logElapsed(debugFn, startTime);
|
|
121
120
|
return NextResponse.next();
|
|
122
121
|
} catch (error) {
|
|
123
122
|
console.error(
|
|
@@ -268,8 +268,8 @@ declare const ReactRouterCloudflareConfigSchema: z.ZodObject<{
|
|
|
268
268
|
};
|
|
269
269
|
}>>>;
|
|
270
270
|
}, "strip", z.ZodTypeAny, {
|
|
271
|
-
lockPageSlug: string;
|
|
272
271
|
debug: boolean;
|
|
272
|
+
lockPageSlug: string;
|
|
273
273
|
appwardenApiToken: string;
|
|
274
274
|
contentSecurityPolicy?: {
|
|
275
275
|
mode: "disabled" | "report-only" | "enforced";
|
|
@@ -306,6 +306,7 @@ declare const ReactRouterCloudflareConfigSchema: z.ZodObject<{
|
|
|
306
306
|
}, {
|
|
307
307
|
lockPageSlug: string;
|
|
308
308
|
appwardenApiToken: string;
|
|
309
|
+
debug?: string | boolean | undefined;
|
|
309
310
|
contentSecurityPolicy?: {
|
|
310
311
|
mode: "disabled" | "report-only" | "enforced";
|
|
311
312
|
directives: string | {
|
|
@@ -337,7 +338,6 @@ declare const ReactRouterCloudflareConfigSchema: z.ZodObject<{
|
|
|
337
338
|
"require-trusted-types-for"?: string | boolean | string[] | undefined;
|
|
338
339
|
};
|
|
339
340
|
} | undefined;
|
|
340
|
-
debug?: string | boolean | undefined;
|
|
341
341
|
appwardenApiHostname?: string | undefined;
|
|
342
342
|
}>;
|
|
343
343
|
type ReactRouterCloudflareConfig = z.infer<typeof ReactRouterCloudflareConfigSchema>;
|
|
@@ -377,7 +377,7 @@ type ReactRouterMiddlewareFunction = (args: ReactRouterMiddlewareArgs, next: ()
|
|
|
377
377
|
* ```typescript
|
|
378
378
|
* // app/root.tsx
|
|
379
379
|
* import { env } from "cloudflare:workers"
|
|
380
|
-
* import { createAppwardenMiddleware } from "@appwarden/middleware/react-router"
|
|
380
|
+
* import { createAppwardenMiddleware } from "@appwarden/middleware/cloudflare/react-router"
|
|
381
381
|
*
|
|
382
382
|
* export const unstable_middleware = [
|
|
383
383
|
* createAppwardenMiddleware(() => ({
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
|
+
applyContentSecurityPolicyToResponse,
|
|
2
3
|
isResponseLike
|
|
3
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-UFWJYCX6.js";
|
|
5
|
+
import "../chunk-WBWF3PPX.js";
|
|
4
6
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
getNowMs
|
|
9
|
-
} from "../chunk-X7WZVYQS.js";
|
|
7
|
+
getNowMs,
|
|
8
|
+
logElapsed
|
|
9
|
+
} from "../chunk-G6BMPIYD.js";
|
|
10
10
|
import {
|
|
11
11
|
checkLockStatus
|
|
12
12
|
} from "../chunk-QC2ZUZWY.js";
|
|
@@ -52,6 +52,31 @@ function createAppwardenMiddleware(configFn) {
|
|
|
52
52
|
return async (args, next) => {
|
|
53
53
|
const startTime = getNowMs();
|
|
54
54
|
const { request } = args;
|
|
55
|
+
let config;
|
|
56
|
+
let debugFn;
|
|
57
|
+
let requestUrl;
|
|
58
|
+
const applyCspToResponse = async (response2) => {
|
|
59
|
+
if (!config.contentSecurityPolicy || !isResponseLike(response2)) {
|
|
60
|
+
return response2;
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
return await applyContentSecurityPolicyToResponse({
|
|
64
|
+
request,
|
|
65
|
+
response: response2,
|
|
66
|
+
hostname: requestUrl.hostname,
|
|
67
|
+
waitUntil,
|
|
68
|
+
debug: debugFn,
|
|
69
|
+
contentSecurityPolicy: config.contentSecurityPolicy
|
|
70
|
+
});
|
|
71
|
+
} catch (error) {
|
|
72
|
+
console.error(
|
|
73
|
+
printMessage(
|
|
74
|
+
`Failed to apply content security policy: ${error instanceof Error ? error.message : String(error)}`
|
|
75
|
+
)
|
|
76
|
+
);
|
|
77
|
+
return response2;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
55
80
|
try {
|
|
56
81
|
const configInput = configFn();
|
|
57
82
|
const validationResult = ReactRouterCloudflareConfigSchema.safeParse(configInput);
|
|
@@ -63,9 +88,9 @@ function createAppwardenMiddleware(configFn) {
|
|
|
63
88
|
);
|
|
64
89
|
return next();
|
|
65
90
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
91
|
+
config = validationResult.data;
|
|
92
|
+
debugFn = debug(config.debug);
|
|
93
|
+
requestUrl = new URL(request.url);
|
|
69
94
|
const isHTML = isHTMLRequest(request);
|
|
70
95
|
debugFn(
|
|
71
96
|
`Appwarden middleware invoked for ${requestUrl.pathname}`,
|
|
@@ -75,45 +100,23 @@ function createAppwardenMiddleware(configFn) {
|
|
|
75
100
|
return next();
|
|
76
101
|
}
|
|
77
102
|
if (isOnLockPage(config.lockPageSlug, request.url)) {
|
|
78
|
-
debugFn("Already on lock page - skipping");
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const result = await checkLockStatus({
|
|
82
|
-
request,
|
|
83
|
-
appwardenApiToken: config.appwardenApiToken,
|
|
84
|
-
appwardenApiHostname: config.appwardenApiHostname,
|
|
85
|
-
debug: config.debug,
|
|
86
|
-
lockPageSlug: config.lockPageSlug,
|
|
87
|
-
waitUntil
|
|
88
|
-
});
|
|
89
|
-
if (result.isLocked) {
|
|
90
|
-
const lockPageUrl = buildLockPageUrl(config.lockPageSlug, request.url);
|
|
91
|
-
debugFn(`Website is locked - redirecting to ${lockPageUrl.pathname}`);
|
|
92
|
-
throw createRedirect(lockPageUrl);
|
|
93
|
-
}
|
|
94
|
-
debugFn("Website is unlocked");
|
|
95
|
-
const response = await next();
|
|
96
|
-
if (config.contentSecurityPolicy && isResponseLike(response)) {
|
|
97
|
-
const cspContext = {
|
|
103
|
+
debugFn("Already on lock page - skipping lock status check");
|
|
104
|
+
} else {
|
|
105
|
+
const result = await checkLockStatus({
|
|
98
106
|
request,
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
debugFn(`Middleware executed in ${elapsed2}ms`);
|
|
112
|
-
return cspContext.response;
|
|
107
|
+
appwardenApiToken: config.appwardenApiToken,
|
|
108
|
+
appwardenApiHostname: config.appwardenApiHostname,
|
|
109
|
+
debug: config.debug,
|
|
110
|
+
lockPageSlug: config.lockPageSlug,
|
|
111
|
+
waitUntil
|
|
112
|
+
});
|
|
113
|
+
if (result.isLocked) {
|
|
114
|
+
const lockPageUrl = buildLockPageUrl(config.lockPageSlug, request.url);
|
|
115
|
+
debugFn(`Website is locked - redirecting to ${lockPageUrl.pathname}`);
|
|
116
|
+
throw createRedirect(lockPageUrl);
|
|
117
|
+
}
|
|
118
|
+
debugFn("Website is unlocked");
|
|
113
119
|
}
|
|
114
|
-
const elapsed = Math.round(getNowMs() - startTime);
|
|
115
|
-
debugFn(`Middleware executed in ${elapsed}ms`);
|
|
116
|
-
return response;
|
|
117
120
|
} catch (error) {
|
|
118
121
|
if (isResponseLike(error)) {
|
|
119
122
|
throw error;
|
|
@@ -125,6 +128,10 @@ function createAppwardenMiddleware(configFn) {
|
|
|
125
128
|
);
|
|
126
129
|
return next();
|
|
127
130
|
}
|
|
131
|
+
const response = await next();
|
|
132
|
+
const finalResponse = isResponseLike(response) ? await applyCspToResponse(response) : response;
|
|
133
|
+
logElapsed(debugFn, startTime);
|
|
134
|
+
return finalResponse;
|
|
128
135
|
};
|
|
129
136
|
}
|
|
130
137
|
export {
|
|
@@ -268,8 +268,8 @@ declare const TanStackStartCloudflareConfigSchema: z.ZodObject<{
|
|
|
268
268
|
};
|
|
269
269
|
}>>>;
|
|
270
270
|
}, "strip", z.ZodTypeAny, {
|
|
271
|
-
lockPageSlug: string;
|
|
272
271
|
debug: boolean;
|
|
272
|
+
lockPageSlug: string;
|
|
273
273
|
appwardenApiToken: string;
|
|
274
274
|
contentSecurityPolicy?: {
|
|
275
275
|
mode: "disabled" | "report-only" | "enforced";
|
|
@@ -306,6 +306,7 @@ declare const TanStackStartCloudflareConfigSchema: z.ZodObject<{
|
|
|
306
306
|
}, {
|
|
307
307
|
lockPageSlug: string;
|
|
308
308
|
appwardenApiToken: string;
|
|
309
|
+
debug?: string | boolean | undefined;
|
|
309
310
|
contentSecurityPolicy?: {
|
|
310
311
|
mode: "disabled" | "report-only" | "enforced";
|
|
311
312
|
directives: string | {
|
|
@@ -337,7 +338,6 @@ declare const TanStackStartCloudflareConfigSchema: z.ZodObject<{
|
|
|
337
338
|
"require-trusted-types-for"?: string | boolean | string[] | undefined;
|
|
338
339
|
};
|
|
339
340
|
} | undefined;
|
|
340
|
-
debug?: string | boolean | undefined;
|
|
341
341
|
appwardenApiHostname?: string | undefined;
|
|
342
342
|
}>;
|
|
343
343
|
type TanStackStartCloudflareConfig = z.infer<typeof TanStackStartCloudflareConfigSchema>;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
|
+
applyContentSecurityPolicyToResponse,
|
|
2
3
|
isResponseLike
|
|
3
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-UFWJYCX6.js";
|
|
5
|
+
import "../chunk-WBWF3PPX.js";
|
|
4
6
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
getNowMs
|
|
9
|
-
} from "../chunk-X7WZVYQS.js";
|
|
7
|
+
getNowMs,
|
|
8
|
+
logElapsed
|
|
9
|
+
} from "../chunk-G6BMPIYD.js";
|
|
10
10
|
import {
|
|
11
11
|
checkLockStatus
|
|
12
12
|
} from "../chunk-QC2ZUZWY.js";
|
|
@@ -52,6 +52,31 @@ function createAppwardenMiddleware(configFn) {
|
|
|
52
52
|
const middleware = async (args) => {
|
|
53
53
|
const startTime = getNowMs();
|
|
54
54
|
const { request, next } = args;
|
|
55
|
+
let config;
|
|
56
|
+
let debugFn;
|
|
57
|
+
let requestUrl;
|
|
58
|
+
const applyCspToResponse = async (response2) => {
|
|
59
|
+
if (!config.contentSecurityPolicy || !isResponseLike(response2)) {
|
|
60
|
+
return response2;
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
return await applyContentSecurityPolicyToResponse({
|
|
64
|
+
request,
|
|
65
|
+
response: response2,
|
|
66
|
+
hostname: requestUrl.hostname,
|
|
67
|
+
waitUntil,
|
|
68
|
+
debug: debugFn,
|
|
69
|
+
contentSecurityPolicy: config.contentSecurityPolicy
|
|
70
|
+
});
|
|
71
|
+
} catch (error) {
|
|
72
|
+
console.error(
|
|
73
|
+
printMessage(
|
|
74
|
+
`Failed to apply content security policy: ${error instanceof Error ? error.message : String(error)}`
|
|
75
|
+
)
|
|
76
|
+
);
|
|
77
|
+
return response2;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
55
80
|
try {
|
|
56
81
|
const rawConfig = configFn();
|
|
57
82
|
const validationResult = TanStackStartCloudflareConfigSchema.safeParse(rawConfig);
|
|
@@ -63,9 +88,9 @@ function createAppwardenMiddleware(configFn) {
|
|
|
63
88
|
);
|
|
64
89
|
return next();
|
|
65
90
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
91
|
+
config = validationResult.data;
|
|
92
|
+
debugFn = debug(config.debug ?? false);
|
|
93
|
+
requestUrl = new URL(request.url);
|
|
69
94
|
const isHTML = isHTMLRequest(request);
|
|
70
95
|
debugFn(
|
|
71
96
|
`Appwarden middleware invoked for ${requestUrl.pathname}`,
|
|
@@ -75,69 +100,27 @@ function createAppwardenMiddleware(configFn) {
|
|
|
75
100
|
return next();
|
|
76
101
|
}
|
|
77
102
|
if (isOnLockPage(config.lockPageSlug, request.url)) {
|
|
78
|
-
debugFn("Already on lock page - skipping");
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (config.contentSecurityPolicy && isResponseLike(redirectResponse)) {
|
|
94
|
-
const cspContext = {
|
|
95
|
-
request,
|
|
96
|
-
response: redirectResponse,
|
|
97
|
-
hostname: requestUrl.hostname,
|
|
98
|
-
waitUntil,
|
|
99
|
-
debug: debugFn
|
|
100
|
-
};
|
|
101
|
-
await useContentSecurityPolicy(config.contentSecurityPolicy)(
|
|
102
|
-
cspContext,
|
|
103
|
-
async () => {
|
|
104
|
-
}
|
|
103
|
+
debugFn("Already on lock page - skipping lock status check");
|
|
104
|
+
} else {
|
|
105
|
+
const lockStatus = await checkLockStatus({
|
|
106
|
+
request,
|
|
107
|
+
appwardenApiToken: config.appwardenApiToken,
|
|
108
|
+
appwardenApiHostname: config.appwardenApiHostname,
|
|
109
|
+
debug: config.debug,
|
|
110
|
+
lockPageSlug: config.lockPageSlug,
|
|
111
|
+
waitUntil
|
|
112
|
+
});
|
|
113
|
+
if (lockStatus.isLocked) {
|
|
114
|
+
const lockPageUrl = buildLockPageUrl(config.lockPageSlug, request.url);
|
|
115
|
+
debugFn(`Website is locked - redirecting to ${lockPageUrl.pathname}`);
|
|
116
|
+
const redirectResponse = await applyCspToResponse(
|
|
117
|
+
createRedirect(lockPageUrl)
|
|
105
118
|
);
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
throw cspContext.response;
|
|
119
|
+
logElapsed(debugFn, startTime);
|
|
120
|
+
throw redirectResponse;
|
|
109
121
|
}
|
|
110
|
-
|
|
111
|
-
debugFn(`Middleware executed in ${elapsed2}ms`);
|
|
112
|
-
throw redirectResponse;
|
|
113
|
-
}
|
|
114
|
-
debugFn("Website is unlocked");
|
|
115
|
-
const result = await next();
|
|
116
|
-
const { response } = result;
|
|
117
|
-
if (config.contentSecurityPolicy && isResponseLike(response)) {
|
|
118
|
-
const cspContext = {
|
|
119
|
-
request,
|
|
120
|
-
response,
|
|
121
|
-
hostname: requestUrl.hostname,
|
|
122
|
-
waitUntil,
|
|
123
|
-
debug: debugFn
|
|
124
|
-
};
|
|
125
|
-
await useContentSecurityPolicy(config.contentSecurityPolicy)(
|
|
126
|
-
cspContext,
|
|
127
|
-
async () => {
|
|
128
|
-
}
|
|
129
|
-
// no-op next
|
|
130
|
-
);
|
|
131
|
-
const elapsed2 = Math.round(getNowMs() - startTime);
|
|
132
|
-
debugFn(`Middleware executed in ${elapsed2}ms`);
|
|
133
|
-
return {
|
|
134
|
-
...result,
|
|
135
|
-
response: cspContext.response
|
|
136
|
-
};
|
|
122
|
+
debugFn("Website is unlocked");
|
|
137
123
|
}
|
|
138
|
-
const elapsed = Math.round(getNowMs() - startTime);
|
|
139
|
-
debugFn(`Middleware executed in ${elapsed}ms`);
|
|
140
|
-
return result;
|
|
141
124
|
} catch (error) {
|
|
142
125
|
if (isResponseLike(error)) {
|
|
143
126
|
throw error;
|
|
@@ -149,6 +132,10 @@ function createAppwardenMiddleware(configFn) {
|
|
|
149
132
|
);
|
|
150
133
|
return next();
|
|
151
134
|
}
|
|
135
|
+
const result = await next();
|
|
136
|
+
const response = isResponseLike(result.response) ? await applyCspToResponse(result.response) : result.response;
|
|
137
|
+
logElapsed(debugFn, startTime);
|
|
138
|
+
return response === result.response ? result : { ...result, response };
|
|
152
139
|
};
|
|
153
140
|
return middleware;
|
|
154
141
|
}
|
package/package.json
CHANGED