Initial commit

This commit is contained in:
2026-06-11 02:38:02 +00:00
commit 1f1b302e6e
6706 changed files with 440580 additions and 0 deletions
+292
View File
@@ -0,0 +1,292 @@
2.0.1 / 2025-03-27
==========
2.0.0 / 2024-08-31
==========
* Drop node <18
* Use `content-type@^1.0.5` and `media-typer@^1.0.0` for type validation
- No behavior changes, upgrades `media-typer`
* deps: mime-types@^3.0.0
- Add `application/toml` with extension `.toml`
- Add `application/ubjson` with extension `.ubj`
- Add `application/x-keepass2` with extension `.kdbx`
- Add deprecated iWorks mime types and extensions
- Add extension `.amr` to `audio/amr`
- Add extension `.cjs` to `application/node`
- Add extension `.dbf` to `application/vnd.dbf`
- Add extension `.m4s` to `video/iso.segment`
- Add extension `.mvt` to `application/vnd.mapbox-vector-tile`
- Add extension `.mxmf` to `audio/mobile-xmf`
- Add extension `.opus` to `audio/ogg`
- Add extension `.rar` to `application/vnd.rar`
- Add extension `.td` to `application/urc-targetdesc+xml`
- Add extension `.trig` to `application/trig`
- Add extensions from IANA for `application/*+xml` types
- Add `image/avif` with extension `.avif`
- Add `image/ktx2` with extension `.ktx2`
- Add `image/vnd.ms-dds` with extension `.dds`
- Add new upstream MIME types
- Fix extension of `application/vnd.apple.keynote` to be `.key`
- Remove ambigious extensions from IANA for `application/*+xml` types
- Update primary extension to `.es` for `application/ecmascript`
1.6.18 / 2019-04-26
===================
* Fix regression passing request object to `typeis.is`
1.6.17 / 2019-04-25
===================
* deps: mime-types@~2.1.24
- Add Apple file extensions from IANA
- Add extension `.csl` to `application/vnd.citationstyles.style+xml`
- Add extension `.es` to `application/ecmascript`
- Add extension `.nq` to `application/n-quads`
- Add extension `.nt` to `application/n-triples`
- Add extension `.owl` to `application/rdf+xml`
- Add extensions `.siv` and `.sieve` to `application/sieve`
- Add extensions from IANA for `image/*` types
- Add extensions from IANA for `model/*` types
- Add extensions to HEIC image types
- Add new mime types
- Add `text/mdx` with extension `.mdx`
* perf: prevent internal `throw` on invalid type
1.6.16 / 2018-02-16
===================
* deps: mime-types@~2.1.18
- Add `application/raml+yaml` with extension `.raml`
- Add `application/wasm` with extension `.wasm`
- Add `text/shex` with extension `.shex`
- Add extensions for JPEG-2000 images
- Add extensions from IANA for `message/*` types
- Add extension `.mjs` to `application/javascript`
- Add extension `.wadl` to `application/vnd.sun.wadl+xml`
- Add extension `.gz` to `application/gzip`
- Add glTF types and extensions
- Add new mime types
- Update extensions `.md` and `.markdown` to be `text/markdown`
- Update font MIME types
- Update `text/hjson` to registered `application/hjson`
1.6.15 / 2017-03-31
===================
* deps: mime-types@~2.1.15
- Add new mime types
1.6.14 / 2016-11-18
===================
* deps: mime-types@~2.1.13
- Add new mime types
1.6.13 / 2016-05-18
===================
* deps: mime-types@~2.1.11
- Add new mime types
1.6.12 / 2016-02-28
===================
* deps: mime-types@~2.1.10
- Add new mime types
- Fix extension of `application/dash+xml`
- Update primary extension for `audio/mp4`
1.6.11 / 2016-01-29
===================
* deps: mime-types@~2.1.9
- Add new mime types
1.6.10 / 2015-12-01
===================
* deps: mime-types@~2.1.8
- Add new mime types
1.6.9 / 2015-09-27
==================
* deps: mime-types@~2.1.7
- Add new mime types
1.6.8 / 2015-09-04
==================
* deps: mime-types@~2.1.6
- Add new mime types
1.6.7 / 2015-08-20
==================
* Fix type error when given invalid type to match against
* deps: mime-types@~2.1.5
- Add new mime types
1.6.6 / 2015-07-31
==================
* deps: mime-types@~2.1.4
- Add new mime types
1.6.5 / 2015-07-16
==================
* deps: mime-types@~2.1.3
- Add new mime types
1.6.4 / 2015-07-01
==================
* deps: mime-types@~2.1.2
- Add new mime types
* perf: enable strict mode
* perf: remove argument reassignment
1.6.3 / 2015-06-08
==================
* deps: mime-types@~2.1.1
- Add new mime types
* perf: reduce try block size
* perf: remove bitwise operations
1.6.2 / 2015-05-10
==================
* deps: mime-types@~2.0.11
- Add new mime types
1.6.1 / 2015-03-13
==================
* deps: mime-types@~2.0.10
- Add new mime types
1.6.0 / 2015-02-12
==================
* fix false-positives in `hasBody` `Transfer-Encoding` check
* support wildcard for both type and subtype (`*/*`)
1.5.7 / 2015-02-09
==================
* fix argument reassignment
* deps: mime-types@~2.0.9
- Add new mime types
1.5.6 / 2015-01-29
==================
* deps: mime-types@~2.0.8
- Add new mime types
1.5.5 / 2014-12-30
==================
* deps: mime-types@~2.0.7
- Add new mime types
- Fix missing extensions
- Fix various invalid MIME type entries
- Remove example template MIME types
- deps: mime-db@~1.5.0
1.5.4 / 2014-12-10
==================
* deps: mime-types@~2.0.4
- Add new mime types
- deps: mime-db@~1.3.0
1.5.3 / 2014-11-09
==================
* deps: mime-types@~2.0.3
- Add new mime types
- deps: mime-db@~1.2.0
1.5.2 / 2014-09-28
==================
* deps: mime-types@~2.0.2
- Add new mime types
- deps: mime-db@~1.1.0
1.5.1 / 2014-09-07
==================
* Support Node.js 0.6
* deps: media-typer@0.3.0
* deps: mime-types@~2.0.1
- Support Node.js 0.6
1.5.0 / 2014-09-05
==================
* fix `hasbody` to be true for `content-length: 0`
1.4.0 / 2014-09-02
==================
* update mime-types
1.3.2 / 2014-06-24
==================
* use `~` range on mime-types
1.3.1 / 2014-06-19
==================
* fix global variable leak
1.3.0 / 2014-06-19
==================
* improve type parsing
- invalid media type never matches
- media type not case-sensitive
- extra LWS does not affect results
1.2.2 / 2014-06-19
==================
* fix behavior on unknown type argument
1.2.1 / 2014-06-03
==================
* switch dependency from `mime` to `mime-types@1.0.0`
1.2.0 / 2014-05-11
==================
* support suffix matching:
- `+json` matches `application/vnd+json`
- `*/vnd+json` matches `application/vnd+json`
- `application/*+json` matches `application/vnd+json`
1.1.0 / 2014-04-12
==================
* add non-array values support
* expose internal utilities:
- `.is()`
- `.hasBody()`
- `.normalize()`
- `.match()`
1.0.1 / 2014-03-30
==================
* add `multipart` as a shorthand
+23
View File
@@ -0,0 +1,23 @@
(The MIT License)
Copyright (c) 2014 Jonathan Ong <me@jongleberry.com>
Copyright (c) 2014-2015 Douglas Christopher Wilson <doug@somethingdoug.com>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+198
View File
@@ -0,0 +1,198 @@
# type-is
[![NPM Version][npm-version-image]][npm-url]
[![NPM Downloads][npm-downloads-image]][npm-url]
[![Node.js Version][node-version-image]][node-version-url]
[![Build Status][ci-image]][ci-url]
[![Test Coverage][coveralls-image]][coveralls-url]
Infer the content-type of a request.
## Install
This is a [Node.js](https://nodejs.org/en/) module available through the
[npm registry](https://www.npmjs.com/). Installation is done using the
[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
```sh
$ npm install type-is
```
## API
```js
var http = require('http')
var typeis = require('type-is')
http.createServer(function (req, res) {
var istext = typeis(req, ['text/*'])
res.end('you ' + (istext ? 'sent' : 'did not send') + ' me text')
})
```
### typeis(request, types)
Checks if the `request` is one of the `types`. If the request has no body,
even if there is a `Content-Type` header, then `null` is returned. If the
`Content-Type` header is invalid or does not matches any of the `types`, then
`false` is returned. Otherwise, a string of the type that matched is returned.
The `request` argument is expected to be a Node.js HTTP request. The `types`
argument is an array of type strings.
Each type in the `types` array can be one of the following:
- A file extension name such as `json`. This name will be returned if matched.
- A mime type such as `application/json`.
- A mime type with a wildcard such as `*/*` or `*/json` or `application/*`.
The full mime type will be returned if matched.
- A suffix such as `+json`. This can be combined with a wildcard such as
`*/vnd+json` or `application/*+json`. The full mime type will be returned
if matched.
Some examples to illustrate the inputs and returned value:
```js
// req.headers.content-type = 'application/json'
typeis(req, ['json']) // => 'json'
typeis(req, ['html', 'json']) // => 'json'
typeis(req, ['application/*']) // => 'application/json'
typeis(req, ['application/json']) // => 'application/json'
typeis(req, ['html']) // => false
```
### typeis.hasBody(request)
Returns a Boolean if the given `request` has a body, regardless of the
`Content-Type` header.
Having a body has no relation to how large the body is (it may be 0 bytes).
This is similar to how file existence works. If a body does exist, then this
indicates that there is data to read from the Node.js request stream.
```js
if (typeis.hasBody(req)) {
// read the body, since there is one
req.on('data', function (chunk) {
// ...
})
}
```
### typeis.is(mediaType, types)
Checks if the `mediaType` is one of the `types`. If the `mediaType` is invalid
or does not matches any of the `types`, then `false` is returned. Otherwise, a
string of the type that matched is returned.
The `mediaType` argument is expected to be a
[media type](https://tools.ietf.org/html/rfc6838) string. The `types` argument
is an array of type strings.
Each type in the `types` array can be one of the following:
- A file extension name such as `json`. This name will be returned if matched.
- A mime type such as `application/json`.
- A mime type with a wildcard such as `*/*` or `*/json` or `application/*`.
The full mime type will be returned if matched.
- A suffix such as `+json`. This can be combined with a wildcard such as
`*/vnd+json` or `application/*+json`. The full mime type will be returned
if matched.
Some examples to illustrate the inputs and returned value:
```js
var mediaType = 'application/json'
typeis.is(mediaType, ['json']) // => 'json'
typeis.is(mediaType, ['html', 'json']) // => 'json'
typeis.is(mediaType, ['application/*']) // => 'application/json'
typeis.is(mediaType, ['application/json']) // => 'application/json'
typeis.is(mediaType, ['html']) // => false
```
### typeis.match(expected, actual)
Match the type string `expected` with `actual`, taking in to account wildcards.
A wildcard can only be in the type of the subtype part of a media type and only
in the `expected` value (as `actual` should be the real media type to match). A
suffix can still be included even with a wildcard subtype. If an input is
malformed, `false` will be returned.
```js
typeis.match('text/html', 'text/html') // => true
typeis.match('*/html', 'text/html') // => true
typeis.match('text/*', 'text/html') // => true
typeis.match('*/*', 'text/html') // => true
typeis.match('*/*+json', 'application/x-custom+json') // => true
```
### typeis.normalize(type)
Normalize a `type` string. This works by performing the following:
- If the `type` is not a string, `false` is returned.
- If the string starts with `+` (so it is a `+suffix` shorthand like `+json`),
then it is expanded to contain the complete wildcard notation of `*/*+suffix`.
- If the string contains a `/`, then it is returned as the type.
- Else the string is assumed to be a file extension and the mapped media type is
returned, or `false` is there is no mapping.
This includes two special mappings:
- `'multipart'` -> `'multipart/*'`
- `'urlencoded'` -> `'application/x-www-form-urlencoded'`
## Examples
### Example body parser
```js
var express = require('express')
var typeis = require('type-is')
var app = express()
app.use(function bodyParser (req, res, next) {
if (!typeis.hasBody(req)) {
return next()
}
switch (typeis(req, ['urlencoded', 'json', 'multipart'])) {
case 'urlencoded':
// parse urlencoded body
throw new Error('implement urlencoded body parsing')
case 'json':
// parse json body
throw new Error('implement json body parsing')
case 'multipart':
// parse multipart body
throw new Error('implement multipart body parsing')
default:
// 415 error code
res.statusCode = 415
res.end()
break
}
})
```
## License
[MIT](LICENSE)
[ci-image]: https://badgen.net/github/checks/jshttp/type-is/master?label=ci
[ci-url]: https://github.com/jshttp/type-is/actions/workflows/ci.yml
[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/type-is/master
[coveralls-url]: https://coveralls.io/r/jshttp/type-is?branch=master
[node-version-image]: https://badgen.net/npm/node/type-is
[node-version-url]: https://nodejs.org/en/download
[npm-downloads-image]: https://badgen.net/npm/dm/type-is
[npm-url]: https://npmjs.org/package/type-is
[npm-version-image]: https://badgen.net/npm/v/type-is
[travis-image]: https://badgen.net/travis/jshttp/type-is/master
[travis-url]: https://travis-ci.org/jshttp/type-is
+240
View File
@@ -0,0 +1,240 @@
/*!
* type-is
* Copyright(c) 2014 Jonathan Ong
* Copyright(c) 2014-2015 Douglas Christopher Wilson
* MIT Licensed
*/
'use strict'
/**
* Module dependencies.
* @private
*/
var contentType = require('content-type')
var mime = require('mime-types')
var typer = require('media-typer')
/**
* Module exports.
* @public
*/
module.exports = typeofrequest
module.exports.is = typeis
module.exports.hasBody = hasbody
module.exports.normalize = normalize
module.exports.match = mimeMatch
/**
* Compare a `value` content-type with `types`.
* Each `type` can be an extension like `html`,
* a special shortcut like `multipart` or `urlencoded`,
* or a mime type.
*
* If no types match, `false` is returned.
* Otherwise, the first `type` that matches is returned.
*
* @param {String} value
* @param {Array} types
* @public
*/
function typeis (value, types_) {
// Backward compatibility. TODO: Remove.
if (value && typeof value === 'object') {
value = value.headers['content-type']
}
var i
var types = types_
// remove parameters and normalize
var val = normalizeType(value)
// no type or invalid
if (!val) {
return false
}
// support flattened arguments
if (types && !Array.isArray(types)) {
types = new Array(arguments.length - 1)
for (i = 0; i < types.length; i++) {
types[i] = arguments[i + 1]
}
}
// no types, return the content type
if (!types || !types.length) {
return val
}
var type
for (i = 0; i < types.length; i++) {
if (mimeMatch(normalize(type = types[i]), val)) {
return type[0] === '+' || type.indexOf('*') !== -1
? val
: type
}
}
// no matches
return false
}
/**
* Check if a request has a request body.
* A request with a body __must__ either have `transfer-encoding`
* or `content-length` headers set.
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3
*
* @param {Object} request
* @return {Boolean}
* @public
*/
function hasbody (req) {
return req.headers['transfer-encoding'] !== undefined ||
!isNaN(req.headers['content-length'])
}
/**
* Check if the incoming request contains the "Content-Type"
* header field, and it contains any of the give mime `type`s.
* If there is no request body, `null` is returned.
* If there is no content type, `false` is returned.
* Otherwise, it returns the first `type` that matches.
*
* Examples:
*
* // With Content-Type: text/html; charset=utf-8
* this.is('html'); // => 'html'
* this.is('text/html'); // => 'text/html'
* this.is('text/*', 'application/json'); // => 'text/html'
*
* // When Content-Type is application/json
* this.is('json', 'urlencoded'); // => 'json'
* this.is('application/json'); // => 'application/json'
* this.is('html', 'application/*'); // => 'application/json'
*
* this.is('html'); // => false
*
* @param {Object} req
* @param {(String|Array)} types...
* @return {(String|false|null)}
* @public
*/
function typeofrequest (req, types_) {
// no body
if (!hasbody(req)) return null
// support flattened arguments
var types = arguments.length > 2
? Array.prototype.slice.call(arguments, 1)
: types_
// request content type
var value = req.headers['content-type']
return typeis(value, types)
}
/**
* Normalize a mime type.
* If it's a shorthand, expand it to a valid mime type.
*
* In general, you probably want:
*
* var type = is(req, ['urlencoded', 'json', 'multipart']);
*
* Then use the appropriate body parsers.
* These three are the most common request body types
* and are thus ensured to work.
*
* @param {String} type
* @return {String|false|null}
* @public
*/
function normalize (type) {
if (typeof type !== 'string') {
// invalid type
return false
}
switch (type) {
case 'urlencoded':
return 'application/x-www-form-urlencoded'
case 'multipart':
return 'multipart/*'
}
if (type[0] === '+') {
// "+json" -> "*/*+json" expando
return '*/*' + type
}
return type.indexOf('/') === -1
? mime.lookup(type)
: type
}
/**
* Check if `expected` mime type
* matches `actual` mime type with
* wildcard and +suffix support.
*
* @param {String} expected
* @param {String} actual
* @return {Boolean}
* @public
*/
function mimeMatch (expected, actual) {
// invalid type
if (expected === false) {
return false
}
// split types
var actualParts = actual.split('/')
var expectedParts = expected.split('/')
// invalid format
if (actualParts.length !== 2 || expectedParts.length !== 2) {
return false
}
// validate type
if (expectedParts[0] !== '*' && expectedParts[0] !== actualParts[0]) {
return false
}
// validate suffix wildcard
if (expectedParts[1].slice(0, 2) === '*+') {
return expectedParts[1].length <= actualParts[1].length + 1 &&
expectedParts[1].slice(1) === actualParts[1].slice(1 - expectedParts[1].length)
}
// validate subtype
if (expectedParts[1] !== '*' && expectedParts[1] !== actualParts[1]) {
return false
}
return true
}
/**
* Normalize a type and remove parameters.
*
* @param {string} value
* @return {(string|null)}
* @private
*/
function normalizeType (value) {
if (!value) return null
var type = contentType.parse(value, { parameters: false }).type
return typer.test(type) ? type : null
}
+22
View File
@@ -0,0 +1,22 @@
(The MIT License)
Copyright (c) 2015 Douglas Christopher Wilson
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+69
View File
@@ -0,0 +1,69 @@
# content-type
[![NPM version][npm-image]][npm-url]
[![NPM downloads][downloads-image]][downloads-url]
[![Build status][build-image]][build-url]
[![Build coverage][coverage-image]][coverage-url]
[![License][license-image]][license-url]
Create and parse HTTP `Content-Type` header.
## Installation
```sh
npm install content-type
```
## API
```js
const contentType = require("content-type");
```
### contentType.parse(string, options?)
```js
const obj = contentType.parse("image/svg+xml; charset=utf-8");
```
Parse a `Content-Type` header. This will return an object with the following properties (examples are shown for the string `'image/svg+xml; charset=utf-8'`):
- `type`: The media type. Example: `'image/svg+xml'`.
- `parameters`: An object of the parameters in the media type (parameter name is always lower case). Example: `{charset: 'utf-8'}`.
The parser is lenient and does not error. You should validate `type` and `parameters` before trusting them.
#### Options
- `parameters` (default: `true`): Set to `false` to skip parameters.
### contentType.format(obj)
```js
const str = contentType.format({
type: "image/svg+xml",
parameters: { charset: "utf-8" },
});
```
Format an object into a `Content-Type` header. This will return a string of the content type for the given object with the following properties (examples are shown that produce the string `'image/svg+xml; charset=utf-8'`):
- `type`: The media type. Example: `'image/svg+xml'`.
- `parameters`: An optional object of the parameters in the media type. Example: `{charset: 'utf-8'}`.
Throws a `TypeError` if the object contains an invalid type or parameter names.
## License
[MIT](LICENSE)
[npm-image]: https://img.shields.io/npm/v/content-type
[npm-url]: https://npmjs.org/package/content-type
[downloads-image]: https://img.shields.io/npm/dm/content-type
[downloads-url]: https://npmjs.org/package/content-type
[build-image]: https://img.shields.io/github/actions/workflow/status/jshttp/content-type/ci.yml?branch=master
[build-url]: https://github.com/jshttp/content-type/actions/workflows/ci.yml?query=branch%3Amaster
[coverage-image]: https://img.shields.io/codecov/c/gh/jshttp/content-type
[coverage-url]: https://codecov.io/gh/jshttp/content-type
[license-image]: http://img.shields.io/npm/l/content-type.svg?style=flat
[license-url]: LICENSE
+26
View File
@@ -0,0 +1,26 @@
/*!
* content-type
* Copyright(c) 2015 Douglas Christopher Wilson
* MIT Licensed
*/
/**
* The content type object contains a type string and optional parameters.
*/
export interface ContentType {
type: string;
parameters: Record<string, string>;
}
/**
* Format an object into a `Content-Type` header.
*/
export declare function format(obj: Partial<ContentType>): string;
/**
* Options for parsing a `Content-Type` header.
*/
export interface ParseOptions {
parameters?: boolean;
}
/**
* Parse a `Content-Type` header.
*/
export declare function parse(header: string, options?: ParseOptions): ContentType;
+170
View File
@@ -0,0 +1,170 @@
"use strict";
/*!
* content-type
* Copyright(c) 2015 Douglas Christopher Wilson
* MIT Licensed
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.format = format;
exports.parse = parse;
const TEXT_REGEXP = /^[\u0009\u0020-\u007e\u0080-\u00ff]*$/;
const TOKEN_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
/**
* RegExp to match chars that must be quoted-pair in RFC 9110 sec 5.6.4
*/
const QUOTE_REGEXP = /[\\"]/g;
/**
* RegExp to match type in RFC 9110 sec 8.3.1
*
* media-type = type "/" subtype
* type = token
* subtype = token
*/
const TYPE_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+\/[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
/**
* Null object perf optimization. Faster than `Object.create(null)` and `{ __proto__: null }`.
*/
const NullObject = /* @__PURE__ */ (() => {
const C = function () { };
C.prototype = Object.create(null);
return C;
})();
/**
* Format an object into a `Content-Type` header.
*/
function format(obj) {
const { type, parameters } = obj;
if (!type || !TYPE_REGEXP.test(type)) {
throw new TypeError(`Invalid type: ${type}`);
}
let result = type;
if (parameters) {
for (const param of Object.keys(parameters)) {
if (!TOKEN_REGEXP.test(param)) {
throw new TypeError(`Invalid parameter name: ${param}`);
}
result += `; ${param}=${qstring(parameters[param])}`;
}
}
return result;
}
/**
* Parse a `Content-Type` header.
*/
function parse(header, options) {
const len = header.length;
let index = skipOWS(header, 0, len);
const valueStart = index;
index = skipValue(header, index, len);
const valueEnd = trailingOWS(header, valueStart, index);
const type = header.slice(valueStart, valueEnd).toLowerCase();
const parameters = options?.parameters === false
? new NullObject()
: parseParameters(header, index, len);
return { type, parameters };
}
const SP = 32; // " "
const HTAB = 9; // "\t"
const SEMI = 59; // ";"
const EQ = 61; // "="
const DQUOTE = 34; // '"'
const BSLASH = 92; // "\\"
/**
* Parses the parameters of a `Content-Type` header starting at the given index.
*/
function parseParameters(header, index, len) {
const parameters = new NullObject();
parameter: while (index < len) {
index = skipOWS(header, index + 1 /* Skip over ; */, len);
const keyStart = index;
while (index < len) {
const code = header.charCodeAt(index);
if (code === SEMI)
continue parameter;
if (code === EQ) {
const keyEnd = trailingOWS(header, keyStart, index);
const key = header.slice(keyStart, keyEnd).toLowerCase();
index = skipOWS(header, index + 1, len);
if (index < len && header.charCodeAt(index) === DQUOTE) {
index++;
let value = "";
while (index < len) {
const code = header.charCodeAt(index++);
if (code === DQUOTE) {
index = skipValue(header, index, len);
if (parameters[key] === undefined)
parameters[key] = value;
break;
}
if (code === BSLASH && index < len) {
value += header[index++];
continue;
}
value += String.fromCharCode(code);
}
continue parameter;
}
const valueStart = index;
index = skipValue(header, index, len);
if (parameters[key] === undefined) {
const valueEnd = trailingOWS(header, valueStart, index);
parameters[key] = header.slice(valueStart, valueEnd);
}
continue parameter;
}
index++;
}
}
return parameters;
}
/**
* Skip over characters until a semicolon.
*/
function skipValue(str, index, len) {
while (index < len) {
const char = str.charCodeAt(index);
if (char === SEMI)
break;
index++;
}
return index;
}
/**
* Skip optional whitespace (OWS) in an HTTP header value.
*
* OWS is defined in RFC 9110 sec 5.6.3 as SP (" ") or HTAB ("\t").
*/
function skipOWS(header, index, len) {
while (index < len) {
const char = header.charCodeAt(index);
if (char !== SP && char !== HTAB)
break;
index++;
}
return index;
}
/**
* Trim optional whitespace (OWS) from the end of a substring.
*
* OWS is defined in RFC 9110 sec 5.6.3 as SP (" ") or HTAB ("\t").
*/
function trailingOWS(header, start, end) {
while (end > start) {
const char = header.charCodeAt(end - 1);
if (char !== SP && char !== HTAB)
break;
end--;
}
return end;
}
/**
* Serialize a parameter value.
*/
function qstring(str) {
if (TOKEN_REGEXP.test(str))
return str;
if (TEXT_REGEXP.test(str))
return `"${str.replace(QUOTE_REGEXP, "\\$&")}"`;
throw new TypeError(`Invalid parameter value: ${str}`);
}
//# sourceMappingURL=index.js.map
File diff suppressed because one or more lines are too long
+52
View File
@@ -0,0 +1,52 @@
{
"name": "content-type",
"version": "2.0.0",
"description": "Create and parse HTTP Content-Type header",
"keywords": [
"content-type",
"http",
"req",
"res",
"rfc7231",
"rfc9110"
],
"repository": "jshttp/content-type",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
},
"license": "MIT",
"author": "Douglas Christopher Wilson <doug@somethingdoug.com>",
"type": "commonjs",
"exports": "./dist/index.js",
"main": "./dist/index.js",
"typings": "./dist/index.d.ts",
"files": [
"dist/"
],
"scripts": {
"bench": "vitest bench",
"build": "ts-scripts build",
"format": "ts-scripts format",
"prepare": "ts-scripts install && npm run build",
"specs": "ts-scripts specs",
"test": "ts-scripts test"
},
"devDependencies": {
"@borderless/ts-scripts": "^0.15.0",
"@vitest/coverage-v8": "^3.0.5",
"typescript": "^5.7.3",
"vitest": "^3.2.4"
},
"engines": {
"node": ">=18"
},
"ts-scripts": {
"dist": [
"dist"
],
"project": [
"tsconfig.build.json"
]
}
}
+51
View File
@@ -0,0 +1,51 @@
{
"name": "type-is",
"description": "Infer the content-type of a request.",
"version": "2.1.0",
"contributors": [
"Douglas Christopher Wilson <doug@somethingdoug.com>",
"Jonathan Ong <me@jongleberry.com> (http://jongleberry.com)"
],
"license": "MIT",
"repository": "jshttp/type-is",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
},
"dependencies": {
"content-type": "^2.0.0",
"media-typer": "^1.1.0",
"mime-types": "^3.0.0"
},
"devDependencies": {
"eslint": "7.32.0",
"eslint-config-standard": "14.1.1",
"eslint-plugin-import": "2.31.0",
"eslint-plugin-markdown": "2.2.1",
"eslint-plugin-node": "11.1.0",
"eslint-plugin-promise": "5.2.0",
"eslint-plugin-standard": "4.1.0",
"mocha": "9.2.2",
"nyc": "15.1.0"
},
"engines": {
"node": ">= 18"
},
"files": [
"LICENSE",
"HISTORY.md",
"index.js"
],
"scripts": {
"lint": "eslint .",
"test": "mocha --reporter spec --check-leaks --bail test/",
"test:debug": "mocha --reporter spec --check-leaks --inspect --inspect-brk test/",
"test-ci": "nyc --reporter=lcovonly --reporter=text npm test",
"test-cov": "nyc --reporter=html --reporter=text npm test"
},
"keywords": [
"content",
"type",
"checking"
]
}