netlify-cli 12.7.2 → 12.9.0
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/npm-shrinkwrap.json +567 -631
- package/package.json +12 -12
- package/src/commands/addons/addons.mjs +0 -1
- package/src/commands/base-command.mjs +18 -2
- package/src/commands/deploy/deploy.mjs +11 -2
- package/src/commands/dev/dev.mjs +43 -8
- package/src/commands/env/env-import.mjs +10 -1
- package/src/commands/init/init.mjs +8 -1
- package/src/commands/link/link.mjs +8 -1
- package/src/commands/serve/index.mjs +1 -0
- package/src/commands/serve/serve.mjs +6 -1
- package/src/functions-templates/go/hello-world/go.mod +1 -1
- package/src/functions-templates/javascript/auth-fetch/package-lock.json +7 -7
- package/src/functions-templates/javascript/google-analytics/package-lock.json +6 -6
- package/src/functions-templates/javascript/token-hider/package-lock.json +6 -6
- package/src/functions-templates/rust/hello-world/Cargo.lock +571 -135
- package/src/functions-templates/rust/hello-world/Cargo.toml +3 -3
- package/src/functions-templates/typescript/hello-world/package-lock.json +12 -12
- package/src/lib/edge-functions/headers.mjs +3 -3
- package/src/lib/edge-functions/proxy.mjs +6 -8
- package/src/lib/edge-functions/registry.mjs +9 -1
- package/src/lib/functions/server.mjs +1 -1
- package/src/lib/functions/synchronous.mjs +28 -7
- package/src/utils/get-repo-data.mjs +1 -1
- package/src/utils/proxy-server.mjs +3 -0
- package/src/utils/proxy.mjs +57 -13
- package/src/utils/redirects.mjs +6 -0
- package/src/utils/sign-redirect.mjs +16 -0
|
@@ -6,9 +6,9 @@ version = "0.1.0"
|
|
|
6
6
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
7
7
|
|
|
8
8
|
[dependencies]
|
|
9
|
-
aws_lambda_events = "0.7.
|
|
9
|
+
aws_lambda_events = "0.7.3"
|
|
10
10
|
http = "0.2.8"
|
|
11
|
-
lambda_runtime = "0.7.
|
|
11
|
+
lambda_runtime = "0.7.3"
|
|
12
12
|
log = "0.4.17"
|
|
13
13
|
simple_logger = "1.16.0"
|
|
14
|
-
tokio = "1.
|
|
14
|
+
tokio = "1.24.1"
|
|
@@ -26,9 +26,9 @@
|
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
28
|
"node_modules/@types/node": {
|
|
29
|
-
"version": "14.18.
|
|
30
|
-
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.
|
|
31
|
-
"integrity": "sha512-
|
|
29
|
+
"version": "14.18.36",
|
|
30
|
+
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.36.tgz",
|
|
31
|
+
"integrity": "sha512-FXKWbsJ6a1hIrRxv+FoukuHnGTgEzKYGi7kilfMae96AL9UNkPFNWJEEYWzdRI9ooIkbr4AKldyuSTLql06vLQ=="
|
|
32
32
|
},
|
|
33
33
|
"node_modules/is-promise": {
|
|
34
34
|
"version": "4.0.0",
|
|
@@ -36,9 +36,9 @@
|
|
|
36
36
|
"integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="
|
|
37
37
|
},
|
|
38
38
|
"node_modules/typescript": {
|
|
39
|
-
"version": "4.9.
|
|
40
|
-
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.
|
|
41
|
-
"integrity": "sha512-
|
|
39
|
+
"version": "4.9.4",
|
|
40
|
+
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz",
|
|
41
|
+
"integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==",
|
|
42
42
|
"bin": {
|
|
43
43
|
"tsc": "bin/tsc",
|
|
44
44
|
"tsserver": "bin/tsserver"
|
|
@@ -58,9 +58,9 @@
|
|
|
58
58
|
}
|
|
59
59
|
},
|
|
60
60
|
"@types/node": {
|
|
61
|
-
"version": "14.18.
|
|
62
|
-
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.
|
|
63
|
-
"integrity": "sha512-
|
|
61
|
+
"version": "14.18.36",
|
|
62
|
+
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.36.tgz",
|
|
63
|
+
"integrity": "sha512-FXKWbsJ6a1hIrRxv+FoukuHnGTgEzKYGi7kilfMae96AL9UNkPFNWJEEYWzdRI9ooIkbr4AKldyuSTLql06vLQ=="
|
|
64
64
|
},
|
|
65
65
|
"is-promise": {
|
|
66
66
|
"version": "4.0.0",
|
|
@@ -68,9 +68,9 @@
|
|
|
68
68
|
"integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="
|
|
69
69
|
},
|
|
70
70
|
"typescript": {
|
|
71
|
-
"version": "4.9.
|
|
72
|
-
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.
|
|
73
|
-
"integrity": "sha512-
|
|
71
|
+
"version": "4.9.4",
|
|
72
|
+
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz",
|
|
73
|
+
"integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg=="
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
const headers = {
|
|
2
2
|
ForwardedHost: 'x-forwarded-host',
|
|
3
|
-
|
|
4
|
-
Functions: 'x-deno-functions',
|
|
3
|
+
Functions: 'x-nf-edge-functions',
|
|
5
4
|
Geo: 'x-nf-geo',
|
|
6
|
-
Passthrough: 'x-
|
|
5
|
+
Passthrough: 'x-nf-passthrough',
|
|
7
6
|
RequestID: 'X-NF-Request-ID',
|
|
8
7
|
IP: 'x-nf-client-connection-ip',
|
|
9
8
|
Site: 'X-NF-Site-Info',
|
|
9
|
+
DebugLogging: 'x-nf-debug-logging',
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export default headers
|
|
@@ -56,19 +56,20 @@ export const createSiteInfoHeader = (siteInfo = {}) => {
|
|
|
56
56
|
export const initializeProxy = async ({
|
|
57
57
|
config,
|
|
58
58
|
configPath,
|
|
59
|
+
debug,
|
|
59
60
|
env: configEnv,
|
|
60
61
|
geoCountry,
|
|
61
62
|
geolocationMode,
|
|
62
63
|
getUpdatedConfig,
|
|
63
64
|
inspectSettings,
|
|
65
|
+
mainPort,
|
|
64
66
|
offline,
|
|
67
|
+
passthroughPort,
|
|
65
68
|
projectDir,
|
|
66
|
-
settings,
|
|
67
69
|
siteInfo,
|
|
68
70
|
state,
|
|
69
71
|
}) => {
|
|
70
72
|
const { functions: internalFunctions, importMap, path: internalFunctionsPath } = await getInternalFunctions()
|
|
71
|
-
const { port: mainPort } = settings
|
|
72
73
|
const userFunctionsPath = config.build.edge_functions
|
|
73
74
|
const isolatePort = await getAvailablePort()
|
|
74
75
|
|
|
@@ -76,7 +77,6 @@ export const initializeProxy = async ({
|
|
|
76
77
|
// the network if needed. We don't want to wait for that to be completed, or
|
|
77
78
|
// the command will be left hanging.
|
|
78
79
|
const server = prepareServer({
|
|
79
|
-
certificatePath: settings.https ? settings.https.certFilePath : undefined,
|
|
80
80
|
config,
|
|
81
81
|
configPath,
|
|
82
82
|
directories: [internalFunctionsPath, userFunctionsPath].filter(Boolean),
|
|
@@ -131,14 +131,14 @@ export const initializeProxy = async ({
|
|
|
131
131
|
|
|
132
132
|
req[headersSymbol] = {
|
|
133
133
|
[headers.Functions]: functionNames.join(','),
|
|
134
|
-
[headers.ForwardedHost]: `localhost:${
|
|
134
|
+
[headers.ForwardedHost]: `localhost:${passthroughPort}`,
|
|
135
135
|
[headers.Passthrough]: 'passthrough',
|
|
136
136
|
[headers.RequestID]: generateUUID(),
|
|
137
137
|
[headers.IP]: LOCAL_HOST,
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
if (
|
|
141
|
-
req[headersSymbol][headers.
|
|
140
|
+
if (debug) {
|
|
141
|
+
req[headersSymbol][headers.DebugLogging] = '1'
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
return `http://${LOCAL_HOST}:${isolatePort}`
|
|
@@ -148,7 +148,6 @@ export const initializeProxy = async ({
|
|
|
148
148
|
export const isEdgeFunctionsRequest = (req) => req[headersSymbol] !== undefined
|
|
149
149
|
|
|
150
150
|
const prepareServer = async ({
|
|
151
|
-
certificatePath,
|
|
152
151
|
config,
|
|
153
152
|
configPath,
|
|
154
153
|
directories,
|
|
@@ -168,7 +167,6 @@ const prepareServer = async ({
|
|
|
168
167
|
const distImportMapPath = getPathInProject([DIST_IMPORT_MAP_PATH])
|
|
169
168
|
const runIsolate = await bundler.serve({
|
|
170
169
|
...getDownloadUpdateFunctions(),
|
|
171
|
-
certificatePath,
|
|
172
170
|
debug: env.NETLIFY_DENO_DEBUG === 'true',
|
|
173
171
|
distImportMapPath,
|
|
174
172
|
formatExportTypeError: (name) =>
|
|
@@ -295,7 +295,15 @@ export class EdgeFunctionsRegistry {
|
|
|
295
295
|
...route,
|
|
296
296
|
pattern: new RegExp(route.pattern),
|
|
297
297
|
}))
|
|
298
|
-
const functionNames = routes
|
|
298
|
+
const functionNames = routes
|
|
299
|
+
.filter(({ pattern }) => pattern.test(urlPath))
|
|
300
|
+
.filter(({ function: name }) => {
|
|
301
|
+
const isExcluded = manifest.function_config[name]?.excluded_patterns.some((pattern) =>
|
|
302
|
+
new RegExp(pattern).test(urlPath),
|
|
303
|
+
)
|
|
304
|
+
return !isExcluded
|
|
305
|
+
})
|
|
306
|
+
.map((route) => route.function)
|
|
299
307
|
const orphanedDeclarations = await this.matchURLPathAgainstOrphanedDeclarations(urlPath)
|
|
300
308
|
|
|
301
309
|
return { functionNames, orphanedDeclarations }
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
import { Buffer } from 'buffer'
|
|
3
3
|
|
|
4
|
-
import { NETLIFYDEVERR } from '../../utils/command-helpers.mjs'
|
|
4
|
+
import { chalk, log, NETLIFYDEVERR } from '../../utils/command-helpers.mjs'
|
|
5
5
|
import renderErrorTemplate from '../render-error-template.mjs'
|
|
6
6
|
|
|
7
7
|
import { detectAwsSdkError } from './utils.mjs'
|
|
@@ -16,20 +16,35 @@ const addHeaders = (headers, response) => {
|
|
|
16
16
|
})
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
export const handleSynchronousFunction = function (
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
export const handleSynchronousFunction = function ({
|
|
20
|
+
error: invocationError,
|
|
21
|
+
functionName,
|
|
22
|
+
request,
|
|
23
|
+
response,
|
|
24
|
+
result,
|
|
25
|
+
}) {
|
|
26
|
+
if (invocationError) {
|
|
27
|
+
return handleErr(invocationError, request, response)
|
|
22
28
|
}
|
|
23
29
|
|
|
24
30
|
const { error } = validateLambdaResponse(result)
|
|
25
31
|
if (error) {
|
|
26
|
-
|
|
32
|
+
log(`${NETLIFYDEVERR} ${error}`)
|
|
27
33
|
return handleErr(error, request, response)
|
|
28
34
|
}
|
|
29
35
|
|
|
30
36
|
response.statusCode = result.statusCode
|
|
31
|
-
|
|
32
|
-
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
addHeaders(result.headers, response)
|
|
40
|
+
addHeaders(result.multiValueHeaders, response)
|
|
41
|
+
} catch (headersError) {
|
|
42
|
+
formatError(headersError)
|
|
43
|
+
|
|
44
|
+
log(`${NETLIFYDEVERR} Failed to set header in function ${chalk.yellow(functionName)}: ${headersError.message}`)
|
|
45
|
+
|
|
46
|
+
return handleErr(headersError, request, response)
|
|
47
|
+
}
|
|
33
48
|
|
|
34
49
|
if (result.body) {
|
|
35
50
|
response.write(result.isBase64Encoded ? Buffer.from(result.body, 'base64') : result.body)
|
|
@@ -37,6 +52,12 @@ export const handleSynchronousFunction = function (err, result, request, respons
|
|
|
37
52
|
response.end()
|
|
38
53
|
}
|
|
39
54
|
|
|
55
|
+
const formatError = (err) => {
|
|
56
|
+
err.errorType = err.code
|
|
57
|
+
err.errorMessage = err.message
|
|
58
|
+
err.stackTrace = err.trace
|
|
59
|
+
}
|
|
60
|
+
|
|
40
61
|
const formatLambdaLocalError = (err, acceptsHtml) =>
|
|
41
62
|
acceptsHtml
|
|
42
63
|
? JSON.stringify({
|
|
@@ -44,7 +44,7 @@ const getRepoData = async function ({ remoteName } = {}) {
|
|
|
44
44
|
Object.keys(gitConfig.remote[remoteName]).length === 0
|
|
45
45
|
) {
|
|
46
46
|
throw new Error(
|
|
47
|
-
`The specified remote "${remoteName}" is not defined in Git repo. Please use --
|
|
47
|
+
`The specified remote "${remoteName}" is not defined in Git repo. Please use --git-remote-name flag to specify a remote.`,
|
|
48
48
|
)
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -39,6 +39,7 @@ export const generateInspectSettings = (edgeInspect, edgeInspectBrk) => {
|
|
|
39
39
|
* @param {*} params.addonsUrls
|
|
40
40
|
* @param {import('../commands/base-command.mjs').NetlifyOptions["config"]} params.config
|
|
41
41
|
* @param {string} [params.configPath] An override for the Netlify config path
|
|
42
|
+
* @param {boolean} params.debug
|
|
42
43
|
* @param {import('../commands/base-command.mjs').NetlifyOptions["cachedConfig"]['env']} params.env
|
|
43
44
|
* @param {InspectSettings} params.inspectSettings
|
|
44
45
|
* @param {() => Promise<object>} params.getUpdatedConfig
|
|
@@ -55,6 +56,7 @@ export const startProxyServer = async ({
|
|
|
55
56
|
addonsUrls,
|
|
56
57
|
config,
|
|
57
58
|
configPath,
|
|
59
|
+
debug,
|
|
58
60
|
env,
|
|
59
61
|
geoCountry,
|
|
60
62
|
geolocationMode,
|
|
@@ -70,6 +72,7 @@ export const startProxyServer = async ({
|
|
|
70
72
|
addonsUrls,
|
|
71
73
|
config,
|
|
72
74
|
configPath: configPath || site.configPath,
|
|
75
|
+
debug,
|
|
73
76
|
env,
|
|
74
77
|
geolocationMode,
|
|
75
78
|
geoCountry,
|
package/src/utils/proxy.mjs
CHANGED
|
@@ -13,6 +13,7 @@ import contentType from 'content-type'
|
|
|
13
13
|
import cookie from 'cookie'
|
|
14
14
|
import { get } from 'dot-prop'
|
|
15
15
|
import generateETag from 'etag'
|
|
16
|
+
import getAvailablePort from 'get-port'
|
|
16
17
|
import httpProxy from 'http-proxy'
|
|
17
18
|
import { createProxyMiddleware } from 'http-proxy-middleware'
|
|
18
19
|
import jwtDecode from 'jwt-decode'
|
|
@@ -32,6 +33,7 @@ import { NETLIFYDEVLOG, NETLIFYDEVWARN } from './command-helpers.mjs'
|
|
|
32
33
|
import createStreamPromise from './create-stream-promise.mjs'
|
|
33
34
|
import { headersForPath, parseHeaders } from './headers.mjs'
|
|
34
35
|
import { createRewriter, onChanges } from './rules-proxy.mjs'
|
|
36
|
+
import { signRedirect } from './sign-redirect.mjs'
|
|
35
37
|
|
|
36
38
|
const decompress = util.promisify(zlib.gunzip)
|
|
37
39
|
const shouldGenerateETag = Symbol('Internal: response should generate ETag')
|
|
@@ -142,7 +144,7 @@ const alternativePathsFor = function (url) {
|
|
|
142
144
|
return paths
|
|
143
145
|
}
|
|
144
146
|
|
|
145
|
-
const serveRedirect = async function ({ match, options, proxy, req, res }) {
|
|
147
|
+
const serveRedirect = async function ({ match, options, proxy, req, res, siteInfo }) {
|
|
146
148
|
if (!match) return proxy.web(req, res, options)
|
|
147
149
|
|
|
148
150
|
options = options || req.proxyOptions || {}
|
|
@@ -154,6 +156,15 @@ const serveRedirect = async function ({ match, options, proxy, req, res }) {
|
|
|
154
156
|
})
|
|
155
157
|
}
|
|
156
158
|
|
|
159
|
+
if (match.signingSecret) {
|
|
160
|
+
req.headers['x-nf-sign'] = signRedirect({
|
|
161
|
+
deployContext: 'dev',
|
|
162
|
+
secret: match.signingSecret,
|
|
163
|
+
siteID: siteInfo.id,
|
|
164
|
+
siteURL: siteInfo.url,
|
|
165
|
+
})
|
|
166
|
+
}
|
|
167
|
+
|
|
157
168
|
if (isFunction(options.functionsPort, req.url)) {
|
|
158
169
|
return proxy.web(req, res, { target: options.functionsServer })
|
|
159
170
|
}
|
|
@@ -305,7 +316,7 @@ const reqToURL = function (req, pathname) {
|
|
|
305
316
|
|
|
306
317
|
const MILLISEC_TO_SEC = 1e3
|
|
307
318
|
|
|
308
|
-
const initializeProxy = async function ({ configPath, distDir, host, port, projectDir }) {
|
|
319
|
+
const initializeProxy = async function ({ configPath, distDir, host, port, projectDir, siteInfo }) {
|
|
309
320
|
const proxy = httpProxy.createProxyServer({
|
|
310
321
|
selfHandleResponse: true,
|
|
311
322
|
target: {
|
|
@@ -369,13 +380,20 @@ const initializeProxy = async function ({ configPath, distDir, host, port, proje
|
|
|
369
380
|
return proxy.web(req, res, req.proxyOptions)
|
|
370
381
|
}
|
|
371
382
|
if (req.proxyOptions && req.proxyOptions.match) {
|
|
372
|
-
return serveRedirect({
|
|
383
|
+
return serveRedirect({
|
|
384
|
+
req,
|
|
385
|
+
res,
|
|
386
|
+
proxy: handlers,
|
|
387
|
+
match: req.proxyOptions.match,
|
|
388
|
+
options: req.proxyOptions,
|
|
389
|
+
siteInfo,
|
|
390
|
+
})
|
|
373
391
|
}
|
|
374
392
|
}
|
|
375
393
|
|
|
376
394
|
if (req.proxyOptions.staticFile && isRedirect({ status: proxyRes.statusCode }) && proxyRes.headers.location) {
|
|
377
395
|
req.url = proxyRes.headers.location
|
|
378
|
-
return serveRedirect({ req, res, proxy: handlers, match: null, options: req.proxyOptions })
|
|
396
|
+
return serveRedirect({ req, res, proxy: handlers, match: null, options: req.proxyOptions, siteInfo })
|
|
379
397
|
}
|
|
380
398
|
|
|
381
399
|
const responseData = []
|
|
@@ -471,7 +489,11 @@ const initializeProxy = async function ({ configPath, distDir, host, port, proje
|
|
|
471
489
|
return handlers
|
|
472
490
|
}
|
|
473
491
|
|
|
474
|
-
const onRequest = async (
|
|
492
|
+
const onRequest = async (
|
|
493
|
+
{ addonsUrls, edgeFunctionsProxy, functionsServer, proxy, rewriter, settings, siteInfo },
|
|
494
|
+
req,
|
|
495
|
+
res,
|
|
496
|
+
) => {
|
|
475
497
|
req.originalBody = ['GET', 'OPTIONS', 'HEAD'].includes(req.method)
|
|
476
498
|
? null
|
|
477
499
|
: await createStreamPromise(req, BYTES_LIMIT)
|
|
@@ -508,7 +530,7 @@ const onRequest = async ({ addonsUrls, edgeFunctionsProxy, functionsServer, prox
|
|
|
508
530
|
// We don't want to generate an ETag for 3xx redirects.
|
|
509
531
|
req[shouldGenerateETag] = ({ statusCode }) => statusCode < 300 || statusCode >= 400
|
|
510
532
|
|
|
511
|
-
return serveRedirect({ req, res, proxy, match, options })
|
|
533
|
+
return serveRedirect({ req, res, proxy, match, options, siteInfo })
|
|
512
534
|
}
|
|
513
535
|
|
|
514
536
|
// The request will be served by the framework server, which means we want to
|
|
@@ -533,6 +555,7 @@ export const startProxy = async function ({
|
|
|
533
555
|
addonsUrls,
|
|
534
556
|
config,
|
|
535
557
|
configPath,
|
|
558
|
+
debug,
|
|
536
559
|
env,
|
|
537
560
|
geoCountry,
|
|
538
561
|
geolocationMode,
|
|
@@ -544,18 +567,21 @@ export const startProxy = async function ({
|
|
|
544
567
|
siteInfo,
|
|
545
568
|
state,
|
|
546
569
|
}) {
|
|
570
|
+
const secondaryServerPort = settings.https ? await getAvailablePort() : null
|
|
547
571
|
const functionsServer = settings.functionsPort ? `http://127.0.0.1:${settings.functionsPort}` : null
|
|
548
572
|
const edgeFunctionsProxy = await initializeEdgeFunctionsProxy({
|
|
549
573
|
config,
|
|
550
574
|
configPath,
|
|
575
|
+
debug,
|
|
551
576
|
env,
|
|
552
577
|
geolocationMode,
|
|
553
578
|
geoCountry,
|
|
554
579
|
getUpdatedConfig,
|
|
555
580
|
inspectSettings,
|
|
581
|
+
mainPort: settings.port,
|
|
556
582
|
offline,
|
|
583
|
+
passthroughPort: secondaryServerPort || settings.port,
|
|
557
584
|
projectDir,
|
|
558
|
-
settings,
|
|
559
585
|
siteInfo,
|
|
560
586
|
state,
|
|
561
587
|
})
|
|
@@ -565,6 +591,7 @@ export const startProxy = async function ({
|
|
|
565
591
|
distDir: settings.dist,
|
|
566
592
|
projectDir,
|
|
567
593
|
configPath,
|
|
594
|
+
siteInfo,
|
|
568
595
|
})
|
|
569
596
|
|
|
570
597
|
const rewriter = await createRewriter({
|
|
@@ -583,17 +610,34 @@ export const startProxy = async function ({
|
|
|
583
610
|
addonsUrls,
|
|
584
611
|
functionsServer,
|
|
585
612
|
edgeFunctionsProxy,
|
|
613
|
+
siteInfo,
|
|
586
614
|
})
|
|
587
|
-
const
|
|
615
|
+
const primaryServer = settings.https
|
|
588
616
|
? https.createServer({ cert: settings.https.cert, key: settings.https.key }, onRequestWithOptions)
|
|
589
617
|
: http.createServer(onRequestWithOptions)
|
|
590
|
-
|
|
591
|
-
server.on('upgrade', function onUpgrade(req, socket, head) {
|
|
618
|
+
const onUpgrade = function onUpgrade(req, socket, head) {
|
|
592
619
|
proxy.ws(req, socket, head)
|
|
593
|
-
}
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
primaryServer.on('upgrade', onUpgrade)
|
|
623
|
+
primaryServer.listen({ port: settings.port })
|
|
624
|
+
|
|
625
|
+
const eventQueue = [once(primaryServer, 'listening')]
|
|
626
|
+
|
|
627
|
+
// If we're running the main server on HTTPS, we need to start a secondary
|
|
628
|
+
// server on HTTP for receiving passthrough requests from edge functions.
|
|
629
|
+
// This lets us run the Deno server on HTTP and avoid the complications of
|
|
630
|
+
// Deno talking to Node on HTTPS with potentially untrusted certificates.
|
|
631
|
+
if (secondaryServerPort) {
|
|
632
|
+
const secondaryServer = http.createServer(onRequestWithOptions)
|
|
633
|
+
|
|
634
|
+
secondaryServer.on('upgrade', onUpgrade)
|
|
635
|
+
secondaryServer.listen({ port: secondaryServerPort })
|
|
636
|
+
|
|
637
|
+
eventQueue.push(once(secondaryServer, 'listening'))
|
|
638
|
+
}
|
|
594
639
|
|
|
595
|
-
|
|
596
|
-
await once(server, 'listening')
|
|
640
|
+
await Promise.all(eventQueue)
|
|
597
641
|
|
|
598
642
|
const scheme = settings.https ? 'https' : 'http'
|
|
599
643
|
return `${scheme}://localhost:${settings.port}`
|
package/src/utils/redirects.mjs
CHANGED
|
@@ -36,6 +36,7 @@ const normalizeRedirect = function ({
|
|
|
36
36
|
conditions: { country, language, role, ...conditions },
|
|
37
37
|
from,
|
|
38
38
|
query,
|
|
39
|
+
signed,
|
|
39
40
|
...redirect
|
|
40
41
|
}) {
|
|
41
42
|
return {
|
|
@@ -48,5 +49,10 @@ const normalizeRedirect = function ({
|
|
|
48
49
|
...(country && { Country: country }),
|
|
49
50
|
...(language && { Language: language }),
|
|
50
51
|
},
|
|
52
|
+
...(signed && {
|
|
53
|
+
sign: {
|
|
54
|
+
jwt_secret: signed,
|
|
55
|
+
},
|
|
56
|
+
}),
|
|
51
57
|
}
|
|
52
58
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import jwt from 'jsonwebtoken'
|
|
2
|
+
|
|
3
|
+
// https://docs.netlify.com/routing/redirects/rewrites-proxies/#signed-proxy-redirects
|
|
4
|
+
export const signRedirect = ({ deployContext, secret, siteID, siteURL }) => {
|
|
5
|
+
const claims = {
|
|
6
|
+
deploy_context: deployContext,
|
|
7
|
+
netlify_id: siteID,
|
|
8
|
+
site_url: siteURL,
|
|
9
|
+
}
|
|
10
|
+
const options = {
|
|
11
|
+
expiresIn: '5 minutes',
|
|
12
|
+
issuer: 'netlify',
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return jwt.sign(claims, secret, options)
|
|
16
|
+
}
|