@adonisjs/bodyparser
Version:
BodyParser middleware for AdonisJS http server to read and parse request body
136 lines (135 loc) • 5.13 kB
JavaScript
import "../file-CexcC_98.js";
import { a as prepareJSONParserOptions, c as streamFile, i as parseJSON, l as Multipart, n as parseForm, o as parseText, r as prepareFormParserOptions, s as prepareTextParserOptions, t as prepareMultipartConfig, u as debug_default } from "../multipart-C3ADW2mk.js";
import { isAbsolute, join } from "node:path";
import string from "@poppinss/utils/string";
import { Exception } from "@poppinss/utils/exception";
import { tmpdir } from "node:os";
var BodyParserMiddleware = class {
#config;
#parsersConfig;
constructor(config, _featureFlags) {
this.#config = config;
this.#parsersConfig = {
raw: prepareTextParserOptions(this.#config.raw),
form: prepareFormParserOptions(this.#config.form),
json: prepareJSONParserOptions(this.#config.json),
multipart: prepareMultipartConfig(this.#config.multipart)
};
debug_default("using config %O", this.#config);
}
#isType(request, types) {
return !!(types && types.length && request.is(types));
}
#getExceptionFor(error) {
switch (error.type) {
case "encoding.unsupported": return new Exception(error.message, {
status: error.status,
code: "E_ENCODING_UNSUPPORTED"
});
case "entity.too.large": return new Exception(error.message, {
status: error.status,
code: "E_REQUEST_ENTITY_TOO_LARGE"
});
case "request.aborted": return new Exception(error.message, {
status: error.status,
code: "E_REQUEST_ABORTED"
});
default: return error;
}
}
#getTmpPath(config) {
if (typeof config.tmpFileName === "function") {
const tmpPath = config.tmpFileName();
return isAbsolute(tmpPath) ? tmpPath : join(tmpdir(), tmpPath);
}
return join(tmpdir(), string.uuid());
}
async handle(ctx, next) {
ctx.request["__raw_files"] = {};
const requestUrl = ctx.request.url();
const requestMethod = ctx.request.method();
if (!this.#config.allowedMethods.includes(requestMethod)) {
debug_default("skipping HTTP request \"%s:%s\"", requestMethod, requestUrl);
return next();
}
if (!ctx.request.hasBody()) {
debug_default("skipping as request has no body \"%s:%s\"", requestMethod, requestUrl);
return next();
}
const multipartConfig = this.#config["multipart"];
if (this.#isType(ctx.request, multipartConfig.types)) {
debug_default("detected multipart request \"%s:%s\"", requestMethod, requestUrl);
ctx.request.multipart = new Multipart(ctx, this.#parsersConfig.multipart, {});
ctx.request.bodyType = "multipart";
if (multipartConfig.autoProcess === false) {
debug_default("skipping auto processing of multipart request \"%s:%s\"", requestMethod, requestUrl);
return next();
}
if (ctx.route && multipartConfig.processManually.includes(ctx.route.pattern)) {
debug_default("skipping auto processing of multipart request \"%s:%s\"", requestMethod, requestUrl);
return next();
}
if (ctx.route && Array.isArray(multipartConfig.autoProcess) && !multipartConfig.autoProcess.includes(ctx.route.pattern)) {
debug_default("skipping auto processing of multipart request \"%s:%s\"", requestMethod, requestUrl);
return next();
}
debug_default("auto processing multipart request \"%s:%s\"", requestMethod, requestUrl);
ctx.request.multipart.onFile("*", { deferValidations: true }, async (part, reporter) => {
try {
const tmpPath = this.#getTmpPath(multipartConfig);
await streamFile(part, tmpPath, reporter);
return { tmpPath };
} catch (error) {
ctx.request.multipart.abort(error);
}
});
try {
await ctx.request.multipart.process();
return next();
} catch (error) {
throw error;
}
}
const formConfig = this.#config["form"];
if (this.#isType(ctx.request, formConfig.types)) {
debug_default("detected urlencoded request \"%s:%s\"", requestMethod, requestUrl);
try {
const { parsed, raw } = await parseForm(ctx.request.request, this.#parsersConfig.form);
ctx.request.setInitialBody(parsed);
ctx.request.updateRawBody(raw);
ctx.request.bodyType = "urlencoded";
return next();
} catch (error) {
throw this.#getExceptionFor(error);
}
}
const jsonConfig = this.#config["json"];
if (this.#isType(ctx.request, jsonConfig.types)) {
debug_default("detected JSON request \"%s:%s\"", requestMethod, requestUrl);
try {
const { parsed, raw } = await parseJSON(ctx.request.request, this.#parsersConfig.json);
ctx.request.setInitialBody(parsed);
ctx.request.updateRawBody(raw);
ctx.request.bodyType = "json";
return next();
} catch (error) {
throw this.#getExceptionFor(error);
}
}
const rawConfig = this.#config["raw"];
if (this.#isType(ctx.request, rawConfig.types)) {
debug_default("parsing raw body \"%s:%s\"", requestMethod, requestUrl);
try {
ctx.request.setInitialBody({});
ctx.request.updateRawBody(await parseText(ctx.request.request, this.#parsersConfig.raw));
ctx.request.bodyType = "raw";
return next();
} catch (error) {
throw this.#getExceptionFor(error);
}
}
ctx.request.bodyType = "unknown";
await next();
}
};
export { BodyParserMiddleware };