diff --git a/packages/next/package.json b/packages/next/package.json index 750dea159fa0be6..508cde7042022c3 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -79,6 +79,7 @@ "browserify-zlib": "0.2.0", "browserslist": "4.16.6", "buffer": "5.6.0", + "bytes": "3.1.0", "caniuse-lite": "^1.0.30001228", "chalk": "2.4.2", "chokidar": "3.5.1", @@ -90,6 +91,7 @@ "etag": "1.8.1", "events": "3.3.0", "find-cache-dir": "3.3.1", + "get-stream": "6.0.0", "get-orientation": "1.1.2", "https-browserify": "1.0.0", "image-size": "1.0.0", @@ -102,7 +104,6 @@ "postcss": "8.2.15", "process": "0.11.10", "querystring-es3": "0.2.1", - "raw-body": "2.4.1", "react-is": "17.0.2", "react-refresh": "0.8.3", "regenerator-runtime": "0.13.4", @@ -167,6 +168,7 @@ "@types/babel__generator": "7.6.2", "@types/babel__template": "7.4.0", "@types/babel__traverse": "7.11.0", + "@types/bytes": "3.1.0", "@types/ci-info": "2.0.0", "@types/compression": "0.0.36", "@types/content-disposition": "0.5.4", diff --git a/packages/next/server/api-utils.ts b/packages/next/server/api-utils.ts index d44c6fc8db9ed91..f24a66520ae432d 100644 --- a/packages/next/server/api-utils.ts +++ b/packages/next/server/api-utils.ts @@ -1,7 +1,8 @@ import { IncomingMessage, ServerResponse } from 'http' import { parse } from 'next/dist/compiled/content-type' import { CookieSerializeOptions } from 'next/dist/compiled/cookie' -import getRawBody from 'raw-body' +import getStream from 'get-stream' +import bytes from 'bytes' import { PageConfig, PreviewData } from 'next/types' import { Stream } from 'stream' import { isResSent, NextApiRequest, NextApiResponse } from '../shared/lib/utils' @@ -136,6 +137,45 @@ export async function apiResolver( } } +// Ensures that the user-provided encoding type is a valid encoding +function getValidEncoding(encoding: string): BufferEncoding | undefined { + switch (encoding) { + case 'ascii': { + return 'ascii' + } + case 'utf8': { + return 'utf8' + } + case 'utf-8': { + return 'utf-8' + } + case 'utf16le': { + return 'utf16le' + } + case 'ucs2': { + return 'ucs2' + } + case 'ucs-2': { + return 'ucs-2' + } + case 'base64': { + return 'base64' + } + case 'latin1': { + return 'latin1' + } + case 'binary': { + return 'binary' + } + case 'hex': { + return 'hex' + } + default: { + return undefined + } + } +} + /** * Parse incoming message like `json` or `urlencoded` * @param req request object @@ -151,14 +191,16 @@ export async function parseBody( contentType = parse('text/plain') } const { type, parameters } = contentType - const encoding = parameters.charset || 'utf-8' + + const encoding = getValidEncoding(parameters.charset) || 'utf-8' let buffer try { - buffer = await getRawBody(req, { encoding, limit }) + const maxBuffer = bytes.parse(limit) + buffer = await getStream.buffer(req, { maxBuffer, encoding }) } catch (e) { - if (isError(e) && e.type === 'entity.too.large') { + if (isError(e) && e.name === 'MaxBufferError') { throw new ApiError(413, `Body exceeded ${limit} limit`) } else { throw new ApiError(400, 'Invalid body') diff --git a/yarn.lock b/yarn.lock index 6b9f70a29baf41a..4bbf8fea9f7a535 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4400,6 +4400,11 @@ resolved "https://registry.yarnpkg.com/@types/braces/-/braces-3.0.1.tgz#5a284d193cfc61abb2e5a50d36ebbc50d942a32b" integrity sha512-+euflG6ygo4bn0JHtn4pYqcXwRtLvElQ7/nnjDu7iYG56H0+OhCd7d6Ug0IE3WcFpZozBKW2+80FUbv5QGk5AQ== +"@types/bytes@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/bytes/-/bytes-3.1.0.tgz#835a3e4aea3b4d7604aca216a78de372bff3ecc3" + integrity sha512-5YG1AiIC8HPPXRvYAIa7ehK3YMAwd0DWiPCtpuL9sgKceWLyWsVtLRA+lT4NkoanDNF9slwQ66lPizWDpgRlWA== + "@types/cacheable-request@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.1.tgz#5d22f3dded1fd3a84c0bbeb5039a7419c2c91976" @@ -10092,6 +10097,11 @@ get-stdin@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" +get-stream@6.0.0, get-stream@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.0.tgz#3e0012cb6827319da2706e601a1583e8629a6718" + integrity sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg== + get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" @@ -10109,11 +10119,6 @@ get-stream@^5.0.0, get-stream@^5.1.0: dependencies: pump "^3.0.0" -get-stream@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.0.tgz#3e0012cb6827319da2706e601a1583e8629a6718" - integrity sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg== - get-symbol-description@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" @@ -10878,7 +10883,7 @@ http-errors@1.7.2: statuses ">= 1.5.0 < 2" toidentifier "1.0.0" -http-errors@1.7.3, http-errors@~1.7.2: +http-errors@~1.7.2: version "1.7.3" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" dependencies: @@ -16495,15 +16500,6 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" -raw-body@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.1.tgz#30ac82f98bb5ae8c152e67149dac8d55153b168c" - dependencies: - bytes "3.1.0" - http-errors "1.7.3" - iconv-lite "0.4.24" - unpipe "1.0.0" - rc@^1.0.1, rc@^1.1.6, rc@^1.2.7, rc@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"