@cloudflare/pages-shared 0.0.10 → 0.0.11
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/asset-server/handler.ts
CHANGED
|
@@ -12,12 +12,15 @@ import {
|
|
|
12
12
|
TemporaryRedirectResponse,
|
|
13
13
|
} from "./responses";
|
|
14
14
|
import { generateRulesMatcher, replacer } from "./rulesEngine";
|
|
15
|
+
import { stringifyURLToRootRelativePathname } from "./url";
|
|
15
16
|
import type {
|
|
16
17
|
Metadata,
|
|
17
18
|
MetadataHeadersEntries,
|
|
18
19
|
MetadataHeadersRulesV2,
|
|
19
20
|
MetadataHeadersV1,
|
|
20
21
|
MetadataHeadersV2,
|
|
22
|
+
MetadataStaticRedirectEntry,
|
|
23
|
+
MetadataRedirectEntry,
|
|
21
24
|
} from "./metadata";
|
|
22
25
|
|
|
23
26
|
type BodyEncoding = "manual" | "automatic";
|
|
@@ -97,7 +100,16 @@ type FullHandlerContext<AssetEntry, ContentNegotiation, Asset> = {
|
|
|
97
100
|
waitUntil: (promise: Promise<unknown>) => void;
|
|
98
101
|
};
|
|
99
102
|
|
|
100
|
-
export type HandlerContext<
|
|
103
|
+
export type HandlerContext<
|
|
104
|
+
AssetEntry,
|
|
105
|
+
ContentNegotiation extends { encoding: string | null } = {
|
|
106
|
+
encoding: string | null;
|
|
107
|
+
},
|
|
108
|
+
Asset extends { body: ReadableStream | null; contentType: string } = {
|
|
109
|
+
body: ReadableStream | null;
|
|
110
|
+
contentType: string;
|
|
111
|
+
}
|
|
112
|
+
> =
|
|
101
113
|
| FullHandlerContext<AssetEntry, ContentNegotiation, Asset>
|
|
102
114
|
| (Omit<
|
|
103
115
|
FullHandlerContext<AssetEntry, ContentNegotiation, Asset>,
|
|
@@ -192,29 +204,7 @@ export async function generateHandler<
|
|
|
192
204
|
staticRedirectsMatcher() || generateRedirectsMatcher()({ request })[0];
|
|
193
205
|
|
|
194
206
|
if (match) {
|
|
195
|
-
|
|
196
|
-
const destination = new URL(to, request.url);
|
|
197
|
-
const location =
|
|
198
|
-
destination.origin === new URL(request.url).origin
|
|
199
|
-
? `${destination.pathname}${destination.search || search}${
|
|
200
|
-
destination.hash
|
|
201
|
-
}`
|
|
202
|
-
: `${destination.href}${destination.search ? "" : search}${
|
|
203
|
-
destination.hash
|
|
204
|
-
}`;
|
|
205
|
-
switch (status) {
|
|
206
|
-
case 301:
|
|
207
|
-
return new MovedPermanentlyResponse(location);
|
|
208
|
-
case 303:
|
|
209
|
-
return new SeeOtherResponse(location);
|
|
210
|
-
case 307:
|
|
211
|
-
return new TemporaryRedirectResponse(location);
|
|
212
|
-
case 308:
|
|
213
|
-
return new PermanentRedirectResponse(location);
|
|
214
|
-
case 302:
|
|
215
|
-
default:
|
|
216
|
-
return new FoundResponse(location);
|
|
217
|
-
}
|
|
207
|
+
return getResponseFromMatch(match, url);
|
|
218
208
|
}
|
|
219
209
|
|
|
220
210
|
if (!request.method.match(/^(get|head)$/i)) {
|
|
@@ -582,6 +572,49 @@ export async function generateHandler<
|
|
|
582
572
|
}
|
|
583
573
|
}
|
|
584
574
|
|
|
575
|
+
/**
|
|
576
|
+
* Given a redirect match and the request URL, returns the response
|
|
577
|
+
* for the redirect. This function will convert the Location header
|
|
578
|
+
* to be a root-relative path URL if the request origin and destination
|
|
579
|
+
* origins are the same. This is so that if the project is served
|
|
580
|
+
* on multiple domains, the redirects won't take the client off of their current domain.
|
|
581
|
+
*/
|
|
582
|
+
export function getResponseFromMatch(
|
|
583
|
+
{
|
|
584
|
+
status,
|
|
585
|
+
to,
|
|
586
|
+
}: Pick<MetadataStaticRedirectEntry | MetadataRedirectEntry, "status" | "to">,
|
|
587
|
+
requestUrl: URL
|
|
588
|
+
) {
|
|
589
|
+
// Inherit origin from the request URL if not specified in _redirects
|
|
590
|
+
const destination = new URL(to, requestUrl);
|
|
591
|
+
// If _redirects doesn't specify a search, inherit from the request
|
|
592
|
+
destination.search = destination.search || requestUrl.search;
|
|
593
|
+
|
|
594
|
+
// If the redirect destination origin matches the incoming request origin
|
|
595
|
+
// we stringify destination to be a root-relative path, e.g.:
|
|
596
|
+
// https://example.com/foo/bar?baz=1 -> /foo/bar/?baz=1
|
|
597
|
+
// This way, the project can more easily be hosted on multiple domains
|
|
598
|
+
const location =
|
|
599
|
+
destination.origin === requestUrl.origin
|
|
600
|
+
? stringifyURLToRootRelativePathname(destination)
|
|
601
|
+
: destination.toString();
|
|
602
|
+
|
|
603
|
+
switch (status) {
|
|
604
|
+
case 301:
|
|
605
|
+
return new MovedPermanentlyResponse(location);
|
|
606
|
+
case 303:
|
|
607
|
+
return new SeeOtherResponse(location);
|
|
608
|
+
case 307:
|
|
609
|
+
return new TemporaryRedirectResponse(location);
|
|
610
|
+
case 308:
|
|
611
|
+
return new PermanentRedirectResponse(location);
|
|
612
|
+
case 302:
|
|
613
|
+
default:
|
|
614
|
+
return new FoundResponse(location);
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
|
|
585
618
|
// Parses a list such as "deflate, gzip;q=1.0, *;q=0.5" into
|
|
586
619
|
// {deflate: 1, gzip: 1, *: 0.5}
|
|
587
620
|
export function parseQualityWeightedList(list = "") {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stringifies a URL instance to a root-relative path string
|
|
3
|
+
* @param url The URL to stringify
|
|
4
|
+
* @returns A root-relative path string
|
|
5
|
+
*/
|
|
6
|
+
export function stringifyURLToRootRelativePathname(url: URL): string {
|
|
7
|
+
return `${url.pathname}${url.search}${url.hash}`;
|
|
8
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {
|
|
2
|
+
fetch as miniflareFetch,
|
|
3
|
+
Headers as MiniflareHeaders,
|
|
4
|
+
Request as MiniflareRequest,
|
|
5
|
+
Response as MiniflareResponse,
|
|
6
|
+
} from "@miniflare/tre";
|
|
7
|
+
import { polyfill } from ".";
|
|
8
|
+
|
|
9
|
+
polyfill({
|
|
10
|
+
fetch: miniflareFetch,
|
|
11
|
+
Headers: MiniflareHeaders,
|
|
12
|
+
Request: MiniflareRequest,
|
|
13
|
+
Response: MiniflareResponse,
|
|
14
|
+
});
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
SPLAT_REGEX,
|
|
6
6
|
PLACEHOLDER_REGEX,
|
|
7
7
|
} from "./constants";
|
|
8
|
+
import type { MetadataStaticRedirects } from "../asset-server/metadata";
|
|
8
9
|
import type {
|
|
9
10
|
Metadata,
|
|
10
11
|
MetadataRedirects,
|
|
@@ -67,13 +68,17 @@ function constructRedirects({
|
|
|
67
68
|
return {};
|
|
68
69
|
}
|
|
69
70
|
|
|
70
|
-
const staticRedirects:
|
|
71
|
+
const staticRedirects: MetadataStaticRedirects = {};
|
|
71
72
|
const dynamicRedirects: MetadataRedirects = {};
|
|
72
73
|
let canCreateStaticRule = true;
|
|
73
74
|
for (const rule of redirects.rules) {
|
|
74
75
|
if (!rule.from.match(SPLAT_REGEX) && !rule.from.match(PLACEHOLDER_REGEX)) {
|
|
75
76
|
if (canCreateStaticRule) {
|
|
76
|
-
staticRedirects[rule.from] = {
|
|
77
|
+
staticRedirects[rule.from] = {
|
|
78
|
+
status: rule.status,
|
|
79
|
+
to: rule.to,
|
|
80
|
+
lineNumber: rule.lineNumber,
|
|
81
|
+
};
|
|
77
82
|
continue;
|
|
78
83
|
} else {
|
|
79
84
|
logger(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudflare/pages-shared",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/cloudflare/wrangler2.git",
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"metadata-generator/**/*"
|
|
14
14
|
],
|
|
15
15
|
"scripts": {
|
|
16
|
-
"check:type": "tsc"
|
|
16
|
+
"check:type": "tsc",
|
|
17
|
+
"test": "jest"
|
|
17
18
|
},
|
|
18
19
|
"jest": {
|
|
19
20
|
"coverageReporters": [
|