From e47438c3517f99cc2c628245673a6f82d5c519fc Mon Sep 17 00:00:00 2001 From: Blake Embrey Date: Fri, 3 Apr 2026 09:07:40 -0700 Subject: [PATCH 1/4] Add parameters option to parse --- README.md | 6 +++++- src/index.bench.ts | 4 ++++ src/index.ts | 20 +++++++++++++++----- src/parse.spec.ts | 9 +++++++++ 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 98cdb90..635f2dc 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ npm install content-type const contentType = require("content-type"); ``` -### contentType.parse(string) +### contentType.parse(string, options?) ```js const obj = contentType.parse("image/svg+xml; charset=utf-8"); @@ -33,6 +33,10 @@ Parse a `Content-Type` header. This will return an object with the following pro The parser is lenient, but will throw a `TypeError` when unable to parse a parameter due to ambiguity. E.g. `foo="` where the quote is unterminated. +#### Options + +- `parameters` (default: `true`): Set to `false` to skip parsing parameters, only returns `type`. + ### contentType.format(obj) ```js diff --git a/src/index.bench.ts b/src/index.bench.ts index 0636571..8065217 100644 --- a/src/index.bench.ts +++ b/src/index.bench.ts @@ -21,6 +21,10 @@ describe("parse", () => { parse(PARAMS_HEADER); }); + bench("simple parameters (options.parameters = false)", () => { + parse(PARAMS_HEADER, { parameters: false }); + }); + bench("quoted and escaped parameters", () => { parse(QUOTED_HEADER); }); diff --git a/src/index.ts b/src/index.ts index 5a536aa..29b3c50 100644 --- a/src/index.ts +++ b/src/index.ts @@ -55,10 +55,17 @@ export function format(obj: ContentType): string { return result; } +/** + * Options for parsing a `Content-Type` header. + */ +export interface ParseOptions { + parameters?: boolean; +} + /** * Parse a `Content-Type` header. */ -export function parse(header: string): ContentType { +export function parse(header: string, options?: ParseOptions): ContentType { const len = header.length; const semiIndex = header.indexOf(";"); const end = semiIndex !== -1 ? semiIndex : len; @@ -66,9 +73,9 @@ export function parse(header: string): ContentType { const valueEnd = trailingOWS(header, valueStart, end); const type = header.slice(valueStart, valueEnd).toLowerCase(); - if (semiIndex === -1) return { type }; + if (semiIndex === -1 || options?.parameters === false) return { type }; - const parameters = parseParameters(header, end, len); + const parameters = parseParameters(header, end + 1, len); return { type, parameters }; } @@ -80,13 +87,16 @@ function parseParameters( const parameters: Record = Object.create(null); parameter: while (index < len) { - index = skipOWS(header, index + 1, len); + index = skipOWS(header, index, len); const keyStart = index; while (index < len) { const char = header[index]; - if (char === ";") continue parameter; + if (char === ";") { + index++; + continue parameter; + } if (char === "=") { const keyEnd = trailingOWS(header, keyStart, index); diff --git a/src/parse.spec.ts b/src/parse.spec.ts index fd0bb16..8e24b39 100644 --- a/src/parse.spec.ts +++ b/src/parse.spec.ts @@ -213,4 +213,13 @@ describe("parse(string)", function () { }, }); }); + + it("should skip parsing parameters when options.parameters is false", function () { + const type = parse("text/html; charset=utf-8; foo=bar", { + parameters: false, + }); + assert.deepEqual(type, { + type: "text/html", + }); + }); }); From d2d175da5aa154443f9d9edc092529ad09ee4ee1 Mon Sep 17 00:00:00 2001 From: Blake Embrey Date: Fri, 3 Apr 2026 09:42:46 -0700 Subject: [PATCH 2/4] Increment past ; --- src/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/index.ts b/src/index.ts index 29b3c50..cc0be5b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -119,6 +119,7 @@ function parseParameters( } parameters[key] = value; + index++; continue parameter; } @@ -141,6 +142,7 @@ function parseParameters( const valueEnd = trailingOWS(header, valueStart, index); parameters[key] = header.slice(valueStart, valueEnd); + index++; continue parameter; } From b9910f0aba5961c9c24f982dfa6812346ba19ff1 Mon Sep 17 00:00:00 2001 From: Blake Embrey Date: Mon, 6 Apr 2026 11:46:59 -0700 Subject: [PATCH 3/4] Shorten error --- src/index.ts | 4 +--- src/parse.spec.ts | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/index.ts b/src/index.ts index cc0be5b..89e91e2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -113,9 +113,7 @@ function parseParameters( if (char === '"') { index = skipOWS(header, index, len); if (index < len && header[index] !== ";") { - throw new TypeError( - `Unexpected characters after parameter at index ${index}`, - ); + throw new TypeError(`Unexpected character at index ${index}`); } parameters[key] = value; diff --git a/src/parse.spec.ts b/src/parse.spec.ts index 8e24b39..8b20cfe 100644 --- a/src/parse.spec.ts +++ b/src/parse.spec.ts @@ -190,7 +190,7 @@ describe("parse(string)", function () { it("should error on non-OWS after closing quote", function () { assert.throws( parse.bind(null, 'text/plain; foo="bar"baz'), - /Unexpected characters after parameter at index 21/, + /Unexpected character at index 21/, ); }); From a50d5675a88817213991f11c7eea8c00735c1b80 Mon Sep 17 00:00:00 2001 From: Blake Embrey Date: Mon, 6 Apr 2026 14:45:25 -0700 Subject: [PATCH 4/4] Add missing length check --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 89e91e2..ac3f443 100644 --- a/src/index.ts +++ b/src/index.ts @@ -104,7 +104,7 @@ function parseParameters( index = skipOWS(header, index + 1, len); - if (header[index] === '"') { + if (index < len && header[index] === '"') { index++; let value = "";