swc/bundler/tests/.cache/deno/15fe53182b4738291c2403d64a24e4e2dbb9f0f1.ts
강동윤 f8aa0509ce
fix(bundler): Fix stack overflow (#2080)
swc_bundler:
 - Prevent infinite recursions. (#1963)
2021-08-15 02:37:31 +00:00

212 lines
5.0 KiB
TypeScript

// Loaded from https://deno.land/x/type_is@1.0.1/mod.ts
/*!
* Based on https://github.com/jshttp/type-is/blob/master/index.js
* Copyright(c) 2014 Jonathan Ong
* Copyright(c) 2014-2015 Douglas Christopher Wilson
* Copyright(c) 2020 Henry Zhuang
* MIT Licensed
*/
import { lookup, parse, test } from "./deps.ts";
/**
* 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} mediaType
* @param {Array} types
*/
export function is(mediaType: string, types?: string[]): boolean | string {
let i;
// remove parameters and normalize
const val = tryNormalizeType(mediaType);
// no type or invalid
if (!val) {
return false;
}
// no types, return the content type
if (!types || !types.length) {
return val;
}
let type;
for (i = 0; i < types.length; i++) {
const normalized = normalize(type = types[i]);
if (normalized && mimeMatch(normalized, val)) {
return type[0] === "+" || type.indexOf("*") !== -1 ? val : type;
}
}
// no matches
return false;
}
/**
* Check if a request's header 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}
*/
export function hasBody(header: Headers): boolean {
return header.get("transfer-encoding") !== null ||
!isNaN(parseInt(header.get("content-length") || "", 10));
}
/**
* Check if the incoming request's header 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
* typeofrequest(header, [ 'html' ]); // => 'html'
* typeofrequest(header, ['text/html' ]); // => 'text/html'
* typeofrequest(header, ['text/*', 'application/json' ]); // => 'text/html'
*
* // When Content-Type is application/json
* typeofrequest(header, [ 'json', 'urlencoded' ]); // => 'json'
* typeofrequest(header, [ 'application/json' ]); // => 'application/json'
* typeofrequest(header, [ 'html', 'application/*' ]); // => 'application/json'
*
* typeofrequest(header, [ 'html' ]); // => false
*
* @param {String|Array} types...
* @return {String|false|null}
*/
export function typeofrequest(
header: Headers,
types_?: string[],
): null | boolean | string {
const types = types_;
// no body
if (!hasBody(header)) {
return null;
}
// request content type
const value = header.get("content-type");
if (!value) {
return false;
}
return is(value, types);
}
/**
* Normalize a mime type.
* If it's a shorthand, expand it to a valid mime type.
*
* In general, you probably want:
*
* const 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
*/
export const normalize = function normalize(type: string): string | undefined {
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 ? 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}
*/
function mimeMatch(expected: string, actual: string): boolean {
// split types
const actualParts = actual.split("/");
const 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].substr(0, 2) === "*+") {
return expectedParts[1].length <= actualParts[1].length + 1 &&
expectedParts[1].substr(1) ===
actualParts[1].substr(1 - expectedParts[1].length);
}
// validate subtype
if (expectedParts[1] !== "*" && expectedParts[1] !== actualParts[1]) {
return false;
}
return true;
}
/**
* Normalize a type
*
* @param {string} value
* @return {string}
*/
function normalizeType(value: string): string | null {
// parse the type
const type = parse(value).type;
if (!test(type)) {
return null;
}
return type;
}
/**
* Try to normalize a type
*
* @param {string} value
* @return {string}
*/
function tryNormalizeType(value: string): string | null {
try {
return normalizeType(value);
} catch (err) {
return null;
}
}