forked from angular/angular-cli
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrequest.ts
More file actions
106 lines (94 loc) · 3.43 KB
/
request.ts
File metadata and controls
106 lines (94 loc) · 3.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import type { IncomingHttpHeaders, IncomingMessage } from 'node:http';
import type { Http2ServerRequest } from 'node:http2';
import { getFirstHeaderValue } from '../../src/utils/validation';
/**
* A set containing all the pseudo-headers defined in the HTTP/2 specification.
*
* This set can be used to filter out pseudo-headers from a list of headers,
* as they are not allowed to be set directly using the `Node.js` Undici API or
* the web `Headers` API.
*/
const HTTP2_PSEUDO_HEADERS = new Set([':method', ':scheme', ':authority', ':path', ':status']);
/**
* Converts a Node.js `IncomingMessage` or `Http2ServerRequest` into a
* Web Standard `Request` object.
*
* This function adapts the Node.js request objects to a format that can
* be used by web platform APIs.
*
* @param nodeRequest - The Node.js request object (`IncomingMessage` or `Http2ServerRequest`) to convert.
* @returns A Web Standard `Request` object.
*/
export function createWebRequestFromNodeRequest(
nodeRequest: IncomingMessage | Http2ServerRequest,
): Request {
const { headers, method = 'GET' } = nodeRequest;
const withBody = method !== 'GET' && method !== 'HEAD';
const referrer = headers.referer && URL.canParse(headers.referer) ? headers.referer : undefined;
return new Request(createRequestUrl(nodeRequest), {
method,
headers: createRequestHeaders(headers),
body: withBody ? nodeRequest : undefined,
duplex: withBody ? 'half' : undefined,
referrer,
});
}
/**
* Creates a `Headers` object from Node.js `IncomingHttpHeaders`.
*
* @param nodeHeaders - The Node.js `IncomingHttpHeaders` object to convert.
* @returns A `Headers` object containing the converted headers.
*/
function createRequestHeaders(nodeHeaders: IncomingHttpHeaders): Headers {
const headers = new Headers();
for (const [name, value] of Object.entries(nodeHeaders)) {
if (HTTP2_PSEUDO_HEADERS.has(name)) {
continue;
}
if (typeof value === 'string') {
headers.append(name, value);
} else if (Array.isArray(value)) {
for (const item of value) {
headers.append(name, item);
}
}
}
return headers;
}
/**
* Creates a `URL` object from a Node.js `IncomingMessage`, taking into account the protocol, host, and port.
*
* @param nodeRequest - The Node.js `IncomingMessage` or `Http2ServerRequest` object to extract URL information from.
* @returns A `URL` object representing the request URL.
*/
export function createRequestUrl(nodeRequest: IncomingMessage | Http2ServerRequest): URL {
const {
headers,
socket,
url = '',
originalUrl,
} = nodeRequest as IncomingMessage & { originalUrl?: string };
const protocol =
getFirstHeaderValue(headers['x-forwarded-proto']) ??
('encrypted' in socket && socket.encrypted ? 'https' : 'http');
const hostname =
getFirstHeaderValue(headers['x-forwarded-host']) ?? headers.host ?? headers[':authority'];
if (Array.isArray(hostname)) {
throw new Error('host value cannot be an array.');
}
let hostnameWithPort = hostname;
if (!hostname?.includes(':')) {
const port = getFirstHeaderValue(headers['x-forwarded-port']);
if (port) {
hostnameWithPort += `:${port}`;
}
}
return new URL(`${protocol}://${hostnameWithPort}${originalUrl ?? url}`);
}