forked from koajs/bodyparser
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
16 changed files
with
903 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
nodeLinker: node-modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import * as Koa from 'koa'; | ||
import { BodyParserOptions } from './body-parser.types.js'; | ||
import 'co-body'; | ||
|
||
declare module 'koa' { | ||
interface Request { | ||
body?: any; | ||
rawBody: string; | ||
} | ||
} | ||
declare module 'http' { | ||
interface IncomingMessage { | ||
body?: any; | ||
rawBody: string; | ||
} | ||
} | ||
declare function bodyParserWrapper(opts?: BodyParserOptions): (ctx: Koa.Context, next: Koa.Next) => Promise<any>; | ||
|
||
export { bodyParserWrapper }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
var __create = Object.create; | ||
var __defProp = Object.defineProperty; | ||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
var __getOwnPropNames = Object.getOwnPropertyNames; | ||
var __getProtoOf = Object.getPrototypeOf; | ||
var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
var __export = (target, all) => { | ||
for (var name in all) | ||
__defProp(target, name, { get: all[name], enumerable: true }); | ||
}; | ||
var __copyProps = (to, from, except, desc) => { | ||
if (from && typeof from === "object" || typeof from === "function") { | ||
for (let key of __getOwnPropNames(from)) | ||
if (!__hasOwnProp.call(to, key) && key !== except) | ||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
} | ||
return to; | ||
}; | ||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( | ||
// If the importer is in node compatibility mode or this is not an ESM | ||
// file that has been converted to a CommonJS file using a Babel- | ||
// compatible transform (i.e. "__esModule" has not been set), then set | ||
// "default" to the CommonJS "module.exports" for node compatibility. | ||
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, | ||
mod | ||
)); | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
|
||
// src/body-parser.ts | ||
var body_parser_exports = {}; | ||
__export(body_parser_exports, { | ||
bodyParserWrapper: () => bodyParserWrapper | ||
}); | ||
module.exports = __toCommonJS(body_parser_exports); | ||
var import_co_body = __toESM(require("co-body")); | ||
|
||
// src/body-parser.utils.ts | ||
var import_lodash = __toESM(require("lodash.merge")); | ||
var import_type_is = __toESM(require("type-is")); | ||
|
||
// src/body-parser.types.ts | ||
var supportedBodyTypes = ["json", "form", "text", "xml"]; | ||
|
||
// src/body-parser.utils.ts | ||
var UnsupportedBodyTypeError = class extends Error { | ||
constructor(wrongType) { | ||
super(); | ||
this.name = "UnsupportedBodyTypeError"; | ||
this.message = `Invalid enabled type '${wrongType}'. make sure to pass an array contains supported types ([${supportedBodyTypes}]).`; | ||
} | ||
}; | ||
function getIsEnabledBodyAs(enableTypes) { | ||
for (const enabledType of enableTypes) { | ||
if (!supportedBodyTypes.includes(enabledType)) { | ||
throw new UnsupportedBodyTypeError(enabledType); | ||
} | ||
} | ||
const isEnabledBodyAs = supportedBodyTypes.reduce( | ||
(prevResult, currentType) => ({ | ||
...prevResult, | ||
[currentType]: enableTypes.includes(currentType) | ||
}), | ||
{} | ||
); | ||
return isEnabledBodyAs; | ||
} | ||
function getMimeTypes(extendTypes) { | ||
for (const extendedTypeKey of Object.keys(extendTypes)) { | ||
const extendedType = extendTypes[extendedTypeKey]; | ||
if (!supportedBodyTypes.includes(extendedTypeKey) || !Array.isArray(extendedType)) { | ||
throw new UnsupportedBodyTypeError(extendedTypeKey); | ||
} | ||
} | ||
const defaultMimeTypes = { | ||
// default json mime types | ||
json: [ | ||
"application/json", | ||
"application/json-patch+json", | ||
"application/vnd.api+json", | ||
"application/csp-report", | ||
"application/reports+json", | ||
"application/scim+json" | ||
], | ||
// default form mime types | ||
form: ["application/x-www-form-urlencoded"], | ||
// default text mime types | ||
text: ["text/plain"], | ||
// default xml mime types | ||
xml: ["text/xml", "application/xml"] | ||
}; | ||
const mimeTypes = (0, import_lodash.default)(defaultMimeTypes, extendTypes); | ||
return mimeTypes; | ||
} | ||
function isTypes(contentTypeValue, types) { | ||
if (typeof contentTypeValue === "string") { | ||
contentTypeValue = contentTypeValue.replace(/;$/, ""); | ||
} | ||
return import_type_is.default.is(contentTypeValue, types); | ||
} | ||
|
||
// src/body-parser.ts | ||
function bodyParserWrapper(opts = {}) { | ||
opts.jsonLimit = opts.jsonLimit || "10mb"; | ||
const { | ||
patchNode = false, | ||
parsedMethods = ["POST", "PUT", "PATCH"], | ||
detectJSON, | ||
onError, | ||
enableTypes = ["json", "form"], | ||
extendTypes = {}, | ||
enableRawChecking = false, | ||
...restOpts | ||
} = opts; | ||
const isEnabledBodyAs = getIsEnabledBodyAs(enableTypes); | ||
const mimeTypes = getMimeTypes(extendTypes); | ||
async function parseBody(ctx) { | ||
const shouldParseBodyAs = (type) => { | ||
return Boolean( | ||
isEnabledBodyAs[type] && isTypes(ctx.request.get("content-type"), mimeTypes[type]) | ||
); | ||
}; | ||
const bodyType = detectJSON?.(ctx) || shouldParseBodyAs("json") ? "json" : shouldParseBodyAs("form") ? "form" : shouldParseBodyAs("text") || shouldParseBodyAs("xml") ? "text" : null; | ||
if (!bodyType) | ||
return {}; | ||
const parserOptions = { | ||
// force co-body return raw body | ||
returnRawBody: true, | ||
strict: bodyType === "json" ? restOpts.jsonStrict : void 0, | ||
[`${bodyType}Types`]: mimeTypes[bodyType], | ||
limit: restOpts[`${shouldParseBodyAs("xml") ? "xml" : bodyType}Limit`] | ||
}; | ||
return import_co_body.default[bodyType](ctx, parserOptions); | ||
} | ||
return async function(ctx, next) { | ||
if ( | ||
// method souldn't be parsed | ||
!parsedMethods.includes(ctx.method.toUpperCase()) || // patchNode enabled and raw request already parsed | ||
patchNode && ctx.req.body !== void 0 || // koa request body already parsed | ||
ctx.request.body !== void 0 || // bodyparser disabled | ||
ctx.disableBodyParser | ||
) | ||
return next(); | ||
if (enableRawChecking && ctx.req.body !== void 0) { | ||
ctx.request.body = ctx.req.body; | ||
return next(); | ||
} | ||
try { | ||
const response = await parseBody(ctx); | ||
if (patchNode) { | ||
ctx.req.body = "parsed" in response ? response.parsed : {}; | ||
if (ctx.req.rawBody === void 0) | ||
ctx.req.rawBody = response.raw; | ||
} | ||
ctx.request.body = "parsed" in response ? response.parsed : {}; | ||
if (ctx.request.rawBody === void 0) | ||
ctx.request.rawBody = response.raw; | ||
} catch (err) { | ||
if (!onError) | ||
throw err; | ||
onError(err, ctx); | ||
} | ||
return next(); | ||
}; | ||
} | ||
// Annotate the CommonJS export names for ESM import in node: | ||
0 && (module.exports = { | ||
bodyParserWrapper | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
// src/body-parser.ts | ||
import parser from "co-body"; | ||
|
||
// src/body-parser.utils.ts | ||
import deepMerge from "lodash.merge"; | ||
import typeis from "type-is"; | ||
|
||
// src/body-parser.types.ts | ||
var supportedBodyTypes = ["json", "form", "text", "xml"]; | ||
|
||
// src/body-parser.utils.ts | ||
var UnsupportedBodyTypeError = class extends Error { | ||
constructor(wrongType) { | ||
super(); | ||
this.name = "UnsupportedBodyTypeError"; | ||
this.message = `Invalid enabled type '${wrongType}'. make sure to pass an array contains supported types ([${supportedBodyTypes}]).`; | ||
} | ||
}; | ||
function getIsEnabledBodyAs(enableTypes) { | ||
for (const enabledType of enableTypes) { | ||
if (!supportedBodyTypes.includes(enabledType)) { | ||
throw new UnsupportedBodyTypeError(enabledType); | ||
} | ||
} | ||
const isEnabledBodyAs = supportedBodyTypes.reduce( | ||
(prevResult, currentType) => ({ | ||
...prevResult, | ||
[currentType]: enableTypes.includes(currentType) | ||
}), | ||
{} | ||
); | ||
return isEnabledBodyAs; | ||
} | ||
function getMimeTypes(extendTypes) { | ||
for (const extendedTypeKey of Object.keys(extendTypes)) { | ||
const extendedType = extendTypes[extendedTypeKey]; | ||
if (!supportedBodyTypes.includes(extendedTypeKey) || !Array.isArray(extendedType)) { | ||
throw new UnsupportedBodyTypeError(extendedTypeKey); | ||
} | ||
} | ||
const defaultMimeTypes = { | ||
// default json mime types | ||
json: [ | ||
"application/json", | ||
"application/json-patch+json", | ||
"application/vnd.api+json", | ||
"application/csp-report", | ||
"application/reports+json", | ||
"application/scim+json" | ||
], | ||
// default form mime types | ||
form: ["application/x-www-form-urlencoded"], | ||
// default text mime types | ||
text: ["text/plain"], | ||
// default xml mime types | ||
xml: ["text/xml", "application/xml"] | ||
}; | ||
const mimeTypes = deepMerge(defaultMimeTypes, extendTypes); | ||
return mimeTypes; | ||
} | ||
function isTypes(contentTypeValue, types) { | ||
if (typeof contentTypeValue === "string") { | ||
contentTypeValue = contentTypeValue.replace(/;$/, ""); | ||
} | ||
return typeis.is(contentTypeValue, types); | ||
} | ||
|
||
// src/body-parser.ts | ||
function bodyParserWrapper(opts = {}) { | ||
opts.jsonLimit = opts.jsonLimit || "10mb"; | ||
const { | ||
patchNode = false, | ||
parsedMethods = ["POST", "PUT", "PATCH"], | ||
detectJSON, | ||
onError, | ||
enableTypes = ["json", "form"], | ||
extendTypes = {}, | ||
enableRawChecking = false, | ||
...restOpts | ||
} = opts; | ||
const isEnabledBodyAs = getIsEnabledBodyAs(enableTypes); | ||
const mimeTypes = getMimeTypes(extendTypes); | ||
async function parseBody(ctx) { | ||
const shouldParseBodyAs = (type) => { | ||
return Boolean( | ||
isEnabledBodyAs[type] && isTypes(ctx.request.get("content-type"), mimeTypes[type]) | ||
); | ||
}; | ||
const bodyType = detectJSON?.(ctx) || shouldParseBodyAs("json") ? "json" : shouldParseBodyAs("form") ? "form" : shouldParseBodyAs("text") || shouldParseBodyAs("xml") ? "text" : null; | ||
if (!bodyType) | ||
return {}; | ||
const parserOptions = { | ||
// force co-body return raw body | ||
returnRawBody: true, | ||
strict: bodyType === "json" ? restOpts.jsonStrict : void 0, | ||
[`${bodyType}Types`]: mimeTypes[bodyType], | ||
limit: restOpts[`${shouldParseBodyAs("xml") ? "xml" : bodyType}Limit`] | ||
}; | ||
return parser[bodyType](ctx, parserOptions); | ||
} | ||
return async function(ctx, next) { | ||
if ( | ||
// method souldn't be parsed | ||
!parsedMethods.includes(ctx.method.toUpperCase()) || // patchNode enabled and raw request already parsed | ||
patchNode && ctx.req.body !== void 0 || // koa request body already parsed | ||
ctx.request.body !== void 0 || // bodyparser disabled | ||
ctx.disableBodyParser | ||
) | ||
return next(); | ||
if (enableRawChecking && ctx.req.body !== void 0) { | ||
ctx.request.body = ctx.req.body; | ||
return next(); | ||
} | ||
try { | ||
const response = await parseBody(ctx); | ||
if (patchNode) { | ||
ctx.req.body = "parsed" in response ? response.parsed : {}; | ||
if (ctx.req.rawBody === void 0) | ||
ctx.req.rawBody = response.raw; | ||
} | ||
ctx.request.body = "parsed" in response ? response.parsed : {}; | ||
if (ctx.request.rawBody === void 0) | ||
ctx.request.rawBody = response.raw; | ||
} catch (err) { | ||
if (!onError) | ||
throw err; | ||
onError(err, ctx); | ||
} | ||
return next(); | ||
}; | ||
} | ||
export { | ||
bodyParserWrapper | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { Options } from 'co-body'; | ||
import * as Koa from 'koa'; | ||
|
||
declare const supportedBodyTypes: readonly ["json", "form", "text", "xml"]; | ||
type BodyType = (typeof supportedBodyTypes)[number]; | ||
type BodyParserOptions = { | ||
parsedMethods?: string[]; | ||
patchNode?: boolean; | ||
detectJSON?: (ctx: Koa.Context) => boolean; | ||
onError?: (error: Error, ctx: Koa.Context) => void; | ||
enableRawChecking?: boolean; | ||
enableTypes?: BodyType[]; | ||
extendTypes?: { | ||
[K in BodyType]?: string[]; | ||
}; | ||
jsonStrict?: Options['strict']; | ||
jsonLimit?: Options['limit']; | ||
formLimit?: Options['limit']; | ||
textLimit?: Options['limit']; | ||
xmlLimit?: Options['limit']; | ||
} & Pick<Options, 'encoding'>; | ||
|
||
export { BodyParserOptions, BodyType, supportedBodyTypes }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
var __defProp = Object.defineProperty; | ||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
var __getOwnPropNames = Object.getOwnPropertyNames; | ||
var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
var __export = (target, all) => { | ||
for (var name in all) | ||
__defProp(target, name, { get: all[name], enumerable: true }); | ||
}; | ||
var __copyProps = (to, from, except, desc) => { | ||
if (from && typeof from === "object" || typeof from === "function") { | ||
for (let key of __getOwnPropNames(from)) | ||
if (!__hasOwnProp.call(to, key) && key !== except) | ||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
} | ||
return to; | ||
}; | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
|
||
// src/body-parser.types.ts | ||
var body_parser_types_exports = {}; | ||
__export(body_parser_types_exports, { | ||
supportedBodyTypes: () => supportedBodyTypes | ||
}); | ||
module.exports = __toCommonJS(body_parser_types_exports); | ||
var supportedBodyTypes = ["json", "form", "text", "xml"]; | ||
// Annotate the CommonJS export names for ESM import in node: | ||
0 && (module.exports = { | ||
supportedBodyTypes | ||
}); |
Oops, something went wrong.