@netlify/plugin-nextjs 4.13.0 → 4.14.1

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.
@@ -270,13 +270,21 @@ const baseServerReplacements = [
270
270
  ];
271
271
  const nextServerReplacements = [
272
272
  [
273
- `getMiddlewareManifest() {\n if (!this.minimalMode) {`,
274
- `getMiddlewareManifest() {\n if (!this.minimalMode && !process.env.NEXT_USE_NETLIFY_EDGE) {`,
273
+ `getMiddlewareManifest() {\n if (this.minimalMode) return null;`,
274
+ `getMiddlewareManifest() {\n if (this.minimalMode || process.env.NEXT_USE_NETLIFY_EDGE) return null;`,
275
+ ],
276
+ [
277
+ `generateCatchAllMiddlewareRoute(devReady) {\n if (this.minimalMode) return []`,
278
+ `generateCatchAllMiddlewareRoute(devReady) {\n if (this.minimalMode || process.env.NEXT_USE_NETLIFY_EDGE) return [];`,
275
279
  ],
276
280
  [
277
281
  `generateCatchAllMiddlewareRoute() {\n if (this.minimalMode) return undefined;`,
278
282
  `generateCatchAllMiddlewareRoute() {\n if (this.minimalMode || process.env.NEXT_USE_NETLIFY_EDGE) return undefined;`,
279
283
  ],
284
+ [
285
+ `getMiddlewareManifest() {\n if (this.minimalMode) {`,
286
+ `getMiddlewareManifest() {\n if (!this.minimalMode && !process.env.NEXT_USE_NETLIFY_EDGE) {`,
287
+ ],
280
288
  ];
281
289
  const patchNextFiles = async (root) => {
282
290
  const baseServerFile = getServerFile(root);
@@ -136,7 +136,7 @@ const findModuleFromBase = ({ paths, candidates }) => {
136
136
  exports.findModuleFromBase = findModuleFromBase;
137
137
  const isNextAuthInstalled = () => {
138
138
  try {
139
- // eslint-disable-next-line import/no-unassigned-import, import/no-unresolved, node/no-missing-require
139
+ // eslint-disable-next-line import/no-unassigned-import, import/no-unresolved, n/no-missing-require
140
140
  require('next-auth');
141
141
  return true;
142
142
  }
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ /* eslint-disable max-classes-per-file */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ /* eslint-enable max-classes-per-file */
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./response"), exports);
18
+ __exportStar(require("./request"), exports);
19
+ __exportStar(require("./html-rewriter"), exports);
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MiddlewareRequest = void 0;
4
+ const server_1 = require("next/server");
5
+ const response_1 = require("./response");
6
+ /**
7
+ * Supercharge your Next middleware with Netlify Edge Functions
8
+ */
9
+ class MiddlewareRequest extends Request {
10
+ constructor(nextRequest) {
11
+ super(nextRequest);
12
+ this.nextRequest = nextRequest;
13
+ if (!('Deno' in globalThis)) {
14
+ throw new Error('MiddlewareRequest only works in a Netlify Edge Function environment');
15
+ }
16
+ const requestId = nextRequest.headers.get('x-nf-request-id');
17
+ if (!requestId) {
18
+ throw new Error('Missing x-nf-request-id header');
19
+ }
20
+ const requestContext = globalThis.NFRequestContextMap.get(requestId);
21
+ if (!requestContext) {
22
+ throw new Error(`Could not find request context for request id ${requestId}`);
23
+ }
24
+ this.context = requestContext.context;
25
+ this.originalRequest = requestContext.request;
26
+ }
27
+ // Add the headers to the original request, which will be passed to the origin
28
+ applyHeaders() {
29
+ this.headers.forEach((value, name) => {
30
+ this.originalRequest.headers.set(name, value);
31
+ });
32
+ }
33
+ async next() {
34
+ this.applyHeaders();
35
+ const response = await this.context.next();
36
+ return new response_1.MiddlewareResponse(response);
37
+ }
38
+ rewrite(destination, init) {
39
+ if (typeof destination === 'string' && destination.startsWith('/')) {
40
+ destination = new URL(destination, this.url);
41
+ }
42
+ this.applyHeaders();
43
+ return server_1.NextResponse.rewrite(destination, init);
44
+ }
45
+ get headers() {
46
+ return this.nextRequest.headers;
47
+ }
48
+ get cookies() {
49
+ return this.nextRequest.cookies;
50
+ }
51
+ get geo() {
52
+ return this.nextRequest.geo;
53
+ }
54
+ get ip() {
55
+ return this.nextRequest.ip;
56
+ }
57
+ get nextUrl() {
58
+ return this.nextRequest.url;
59
+ }
60
+ get url() {
61
+ return this.nextRequest.url.toString();
62
+ }
63
+ }
64
+ exports.MiddlewareRequest = MiddlewareRequest;
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MiddlewareResponse = void 0;
4
+ const server_1 = require("next/server");
5
+ // A NextResponse that wraps the Netlify origin response
6
+ // We can't pass it through directly, because Next disallows returning a response body
7
+ class MiddlewareResponse extends server_1.NextResponse {
8
+ constructor(originResponse) {
9
+ super();
10
+ this.originResponse = originResponse;
11
+ // These are private in Node when compiling, but we access them in Deno at runtime
12
+ Object.defineProperty(this, 'dataTransforms', {
13
+ value: [],
14
+ enumerable: false,
15
+ writable: false,
16
+ });
17
+ Object.defineProperty(this, 'elementHandlers', {
18
+ value: [],
19
+ enumerable: false,
20
+ writable: false,
21
+ });
22
+ }
23
+ /**
24
+ * Transform the page props before they are passed to the client.
25
+ * This works for both HTML pages and JSON data
26
+ */
27
+ transformData(transform) {
28
+ // The transforms are evaluated after the middleware is returned
29
+ this.dataTransforms.push(transform);
30
+ }
31
+ /**
32
+ * Rewrite the response HTML with the given selector and handlers
33
+ */
34
+ rewriteHTML(selector, handlers) {
35
+ this.elementHandlers.push([selector, handlers]);
36
+ }
37
+ /**
38
+ * Sets the value of a page prop.
39
+ * @see transformData if you need more control
40
+ */
41
+ setPageProp(key, value) {
42
+ this.transformData((props) => {
43
+ props.pageProps || (props.pageProps = {});
44
+ props.pageProps[key] = value;
45
+ return props;
46
+ });
47
+ }
48
+ /**
49
+ * Replace the text of the given element. Takes either a string or a function
50
+ * that is passed the original string and returns new new string.
51
+ * @see rewriteHTML for more control
52
+ */
53
+ replaceText(selector, valueOrReplacer) {
54
+ // If it's a string then our job is simpler, because we don't need to collect the current text
55
+ if (typeof valueOrReplacer === 'string') {
56
+ this.rewriteHTML(selector, {
57
+ text(textChunk) {
58
+ if (textChunk.lastInTextNode) {
59
+ textChunk.replace(valueOrReplacer);
60
+ }
61
+ else {
62
+ textChunk.remove();
63
+ }
64
+ },
65
+ });
66
+ }
67
+ else {
68
+ let text = '';
69
+ this.rewriteHTML(selector, {
70
+ text(textChunk) {
71
+ text += textChunk.text;
72
+ // We're finished, so we can replace the text
73
+ if (textChunk.lastInTextNode) {
74
+ textChunk.replace(valueOrReplacer(text));
75
+ }
76
+ else {
77
+ // Remove the chunk, because we'll be adding it back later
78
+ textChunk.remove();
79
+ }
80
+ },
81
+ });
82
+ }
83
+ }
84
+ get headers() {
85
+ var _a;
86
+ // If we have the origin response, we should use its headers
87
+ return ((_a = this.originResponse) === null || _a === void 0 ? void 0 : _a.headers) || super.headers;
88
+ }
89
+ }
90
+ exports.MiddlewareResponse = MiddlewareResponse;
@@ -6,7 +6,7 @@ const outdent_1 = require("outdent");
6
6
  const { promises } = require('fs');
7
7
  const { Server } = require('http');
8
8
  const path = require('path');
9
- // eslint-disable-next-line node/prefer-global/url, node/prefer-global/url-search-params
9
+ // eslint-disable-next-line n/prefer-global/url, n/prefer-global/url-search-params
10
10
  const { URLSearchParams, URL } = require('url');
11
11
  const { Bridge } = require('@vercel/node-bridge/bridge');
12
12
  const { augmentFsModule, getMaxAge, getMultiValueHeaders, getNextServer } = require('./handlerUtils');
@@ -22,7 +22,7 @@ const makeHandler = (conf, app, pageRoot, staticManifest = [], mode = 'ssr') =>
22
22
  }
23
23
  // This is just so nft knows about the page entrypoints. It's not actually used
24
24
  try {
25
- // eslint-disable-next-line node/no-missing-require
25
+ // eslint-disable-next-line n/no-missing-require
26
26
  require.resolve('./pages.js');
27
27
  }
28
28
  catch { }
@@ -121,7 +121,7 @@ const getHandler = ({ isODB = false, publishDir = '../../../.next', appDir = '..
121
121
 
122
122
  const { builder } = require("@netlify/functions");
123
123
  const { config } = require("${publishDir}/required-server-files.json")
124
- let staticManifest
124
+ let staticManifest
125
125
  try {
126
126
  staticManifest = require("${publishDir}/static-manifest.json")
127
127
  } catch {}
@@ -160,7 +160,7 @@ const getNextServer = () => {
160
160
  if (!NextServer) {
161
161
  try {
162
162
  // next < 11.0.1
163
- // eslint-disable-next-line node/no-missing-require, import/no-unresolved, @typescript-eslint/no-var-requires
163
+ // eslint-disable-next-line n/no-missing-require, import/no-unresolved, @typescript-eslint/no-var-requires
164
164
  NextServer = require('next/dist/next-server/server/next-server').default;
165
165
  }
166
166
  catch (error) {
@@ -9,4 +9,4 @@ exports.handler = (0, ipx_1.createIPXHandler)({
9
9
  domains: imageconfig_json_1.domains,
10
10
  remotePatterns: imageconfig_json_1.remotePatterns,
11
11
  });
12
- /* eslint-enable node/no-missing-import, import/no-unresolved, @typescript-eslint/ban-ts-comment */
12
+ /* eslint-enable n/no-missing-import, import/no-unresolved, @typescript-eslint/ban-ts-comment */
package/package.json CHANGED
@@ -1,13 +1,25 @@
1
1
  {
2
2
  "name": "@netlify/plugin-nextjs",
3
- "version": "4.13.0",
3
+ "version": "4.14.1",
4
4
  "description": "Run Next.js seamlessly on Netlify",
5
5
  "main": "lib/index.js",
6
6
  "files": [
7
7
  "lib/**/*",
8
8
  "src/templates/edge/*",
9
- "manifest.yml"
9
+ "manifest.yml",
10
+ "middleware.js"
10
11
  ],
12
+ "typesVersions": {
13
+ "*": {
14
+ "middleware": [
15
+ "dist-types/middleware"
16
+ ]
17
+ }
18
+ },
19
+ "exports": {
20
+ ".": "./lib/index.js",
21
+ "./middleware": "./lib/middleware/index.js"
22
+ },
11
23
  "dependencies": {
12
24
  "@netlify/functions": "^1.0.0",
13
25
  "@netlify/ipx": "^1.1.3",
@@ -28,7 +40,7 @@
28
40
  },
29
41
  "devDependencies": {
30
42
  "@delucis/if-env": "^1.1.2",
31
- "@netlify/build": "^27.4.2",
43
+ "@netlify/build": "^27.8.1",
32
44
  "@types/fs-extra": "^9.0.13",
33
45
  "@types/jest": "^27.4.1",
34
46
  "@types/node": "^17.0.25",
@@ -41,7 +53,7 @@
41
53
  "publish:pull": "git pull",
42
54
  "publish:install": "npm ci",
43
55
  "publish:test": "cd .. && npm ci && npm test",
44
- "clean": "rimraf lib",
56
+ "clean": "rimraf lib dist-types",
45
57
  "build": "tsc",
46
58
  "watch": "tsc --watch",
47
59
  "prepare": "npm run build"
@@ -62,4 +74,4 @@
62
74
  "engines": {
63
75
  "node": ">=12.0.0"
64
76
  }
65
- }
77
+ }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * This placeholder is replaced with the compiled Next.js bundle at build time
3
- * @args {Object}
4
- * @args.request {import("./runtime.ts").RequestData}
3
+ * @param {Object} props
4
+ * @param {import("./runtime.ts").RequestData} props.request
5
5
  * @returns {Promise<import("./utils.ts").FetchEventResult>}
6
6
  */
7
- export default async (props) => {}
7
+ export default async ({ request }) => {}
@@ -1,14 +1,12 @@
1
- import { Accepts } from "https://deno.land/x/accepts@2.1.1/mod.ts";
2
- import type { Context } from "netlify:edge";
1
+ import { Accepts } from 'https://deno.land/x/accepts@2.1.1/mod.ts'
2
+ import type { Context } from 'https://edge.netlify.com'
3
3
  // Available at build time
4
- import imageconfig from "./imageconfig.json" assert {
5
- type: "json",
6
- };
4
+ import imageconfig from './imageconfig.json' assert { type: 'json' }
7
5
 
8
- const defaultFormat = "webp"
6
+ const defaultFormat = 'webp'
9
7
 
10
8
  interface ImageConfig extends Record<string, unknown> {
11
- formats?: string[];
9
+ formats?: string[]
12
10
  }
13
11
 
14
12
  /**
@@ -17,41 +15,38 @@ interface ImageConfig extends Record<string, unknown> {
17
15
 
18
16
  // deno-lint-ignore require-await
19
17
  const handler = async (req: Request, context: Context) => {
20
- const { searchParams } = new URL(req.url);
21
- const accept = new Accepts(req.headers);
22
- const { formats = [defaultFormat] } = imageconfig as ImageConfig;
18
+ const { searchParams } = new URL(req.url)
19
+ const accept = new Accepts(req.headers)
20
+ const { formats = [defaultFormat] } = imageconfig as ImageConfig
23
21
  if (formats.length === 0) {
24
- formats.push(defaultFormat);
22
+ formats.push(defaultFormat)
25
23
  }
26
- let type = accept.types(formats) || defaultFormat;
27
- if(Array.isArray(type)) {
28
- type = type[0];
24
+ let type = accept.types(formats) || defaultFormat
25
+ if (Array.isArray(type)) {
26
+ type = type[0]
29
27
  }
30
28
 
31
-
32
- const source = searchParams.get("url");
33
- const width = searchParams.get("w");
34
- const quality = searchParams.get("q") ?? 75;
29
+ const source = searchParams.get('url')
30
+ const width = searchParams.get('w')
31
+ const quality = searchParams.get('q') ?? 75
35
32
 
36
33
  if (!source || !width) {
37
- return new Response("Invalid request", {
34
+ return new Response('Invalid request', {
38
35
  status: 400,
39
- });
36
+ })
40
37
  }
41
38
 
42
- const modifiers = [`w_${width}`, `q_${quality}`];
39
+ const modifiers = [`w_${width}`, `q_${quality}`]
43
40
 
44
41
  if (type) {
45
- if(type.includes('/')) {
42
+ if (type.includes('/')) {
46
43
  // If this is a mimetype, strip "image/"
47
- type = type.split('/')[1];
44
+ type = type.split('/')[1]
48
45
  }
49
- modifiers.push(`f_${type}`);
46
+ modifiers.push(`f_${type}`)
50
47
  }
51
- const target = `/_ipx/${modifiers.join(",")}/${encodeURIComponent(source)}`;
52
- return context.rewrite(
53
- target,
54
- );
55
- };
48
+ const target = `/_ipx/${modifiers.join(',')}/${encodeURIComponent(source)}`
49
+ return context.rewrite(target)
50
+ }
56
51
 
57
- export default handler;
52
+ export default handler
@@ -1,4 +1,4 @@
1
- import type { Context } from 'netlify:edge'
1
+ import type { Context } from 'https://edge.netlify.com'
2
2
 
3
3
  import edgeFunction from './bundle.js'
4
4
  import { buildResponse } from './utils.ts'
@@ -32,19 +32,43 @@ export interface RequestData {
32
32
  body?: ReadableStream<Uint8Array>
33
33
  }
34
34
 
35
+ export interface RequestContext {
36
+ request: Request
37
+ context: Context
38
+ }
39
+
40
+ declare global {
41
+ // deno-lint-ignore no-var
42
+ var NFRequestContextMap: Map<string, RequestContext>
43
+ }
44
+
45
+ globalThis.NFRequestContextMap ||= new Map()
46
+
35
47
  const handler = async (req: Request, context: Context) => {
36
48
  const url = new URL(req.url)
37
49
  if (url.pathname.startsWith('/_next/static/')) {
38
50
  return
39
51
  }
40
52
 
53
+ const geo = {
54
+ country: context.geo.country?.code,
55
+ region: context.geo.subdivision?.code,
56
+ city: context.geo.city,
57
+ }
58
+
59
+ const requestId = req.headers.get('x-nf-request-id')
60
+ if (!requestId) {
61
+ console.error('Missing x-nf-request-id header')
62
+ } else {
63
+ globalThis.NFRequestContextMap.set(requestId, {
64
+ request: req,
65
+ context,
66
+ })
67
+ }
68
+
41
69
  const request: RequestData = {
42
70
  headers: Object.fromEntries(req.headers.entries()),
43
- geo: {
44
- country: context.geo.country?.code,
45
- region: context.geo.subdivision?.code,
46
- city: context.geo.city,
47
- },
71
+ geo,
48
72
  url: url.toString(),
49
73
  method: req.method,
50
74
  ip: context.ip,
@@ -57,6 +81,10 @@ const handler = async (req: Request, context: Context) => {
57
81
  } catch (error) {
58
82
  console.error(error)
59
83
  return new Response(error.message, { status: 500 })
84
+ } finally {
85
+ if (requestId) {
86
+ globalThis.NFRequestContextMap.delete(requestId)
87
+ }
60
88
  }
61
89
  }
62
90
 
@@ -1,14 +1,17 @@
1
- import type { Context } from 'netlify:edge'
1
+ import type { Context } from 'https://edge.netlify.com'
2
+ import { ElementHandlers, HTMLRewriter } from 'https://deno.land/x/html_rewriter@v0.1.0-pre.17/index.ts'
2
3
 
3
4
  export interface FetchEventResult {
4
5
  response: Response
5
6
  waitUntil: Promise<any>
6
7
  }
7
8
 
9
+ type NextDataTransform = <T>(data: T) => T
10
+
8
11
  /**
9
12
  * This is how Next handles rewritten URLs.
10
13
  */
11
- export function relativizeURL(url: string | string, base: string | URL) {
14
+ export function relativizeURL(url: string | string, base: string | URL) {
12
15
  const baseURL = typeof base === 'string' ? new URL(base) : base
13
16
  const relative = new URL(url, base)
14
17
  const origin = `${baseURL.protocol}//${baseURL.host}`
@@ -17,7 +20,6 @@ export interface FetchEventResult {
17
20
  : relative.toString()
18
21
  }
19
22
 
20
-
21
23
  export const addMiddlewareHeaders = async (
22
24
  originResponse: Promise<Response> | Response,
23
25
  middlewareResponse: Response,
@@ -34,6 +36,29 @@ export const addMiddlewareHeaders = async (
34
36
  })
35
37
  return response
36
38
  }
39
+
40
+ interface MiddlewareResponse extends Response {
41
+ originResponse: Response
42
+ dataTransforms: NextDataTransform[]
43
+ elementHandlers: Array<[selector: string, handlers: ElementHandlers]>
44
+ }
45
+
46
+ interface MiddlewareRequest {
47
+ request: Request
48
+ context: Context
49
+ originalRequest: Request
50
+ next(): Promise<MiddlewareResponse>
51
+ rewrite(destination: string | URL, init?: ResponseInit): Response
52
+ }
53
+
54
+ function isMiddlewareRequest(response: Response | MiddlewareRequest): response is MiddlewareRequest {
55
+ return 'originalRequest' in response
56
+ }
57
+
58
+ function isMiddlewareResponse(response: Response | MiddlewareResponse): response is MiddlewareResponse {
59
+ return 'dataTransforms' in response
60
+ }
61
+
37
62
  export const buildResponse = async ({
38
63
  result,
39
64
  request,
@@ -43,13 +68,65 @@ export const buildResponse = async ({
43
68
  request: Request
44
69
  context: Context
45
70
  }) => {
71
+ // They've returned the MiddlewareRequest directly, so we'll call `next()` for them.
72
+ if (isMiddlewareRequest(result.response)) {
73
+ result.response = await result.response.next()
74
+ }
75
+ if (isMiddlewareResponse(result.response)) {
76
+ const { response } = result
77
+ if (request.method === 'HEAD' || request.method === 'OPTIONS') {
78
+ return response.originResponse
79
+ }
80
+ // If it's JSON we don't need to use the rewriter, we can just parse it
81
+ if (response.originResponse.headers.get('content-type')?.includes('application/json')) {
82
+ const props = await response.originResponse.json()
83
+ const transformed = response.dataTransforms.reduce((prev, transform) => {
84
+ return transform(prev)
85
+ }, props)
86
+ return context.json(transformed)
87
+ }
88
+ // This var will hold the contents of the script tag
89
+ let buffer = ''
90
+ // Create an HTMLRewriter that matches the Next data script tag
91
+ const rewriter = new HTMLRewriter()
92
+
93
+ if (response.dataTransforms.length > 0) {
94
+ rewriter.on('script[id="__NEXT_DATA__"]', {
95
+ text(textChunk) {
96
+ // Grab all the chunks in the Next data script tag
97
+ buffer += textChunk.text
98
+ if (textChunk.lastInTextNode) {
99
+ try {
100
+ // When we have all the data, try to parse it as JSON
101
+ const data = JSON.parse(buffer.trim())
102
+ // Apply all of the transforms to the props
103
+ const props = response.dataTransforms.reduce((prev, transform) => transform(prev), data.props)
104
+ // Replace the data with the transformed props
105
+ textChunk.replace(JSON.stringify({ ...data, props }))
106
+ } catch (err) {
107
+ console.log('Could not parse', err)
108
+ }
109
+ } else {
110
+ // Remove the chunk after we've appended it to the buffer
111
+ textChunk.remove()
112
+ }
113
+ },
114
+ })
115
+ }
116
+
117
+ if (response.elementHandlers.length > 0) {
118
+ response.elementHandlers.forEach(([selector, handlers]) => rewriter.on(selector, handlers))
119
+ }
120
+ return rewriter.transform(response.originResponse)
121
+ }
46
122
  const res = new Response(result.response.body, result.response)
47
123
  request.headers.set('x-nf-next-middleware', 'skip')
124
+
48
125
  const rewrite = res.headers.get('x-middleware-rewrite')
49
126
  if (rewrite) {
50
127
  const rewriteUrl = new URL(rewrite, request.url)
51
128
  const baseUrl = new URL(request.url)
52
- if(rewriteUrl.hostname !== baseUrl.hostname) {
129
+ if (rewriteUrl.hostname !== baseUrl.hostname) {
53
130
  // Netlify Edge Functions don't support proxying to external domains, but Next middleware does
54
131
  const proxied = fetch(new Request(rewriteUrl.toString(), request))
55
132
  return addMiddlewareHeaders(proxied, res)