UNPKG

uws-connect

Version:

Use connect like middlewares with uWebSockets.js

96 lines (80 loc) 2.36 kB
import { HttpError } from './utils/HttpError.js' import * as qs from './utils/qs.js' export const CONTENT_TYPE_JSON = 'application/json' export const CONTENT_TYPE_FORM = 'application/x-www-form-urlencoded' /** * @param {string} v * @param {number} [def] * @returns {string|number} */ const toNumber = (v, def) => { const n = +v return isNaN(n) ? def || v : n } /** * body-parser for json and url-encoded data * * form data is parsed with [qs](https://www.npmjs.com/package/qs). * * @param {object} [options] * @param {number} [options.limit=1e6] max. content-length in bytes * @param {string} [options.type] default expected content-type * @returns {import('./types').BodyParserMiddleware} */ export function bodyParser(options) { const { limit = 1e6, type } = options || {} /** * @param {import('./types').BodyParserRequest} req * @param {import('./http/Response').Response} res * @param {function} next */ return (req, res, next) => { const buffer = [] let length = 0 const contentType = type || req.headers['content-type'] || '' const contentLength = Number( req.headers['content-length'] === undefined ? NaN : toNumber(req.headers['content-length'], NaN) ) const onEnd = (err) => { req.raw = Buffer.concat(buffer) const body = (req.text = req.raw.toString()) if (contentType.indexOf(CONTENT_TYPE_JSON) === 0) { try { req.body = JSON.parse(body) } catch (/** @type {Error|any} */ e) { err = new HttpError(400, 'err_json_parse', e) } } else if (contentType.indexOf(CONTENT_TYPE_FORM) === 0) { try { req.body = qs.parse(body) /* c8 ignore next 3 */ } catch (/** @type {Error|any} */ e) { err = new HttpError(400, 'err_urlencoded_parse', e) } } next(err) } const limitExceeded = () => { length = limit + 1 next(new HttpError(413, 'err_limit')) } if (contentLength > limit) { limitExceeded() return } req.on('data', (chunk) => { if (length > limit) { return } length += chunk.length if (length > limit || length > contentLength) { limitExceeded() return } buffer.push(chunk) }) req.on('end', () => onEnd()) } }