From d11735d4cd4030c3134b17696a2e05c96e334804 Mon Sep 17 00:00:00 2001 From: Narciso Date: Tue, 11 Aug 2026 14:24:35 -0400 Subject: [PATCH] fix(api): configurable body size limits for OpenAPI catch-all route --- apps/dokploy/pages/api/[...trpc].ts | 28 +++++++++++++++++++++++++- packages/server/src/constants/index.ts | 12 +++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/apps/dokploy/pages/api/[...trpc].ts b/apps/dokploy/pages/api/[...trpc].ts index 83ff9b050..b7140e96f 100644 --- a/apps/dokploy/pages/api/[...trpc].ts +++ b/apps/dokploy/pages/api/[...trpc].ts @@ -1,4 +1,8 @@ -import { validateRequest } from "@dokploy/server"; +import { + OPENAPI_MAX_JSON_BODY_SIZE, + OPENAPI_MAX_UPLOAD_SIZE, + validateRequest, +} from "@dokploy/server"; import { createOpenApiNextHandler } from "@dokploy/trpc-openapi"; import type { NextApiRequest, NextApiResponse } from "next"; import { appRouter } from "@/server/api/root"; @@ -12,10 +16,26 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => { return; } + // getMultipartBody (trpc-openapi) doesn't accept maxBodySize, so multipart + // uploads have no cap unless enforced here before the handler reads the stream. + const contentLength = Number(req.headers["content-length"] ?? 0); + const isMultipart = req.headers["content-type"]?.startsWith( + "multipart/form-data", + ); + const limit = isMultipart + ? OPENAPI_MAX_UPLOAD_SIZE + : OPENAPI_MAX_JSON_BODY_SIZE; + + if (contentLength > limit) { + res.status(413).json({ message: "Payload too large" }); + return; + } + // @ts-ignore return createOpenApiNextHandler({ router: appRouter, createContext: createTRPCContext, + maxBodySize: OPENAPI_MAX_JSON_BODY_SIZE, onError: process.env.NODE_ENV === "development" ? ({ path, error }: { path: string | undefined; error: Error }) => { @@ -28,3 +48,9 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => { }; export default handler; + +export const config = { + api: { + bodyParser: false, + }, +}; diff --git a/packages/server/src/constants/index.ts b/packages/server/src/constants/index.ts index 51ffeb8c4..4f56173cf 100644 --- a/packages/server/src/constants/index.ts +++ b/packages/server/src/constants/index.ts @@ -13,6 +13,18 @@ export const DOKPLOY_DOCKER_PORT = process.env.DOKPLOY_DOCKER_PORT export const CLEANUP_CRON_JOB = "50 23 * * *"; +// Body size limits for the OpenAPI catch-all route (pages/api/[...trpc].ts). +// JSON/urlencoded bodies are capped by trpc-openapi's own default (100kb) unless +// we pass an explicit limit; multipart uploads (e.g. drop-deployment zips) have +// no built-in cap at all, so we enforce one manually via content-length. +export const OPENAPI_MAX_JSON_BODY_SIZE = process.env.OPENAPI_MAX_JSON_BODY_SIZE + ? Number.parseInt(process.env.OPENAPI_MAX_JSON_BODY_SIZE, 10) + : 10 * 1024 * 1024; // 10mb + +export const OPENAPI_MAX_UPLOAD_SIZE = process.env.OPENAPI_MAX_UPLOAD_SIZE + ? Number.parseInt(process.env.OPENAPI_MAX_UPLOAD_SIZE, 10) + : 1024 * 1024 * 1024; // 1gb + type DockerSocketCandidate = { label: string; path: string;