Skip to content

Commit a2742f7

Browse files
author
FalkWolsky
committed
Updating dependencies and MAX_REQUEST_SIZE in node-service
1 parent 482c30c commit a2742f7

File tree

4 files changed

+8992
-11200
lines changed

4 files changed

+8992
-11200
lines changed

server/node-service/package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
"@aws-sdk/client-s3": "^3.332.0",
3939
"@aws-sdk/s3-request-presigner": "^3.332.0",
4040
"@duckdb/node-api": "^1.3.0-alpha.21",
41-
"@google-cloud/bigquery": "^6.1.0",
41+
"@google-cloud/bigquery": "^8.1.1",
4242
"@google-cloud/storage": "^6.10.1",
4343
"@supabase/supabase-js": "^2.26.0",
4444
"@types/cors": "^2.8.17",
@@ -48,15 +48,15 @@
4848
"@types/morgan": "^1.9.3",
4949
"@types/node": "^22.10.5",
5050
"@types/node-fetch": "^2.6.2",
51-
"ali-oss": "^6.20.0",
51+
"ali-oss": "^6.23.0",
5252
"axios": "^1.7.9",
5353
"base64-arraybuffer": "^1.0.2",
5454
"bluebird": "^3.7.2",
5555
"cors": "^2.8.5",
5656
"dynamodb-data-types": "^4.0.1",
57-
"express": "^4.21.0",
57+
"express": "^4.21.1",
5858
"express-async-errors": "^3.1.1",
59-
"firebase-admin": "^12.6.0",
59+
"firebase-admin": "^13.6.0",
6060
"formdata-node": "4",
6161
"graphql": "^16.9.0",
6262
"graphql-request": "^6.1.0",
@@ -71,9 +71,9 @@
7171
"openapi-types": "^12.1.3",
7272
"pino": "^9.5.0",
7373
"prom-client": "^14.2.0",
74-
"proxy-agent": "^5.0.0",
74+
"proxy-agent": "^6.5.0",
7575
"stylis": "^4.3.0",
76-
"swagger-client": "^3.32.2",
76+
"swagger-client": "^3.36.0",
7777
"typescript": "^4.9.3",
7878
"yaml": "^2.6.0"
7979
},
Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1-
import nodeFetch, { RequestInit, RequestInfo } from "node-fetch";
2-
import proxyAgent from "proxy-agent";
1+
import { ProxyAgent } from "proxy-agent";
2+
import nodeFetch, { RequestInit } from "node-fetch";
33

4-
export function fetch(url: RequestInfo, init?: RequestInit) {
5-
return nodeFetch(url, { agent: proxyAgent(), ...init });
4+
const proxyAgent = new ProxyAgent();
5+
6+
export function fetch(url: string, init: RequestInit = {}) {
7+
return nodeFetch(url, {
8+
...init,
9+
agent: proxyAgent,
10+
});
611
}

server/node-service/src/server.ts

Lines changed: 112 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,22 +30,25 @@ router.use(prefix, express.static(path.join(__dirname, "static")));
3030
/** Logging */
3131
router.use(morgan("dev"));
3232

33-
const MAX_REQUEST_SIZE = process.env.LOWCODER_MAX_REQUEST_SIZE || "50mb";
33+
const MAX_REQUEST_SIZE_BYTES = parseRequestLimitNoLib(
34+
process.env.LOWCODER_MAX_REQUEST_SIZE,
35+
"50mb"
36+
);
3437

3538
/** Parse the request */
36-
router.use(express.urlencoded({ extended: false, limit: MAX_REQUEST_SIZE }));
39+
router.use(express.urlencoded({ extended: false, limit: MAX_REQUEST_SIZE_BYTES }));
3740

3841
/** Custom middleware: use raw body for encrypted requests */
3942
router.use((req, res, next) => {
4043
if (req.headers["x-encrypted"]) {
41-
bodyParser.text({ type: "*/*", limit: MAX_REQUEST_SIZE })(req, res, next);
44+
bodyParser.text({ type: "*/*", limit: MAX_REQUEST_SIZE_BYTES })(req, res, next);
4245
} else {
43-
bodyParser.json({ limit: MAX_REQUEST_SIZE })(req, res, next);
46+
bodyParser.json({ limit: MAX_REQUEST_SIZE_BYTES })(req, res, next);
4447
}
4548
});
4649

4750
/** Takes care of JSON data */
48-
router.use(express.json({ limit: MAX_REQUEST_SIZE }));
51+
router.use(express.json({ limit: MAX_REQUEST_SIZE_BYTES }));
4952

5053
/** RULES OF OUR API */
5154

@@ -62,7 +65,7 @@ const corsOptions: CorsOptions = {
6265
'Accept',
6366
'Content-Type'
6467
],
65-
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH']
68+
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS']
6669
};
6770

6871
router.use(cors(corsOptions));
@@ -97,3 +100,106 @@ router.use((req, res, next) => {
97100
const httpServer = http.createServer(router);
98101
const PORT = process.env.NODE_SERVICE_PORT ?? 6060;
99102
httpServer.listen(PORT, () => logger.info(`The server is running on port: ${PORT}`));
103+
104+
/**
105+
* Parses request size strings into bytes.
106+
*
107+
* Accepts:
108+
* - "52428800" => bytes
109+
* - "50mb", "128kb", "1gb" => bytes (binary base 1024)
110+
* - "50m", "128k", "1g" => Spring short units (treated as mb/kb/gb)
111+
* - "1.5m", "0.25gb" => decimals supported
112+
* - "50 m" => whitespace tolerated
113+
*
114+
* Units are binary (KiB/MiB/GiB) using 1024 multipliers, which matches Node conventions well.
115+
* (If you want decimal SI units (1000), adjust multipliers accordingly.)
116+
*/
117+
function parseRequestLimitNoLib(input: unknown, fallback: string = "50mb"): number {
118+
const raw = input ?? fallback;
119+
120+
// Direct number => bytes
121+
if (typeof raw === "number") {
122+
if (!Number.isFinite(raw) || raw <= 0) throw new Error(`Invalid request size number: ${raw}`);
123+
return Math.floor(raw);
124+
}
125+
126+
const s0 = String(raw).trim();
127+
if (!s0) return parseRequestLimitNoLib(fallback);
128+
129+
// Remove whitespace and lowercase
130+
const s = s0.replace(/\s+/g, "").toLowerCase();
131+
132+
// Pure integer bytes
133+
if (/^\d+$/u.test(s)) {
134+
const n = Number(s);
135+
if (!Number.isFinite(n) || n <= 0) throw new Error(`Invalid request size: ${s0}`);
136+
return n;
137+
}
138+
139+
// Match: number + unit (unit may be k|kb|m|mb|g|gb|t|tb|p|pb|b)
140+
const m = s.match(/^(\d+(?:\.\d+)?)(b|kb|k|mb|m|gb|g|tb|t|pb|p)$/u);
141+
if (!m) {
142+
throw new Error(
143+
`Invalid LOWCODER_MAX_REQUEST_SIZE: "${s0}". ` +
144+
`Use bytes ("52428800"), long units ("50mb"), or Spring units ("50m").`
145+
);
146+
}
147+
148+
const value = Number(m[1]);
149+
const unit = m[2];
150+
151+
if (!Number.isFinite(value) || value <= 0) {
152+
throw new Error(`Invalid LOWCODER_MAX_REQUEST_SIZE numeric value: "${m[1]}"`);
153+
}
154+
155+
// Binary multipliers (base 1024)
156+
const KB = 1024;
157+
const MB = 1024 * KB;
158+
const GB = 1024 * MB;
159+
const TB = 1024 * GB;
160+
const PB = 1024 * TB;
161+
162+
let bytes: number;
163+
164+
switch (unit) {
165+
case "b":
166+
bytes = value;
167+
break;
168+
169+
case "k":
170+
case "kb":
171+
bytes = value * KB;
172+
break;
173+
174+
case "m":
175+
case "mb":
176+
bytes = value * MB;
177+
break;
178+
179+
case "g":
180+
case "gb":
181+
bytes = value * GB;
182+
break;
183+
184+
case "t":
185+
case "tb":
186+
bytes = value * TB;
187+
break;
188+
189+
case "p":
190+
case "pb":
191+
bytes = value * PB;
192+
break;
193+
194+
default:
195+
// Should be unreachable because of regex, but keep safe:
196+
throw new Error(`Unsupported unit: "${unit}"`);
197+
}
198+
199+
// Guard: must fit into a safe integer
200+
if (!Number.isFinite(bytes) || bytes <= 0 || !Number.isSafeInteger(Math.floor(bytes))) {
201+
throw new Error(`LOWCODER_MAX_REQUEST_SIZE too large or invalid: "${s0}"`);
202+
}
203+
204+
return Math.floor(bytes);
205+
}

0 commit comments

Comments
 (0)