Skip to content

Commit f4650e3

Browse files
author
Benoit Ngo
committed
Fixing request proxy to send stream instead of loading body. It fix binaries file upload that use the proxy aswell
1 parent f6115dc commit f4650e3

File tree

2 files changed

+87
-3
lines changed

2 files changed

+87
-3
lines changed

apps/front/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"generate": "nuxt generate",
77
"preview": "nuxt preview",
88
"postinstall": "nuxt prepare",
9-
"lint": "eslint nuxt.config.ts --fix ; nuxi typecheck ; eslint ./src/"
9+
"lint": "eslint nuxt.config.ts --fix ; nuxi typecheck && eslint ./src/"
1010
},
1111
"devDependencies": {
1212
"@nuxt/eslint-config": "^0.1.1",

apps/front/src/server/api/[...].ts

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1-
import { defineEventHandler, H3Event, proxyRequest } from "h3";
2-
1+
import {
2+
defineEventHandler,
3+
H3Event,
4+
RequestHeaders,
5+
getMethod,
6+
getRequestHeaders,
7+
sendProxy as _sendProxy,
8+
} from "h3";
39
/**
410
* Beware
511
* Using the SSR, cookies are transmitted to the proxy BUT
@@ -25,6 +31,83 @@ import { defineEventHandler, H3Event, proxyRequest } from "h3";
2531

2632
import logger from "~/utils/logger";
2733

34+
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
35+
36+
/**
37+
* This code override proxyRequest from h3
38+
*/
39+
40+
/**
41+
* start - this code is not exported from h3
42+
*/
43+
export interface ProxyOptions {
44+
headers?: RequestHeaders | HeadersInit;
45+
fetchOptions?: RequestInit;
46+
fetch?: typeof fetch;
47+
sendStream?: boolean;
48+
cookieDomainRewrite?: string | Record<string, string>;
49+
cookiePathRewrite?: string | Record<string, string>;
50+
onResponse?: (event: H3Event, response: Response) => void;
51+
}
52+
53+
const ignoredHeaders = new Set([
54+
'transfer-encoding',
55+
'connection',
56+
'keep-alive',
57+
'upgrade',
58+
'expect',
59+
'host',
60+
]);
61+
62+
export function getProxyRequestHeaders(event: H3Event) {
63+
const headers = Object.create(null);
64+
const reqHeaders = getRequestHeaders(event);
65+
// eslint-disable-next-line no-restricted-syntax
66+
for (const name in reqHeaders) {
67+
if (!ignoredHeaders.has(name)) {
68+
headers[name] = reqHeaders[name];
69+
}
70+
}
71+
return headers;
72+
}
73+
74+
/**
75+
* end - this code is not exported from h3
76+
*/
77+
78+
/**
79+
* This code override h3 default behavior:
80+
* Instead of reading the body we send the body as the stream, allowing better memory usage + prevent utf8 decoding
81+
* */
82+
async function proxyRequest(
83+
event: H3Event,
84+
target: string,
85+
opts: ProxyOptions = {},
86+
) {
87+
const method = getMethod(event);
88+
89+
// Headers
90+
const headers = getProxyRequestHeaders(event);
91+
if (opts.fetchOptions?.headers) {
92+
Object.assign(headers, opts.fetchOptions.headers);
93+
}
94+
if (opts.headers) {
95+
Object.assign(headers, opts.headers);
96+
}
97+
return _sendProxy(event, target, {
98+
...opts,
99+
fetchOptions: {
100+
headers,
101+
method,
102+
body: method !== "GET" && method !== "HEAD" ? event.node.req : undefined,
103+
...opts.fetchOptions,
104+
} as RequestInit,
105+
});
106+
}
107+
108+
/**
109+
* Here we use the proxy as a default request
110+
*/
28111
export default defineEventHandler(async (event: H3Event) => {
29112
const { API_URL } = useRuntimeConfig();
30113
const target = new URL(event.req.url as string, API_URL);
@@ -33,6 +116,7 @@ export default defineEventHandler(async (event: H3Event) => {
33116
headers: {
34117
host: target.host,
35118
},
119+
sendStream: true,
36120
fetchOptions: {
37121
redirect: "manual",
38122
},

0 commit comments

Comments
 (0)