Error handling bugfix: pass #1
This commit is contained in:
@@ -7,6 +7,7 @@ import grabRouteParams from "../../utils/grab-route-params";
|
||||
import grabConstants from "../../utils/grab-constants";
|
||||
import grabRouter from "../../utils/grab-router";
|
||||
import isDevelopment from "../../utils/is-development";
|
||||
import { log } from "../../utils/log";
|
||||
import _ from "lodash";
|
||||
import path from "path";
|
||||
import grabDirNames from "../../utils/grab-dir-names";
|
||||
@@ -19,138 +20,199 @@ type Params = {
|
||||
};
|
||||
|
||||
export default async function ({ req }: Params): Promise<Response> {
|
||||
const url = new URL(req.url);
|
||||
const is_dev = isDevelopment();
|
||||
try {
|
||||
const url = new URL(req.url);
|
||||
const is_dev = isDevelopment();
|
||||
|
||||
const { MBInBytes, ServerDefaultRequestBodyLimitBytes } = grabConstants();
|
||||
const { MBInBytes, ServerDefaultRequestBodyLimitBytes } =
|
||||
grabConstants();
|
||||
|
||||
const router = grabRouter();
|
||||
const router = grabRouter();
|
||||
|
||||
const match = router.match(url.pathname);
|
||||
const match = router.match(url.pathname);
|
||||
|
||||
if (!match?.filePath) {
|
||||
const errMsg = `Route ${url.pathname} not found`;
|
||||
if (!match?.filePath) {
|
||||
const errMsg = `Route ${url.pathname} not found`;
|
||||
|
||||
return Response.json(
|
||||
{
|
||||
success: false,
|
||||
msg: errMsg,
|
||||
},
|
||||
{
|
||||
status: 404,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
const routeParams: BunxRouteParams = await grabRouteParams({
|
||||
req,
|
||||
query: match.query,
|
||||
});
|
||||
|
||||
let module: any;
|
||||
const now = Date.now();
|
||||
|
||||
const relative_match_path = grabRelativePath(match.filePath);
|
||||
|
||||
if (
|
||||
is_dev &&
|
||||
global.BUNEXT_SSR_BUNDLER_CTX_MAP?.[relative_match_path]?.path
|
||||
) {
|
||||
const target_import = path.join(
|
||||
ROOT_DIR,
|
||||
global.BUNEXT_SSR_BUNDLER_CTX_MAP[relative_match_path].path,
|
||||
);
|
||||
|
||||
module = await import(`${target_import}?t=${now}`);
|
||||
} else {
|
||||
const import_path = is_dev
|
||||
? `${match.filePath}?t=${now}`
|
||||
: match.filePath;
|
||||
module = await import(import_path);
|
||||
}
|
||||
|
||||
const config = module.config as BunextServerRouteConfig | undefined;
|
||||
|
||||
const maxBodyBytes = config?.max_request_body_mb
|
||||
? config.max_request_body_mb * MBInBytes
|
||||
: ServerDefaultRequestBodyLimitBytes;
|
||||
|
||||
const contentLength = req.headers.get("content-length");
|
||||
|
||||
if (contentLength) {
|
||||
const size = parseInt(contentLength, 10);
|
||||
|
||||
if (size > maxBodyBytes) {
|
||||
return Response.json(
|
||||
{
|
||||
success: false,
|
||||
msg: "Request Body Too Large!",
|
||||
},
|
||||
{
|
||||
status: 413,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
} else if (req.method !== "GET" && req.method !== "HEAD") {
|
||||
const body = await req.arrayBuffer();
|
||||
if (body.byteLength > maxBodyBytes) {
|
||||
return Response.json(
|
||||
{
|
||||
success: false,
|
||||
msg: "Request Body Too Large!",
|
||||
},
|
||||
{
|
||||
status: 413,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
routeParams.body = JSON.parse(
|
||||
new TextDecoder().decode(body) || "{}",
|
||||
);
|
||||
} catch (error: any) {
|
||||
log.error(
|
||||
`Invalid JSON body for ${url.pathname}: ${error?.message}`,
|
||||
);
|
||||
return Response.json(
|
||||
{
|
||||
success: false,
|
||||
msg: "Invalid JSON body",
|
||||
},
|
||||
{
|
||||
status: 400,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const target_module = (module["default"] ||
|
||||
module["handler"]) as BunextAPIRouteHandler;
|
||||
|
||||
let res: any;
|
||||
try {
|
||||
res = await target_module?.({
|
||||
...routeParams,
|
||||
});
|
||||
} catch (error: any) {
|
||||
log.error(
|
||||
`API Route Error (${url.pathname}): ${error?.message}\n${error?.stack || ""}`,
|
||||
);
|
||||
return Response.json(
|
||||
{
|
||||
success: false,
|
||||
msg: `Route handler error: ${error?.message || "Internal Server Error"}`,
|
||||
},
|
||||
{
|
||||
status: 500,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if (res instanceof Response) {
|
||||
if (is_dev) {
|
||||
res.headers.set(
|
||||
"Cache-Control",
|
||||
"no-cache, no-store, must-revalidate",
|
||||
);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
if (res) {
|
||||
let final_res = Response.json(
|
||||
_.omit(res, [
|
||||
"bunext_api_route_res_options",
|
||||
"bunext_api_route_res_transform_fn",
|
||||
]),
|
||||
{
|
||||
...(res.bunext_api_route_res_options || undefined),
|
||||
},
|
||||
);
|
||||
|
||||
if (res.bunext_api_route_res_transform_fn) {
|
||||
final_res = await res.bunext_api_route_res_transform_fn(
|
||||
final_res,
|
||||
);
|
||||
}
|
||||
|
||||
return final_res;
|
||||
}
|
||||
|
||||
return Response.json({ err: `Route handler error` });
|
||||
} catch (error: any) {
|
||||
const url = new URL(req.url);
|
||||
log.error(
|
||||
`API Route Error (${url.pathname}): ${error?.message}\n${error?.stack || ""}`,
|
||||
);
|
||||
return Response.json(
|
||||
{
|
||||
success: false,
|
||||
msg: errMsg,
|
||||
msg: `Route handler error: ${error?.message || "Internal Server Error"}`,
|
||||
},
|
||||
{
|
||||
status: 404,
|
||||
status: 500,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
const routeParams: BunxRouteParams = await grabRouteParams({
|
||||
req,
|
||||
query: match.query,
|
||||
});
|
||||
|
||||
let module: any;
|
||||
const now = Date.now();
|
||||
|
||||
const relative_match_path = grabRelativePath(match.filePath);
|
||||
|
||||
if (
|
||||
is_dev &&
|
||||
global.BUNEXT_SSR_BUNDLER_CTX_MAP?.[relative_match_path]?.path
|
||||
) {
|
||||
const target_import = path.join(
|
||||
ROOT_DIR,
|
||||
global.BUNEXT_SSR_BUNDLER_CTX_MAP[relative_match_path].path,
|
||||
);
|
||||
|
||||
module = await import(`${target_import}?t=${now}`);
|
||||
} else {
|
||||
const import_path = is_dev
|
||||
? `${match.filePath}?t=${now}`
|
||||
: match.filePath;
|
||||
module = await import(import_path);
|
||||
}
|
||||
|
||||
const config = module.config as BunextServerRouteConfig | undefined;
|
||||
|
||||
const maxBodyBytes = config?.max_request_body_mb
|
||||
? config.max_request_body_mb * MBInBytes
|
||||
: ServerDefaultRequestBodyLimitBytes;
|
||||
|
||||
const contentLength = req.headers.get("content-length");
|
||||
|
||||
if (contentLength) {
|
||||
const size = parseInt(contentLength, 10);
|
||||
|
||||
if (size > maxBodyBytes) {
|
||||
return Response.json(
|
||||
{
|
||||
success: false,
|
||||
msg: "Request Body Too Large!",
|
||||
},
|
||||
{
|
||||
status: 413,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
} else if (req.method !== "GET" && req.method !== "HEAD") {
|
||||
const body = await req.arrayBuffer();
|
||||
if (body.byteLength > maxBodyBytes) {
|
||||
return Response.json(
|
||||
{
|
||||
success: false,
|
||||
msg: "Request Body Too Large!",
|
||||
},
|
||||
{
|
||||
status: 413,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
routeParams.body = JSON.parse(new TextDecoder().decode(body) || "{}");
|
||||
}
|
||||
|
||||
const target_module = (module["default"] ||
|
||||
module["handler"]) as BunextAPIRouteHandler;
|
||||
|
||||
const res = await target_module?.({
|
||||
...routeParams,
|
||||
});
|
||||
|
||||
if (res instanceof Response) {
|
||||
if (is_dev) {
|
||||
res.headers.set(
|
||||
"Cache-Control",
|
||||
"no-cache, no-store, must-revalidate",
|
||||
);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
if (res) {
|
||||
let final_res = Response.json(
|
||||
_.omit(res, [
|
||||
"bunext_api_route_res_options",
|
||||
"bunext_api_route_res_transform_fn",
|
||||
]),
|
||||
{
|
||||
...(res.bunext_api_route_res_options || undefined),
|
||||
},
|
||||
);
|
||||
|
||||
if (res.bunext_api_route_res_transform_fn) {
|
||||
final_res = await res.bunext_api_route_res_transform_fn(final_res);
|
||||
}
|
||||
|
||||
return final_res;
|
||||
}
|
||||
|
||||
return Response.json({ err: `Route handler error` });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user