@httpland/compression-middleware 1.0.0-beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +208 -0
  3. package/esm/deps/deno.land/std@0.180.0/http/_negotiation/common.js +40 -0
  4. package/esm/deps/deno.land/std@0.180.0/http/_negotiation/encoding.js +121 -0
  5. package/esm/deps/deno.land/std@0.180.0/http/_negotiation/language.js +110 -0
  6. package/esm/deps/deno.land/std@0.180.0/http/_negotiation/media_type.js +174 -0
  7. package/esm/deps/deno.land/std@0.180.0/http/negotiation.js +36 -0
  8. package/esm/deps/deno.land/std@0.180.0/media_types/_db.js +33 -0
  9. package/esm/deps/deno.land/std@0.180.0/media_types/_util.js +122 -0
  10. package/esm/deps/deno.land/std@0.180.0/media_types/content_type.js +54 -0
  11. package/esm/deps/deno.land/std@0.180.0/media_types/extension.js +25 -0
  12. package/esm/deps/deno.land/std@0.180.0/media_types/extensions_by_type.js +30 -0
  13. package/esm/deps/deno.land/std@0.180.0/media_types/format_media_type.js +60 -0
  14. package/esm/deps/deno.land/std@0.180.0/media_types/get_charset.js +36 -0
  15. package/esm/deps/deno.land/std@0.180.0/media_types/mod.js +22 -0
  16. package/esm/deps/deno.land/std@0.180.0/media_types/parse_media_type.js +121 -0
  17. package/esm/deps/deno.land/std@0.180.0/media_types/type_by_extension.js +23 -0
  18. package/esm/deps/deno.land/std@0.180.0/media_types/vendor/mime-db.v1.52.0.js +8555 -0
  19. package/esm/deps/deno.land/x/vary@1.0.0/mod.js +108 -0
  20. package/esm/deps.js +8 -0
  21. package/esm/encoders/deflate.js +11 -0
  22. package/esm/encoders/gzip.js +11 -0
  23. package/esm/encoders/utils.js +7 -0
  24. package/esm/middleware.js +55 -0
  25. package/esm/mod.js +3 -0
  26. package/esm/package.json +3 -0
  27. package/esm/transform.js +23 -0
  28. package/esm/types.js +3 -0
  29. package/esm/utils.js +19 -0
  30. package/package.json +55 -0
  31. package/script/deps/deno.land/std@0.180.0/http/_negotiation/common.js +45 -0
  32. package/script/deps/deno.land/std@0.180.0/http/_negotiation/encoding.js +125 -0
  33. package/script/deps/deno.land/std@0.180.0/http/_negotiation/language.js +114 -0
  34. package/script/deps/deno.land/std@0.180.0/http/_negotiation/media_type.js +178 -0
  35. package/script/deps/deno.land/std@0.180.0/http/negotiation.js +42 -0
  36. package/script/deps/deno.land/std@0.180.0/media_types/_db.js +39 -0
  37. package/script/deps/deno.land/std@0.180.0/media_types/_util.js +132 -0
  38. package/script/deps/deno.land/std@0.180.0/media_types/content_type.js +58 -0
  39. package/script/deps/deno.land/std@0.180.0/media_types/extension.js +29 -0
  40. package/script/deps/deno.land/std@0.180.0/media_types/extensions_by_type.js +34 -0
  41. package/script/deps/deno.land/std@0.180.0/media_types/format_media_type.js +64 -0
  42. package/script/deps/deno.land/std@0.180.0/media_types/get_charset.js +40 -0
  43. package/script/deps/deno.land/std@0.180.0/media_types/mod.js +38 -0
  44. package/script/deps/deno.land/std@0.180.0/media_types/parse_media_type.js +125 -0
  45. package/script/deps/deno.land/std@0.180.0/media_types/type_by_extension.js +27 -0
  46. package/script/deps/deno.land/std@0.180.0/media_types/vendor/mime-db.v1.52.0.js +8557 -0
  47. package/script/deps/deno.land/x/vary@1.0.0/mod.js +113 -0
  48. package/script/deps.js +22 -0
  49. package/script/encoders/deflate.js +14 -0
  50. package/script/encoders/gzip.js +14 -0
  51. package/script/encoders/utils.js +10 -0
  52. package/script/middleware.js +61 -0
  53. package/script/mod.js +7 -0
  54. package/script/package.json +3 -0
  55. package/script/transform.js +27 -0
  56. package/script/types.js +4 -0
  57. package/script/utils.js +24 -0
  58. package/types/deps/deno.land/std@0.180.0/http/_negotiation/common.d.ts +37 -0
  59. package/types/deps/deno.land/std@0.180.0/http/_negotiation/encoding.d.ts +33 -0
  60. package/types/deps/deno.land/std@0.180.0/http/_negotiation/language.d.ts +30 -0
  61. package/types/deps/deno.land/std@0.180.0/http/_negotiation/media_type.d.ts +30 -0
  62. package/types/deps/deno.land/std@0.180.0/http/negotiation.d.ts +126 -0
  63. package/types/deps/deno.land/std@0.180.0/media_types/_db.d.ts +5 -0
  64. package/types/deps/deno.land/std@0.180.0/media_types/_util.d.ts +21 -0
  65. package/types/deps/deno.land/std@0.180.0/media_types/content_type.d.ts +38 -0
  66. package/types/deps/deno.land/std@0.180.0/media_types/extension.d.ts +17 -0
  67. package/types/deps/deno.land/std@0.180.0/media_types/extensions_by_type.d.ts +20 -0
  68. package/types/deps/deno.land/std@0.180.0/media_types/format_media_type.d.ts +16 -0
  69. package/types/deps/deno.land/std@0.180.0/media_types/get_charset.d.ts +15 -0
  70. package/types/deps/deno.land/std@0.180.0/media_types/mod.d.ts +20 -0
  71. package/types/deps/deno.land/std@0.180.0/media_types/parse_media_type.d.ts +37 -0
  72. package/types/deps/deno.land/std@0.180.0/media_types/type_by_extension.d.ts +17 -0
  73. package/types/deps/deno.land/std@0.180.0/media_types/vendor/mime-db.v1.52.0.d.ts +8518 -0
  74. package/types/deps/deno.land/x/vary@1.0.0/mod.d.ts +23 -0
  75. package/types/deps.d.ts +7 -0
  76. package/types/encoders/deflate.d.ts +3 -0
  77. package/types/encoders/gzip.d.ts +3 -0
  78. package/types/encoders/utils.d.ts +4 -0
  79. package/types/middleware.d.ts +28 -0
  80. package/types/mod.d.ts +2 -0
  81. package/types/transform.d.ts +3 -0
  82. package/types/types.d.ts +15 -0
  83. package/types/utils.d.ts +2 -0
@@ -0,0 +1,36 @@
1
+ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
2
+ /**
3
+ * Contains the functions {@linkcode accepts}, {@linkcode acceptsEncodings}, and
4
+ * {@linkcode acceptsLanguages} to provide content negotiation capabilities.
5
+ *
6
+ * @module
7
+ */
8
+ import { preferredEncodings } from "./_negotiation/encoding.js";
9
+ import { preferredLanguages } from "./_negotiation/language.js";
10
+ import { preferredMediaTypes } from "./_negotiation/media_type.js";
11
+ export function accepts(request, ...types) {
12
+ const accept = request.headers.get("accept");
13
+ return types.length
14
+ ? accept ? preferredMediaTypes(accept, types)[0] : types[0]
15
+ : accept
16
+ ? preferredMediaTypes(accept)
17
+ : ["*/*"];
18
+ }
19
+ export function acceptsEncodings(request, ...encodings) {
20
+ const acceptEncoding = request.headers.get("accept-encoding");
21
+ return encodings.length
22
+ ? acceptEncoding
23
+ ? preferredEncodings(acceptEncoding, encodings)[0]
24
+ : encodings[0]
25
+ : acceptEncoding
26
+ ? preferredEncodings(acceptEncoding)
27
+ : ["*"];
28
+ }
29
+ export function acceptsLanguages(request, ...langs) {
30
+ const acceptLanguage = request.headers.get("accept-language");
31
+ return langs.length
32
+ ? acceptLanguage ? preferredLanguages(acceptLanguage, langs)[0] : langs[0]
33
+ : acceptLanguage
34
+ ? preferredLanguages(acceptLanguage)
35
+ : ["*"];
36
+ }
@@ -0,0 +1,33 @@
1
+ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
2
+ import db from "./vendor/mime-db.v1.52.0.js";
3
+ import { extensions } from "./_util.js";
4
+ /** A map of the media type for a given extension */
5
+ export const types = new Map();
6
+ /** Internal function to populate the maps based on the Mime DB. */
7
+ (function populateMaps() {
8
+ const preference = ["nginx", "apache", undefined, "iana"];
9
+ for (const type of Object.keys(db)) {
10
+ const mime = db[type];
11
+ const exts = mime.extensions;
12
+ if (!exts || !exts.length) {
13
+ continue;
14
+ }
15
+ // @ts-ignore work around denoland/dnt#148
16
+ extensions.set(type, exts);
17
+ for (const ext of exts) {
18
+ const current = types.get(ext);
19
+ if (current) {
20
+ const from = preference.indexOf(db[current].source);
21
+ const to = preference.indexOf(mime.source);
22
+ if (current !== "application/octet-stream" &&
23
+ (from > to ||
24
+ // @ts-ignore work around denoland/dnt#148
25
+ (from === to && current.startsWith("application/")))) {
26
+ continue;
27
+ }
28
+ }
29
+ types.set(ext, type);
30
+ }
31
+ }
32
+ })();
33
+ export { db };
@@ -0,0 +1,122 @@
1
+ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
2
+ /** A map of extensions for a given media type. */
3
+ export const extensions = new Map();
4
+ export function consumeToken(v) {
5
+ const notPos = indexOf(v, isNotTokenChar);
6
+ if (notPos == -1) {
7
+ return [v, ""];
8
+ }
9
+ if (notPos == 0) {
10
+ return ["", v];
11
+ }
12
+ return [v.slice(0, notPos), v.slice(notPos)];
13
+ }
14
+ export function consumeValue(v) {
15
+ if (!v) {
16
+ return ["", v];
17
+ }
18
+ if (v[0] !== `"`) {
19
+ return consumeToken(v);
20
+ }
21
+ let value = "";
22
+ for (let i = 1; i < v.length; i++) {
23
+ const r = v[i];
24
+ if (r === `"`) {
25
+ return [value, v.slice(i + 1)];
26
+ }
27
+ if (r === "\\" && i + 1 < v.length && isTSpecial(v[i + 1])) {
28
+ value += v[i + 1];
29
+ i++;
30
+ continue;
31
+ }
32
+ if (r === "\r" || r === "\n") {
33
+ return ["", v];
34
+ }
35
+ value += v[i];
36
+ }
37
+ return ["", v];
38
+ }
39
+ export function consumeMediaParam(v) {
40
+ let rest = v.trimStart();
41
+ if (!rest.startsWith(";")) {
42
+ return ["", "", v];
43
+ }
44
+ rest = rest.slice(1);
45
+ rest = rest.trimStart();
46
+ let param;
47
+ [param, rest] = consumeToken(rest);
48
+ param = param.toLowerCase();
49
+ if (!param) {
50
+ return ["", "", v];
51
+ }
52
+ rest = rest.slice(1);
53
+ rest = rest.trimStart();
54
+ const [value, rest2] = consumeValue(rest);
55
+ if (value == "" && rest2 === rest) {
56
+ return ["", "", v];
57
+ }
58
+ rest = rest2;
59
+ return [param, value, rest];
60
+ }
61
+ export function decode2331Encoding(v) {
62
+ const sv = v.split(`'`, 3);
63
+ if (sv.length !== 3) {
64
+ return undefined;
65
+ }
66
+ const charset = sv[0].toLowerCase();
67
+ if (!charset) {
68
+ return undefined;
69
+ }
70
+ if (charset != "us-ascii" && charset != "utf-8") {
71
+ return undefined;
72
+ }
73
+ const encv = decodeURI(sv[2]);
74
+ if (!encv) {
75
+ return undefined;
76
+ }
77
+ return encv;
78
+ }
79
+ function indexOf(s, fn) {
80
+ let i = -1;
81
+ for (const v of s) {
82
+ i++;
83
+ if (fn(v)) {
84
+ return i;
85
+ }
86
+ }
87
+ return -1;
88
+ }
89
+ export function isIterator(obj) {
90
+ if (obj == null) {
91
+ return false;
92
+ }
93
+ // deno-lint-ignore no-explicit-any
94
+ return typeof obj[Symbol.iterator] === "function";
95
+ }
96
+ export function isToken(s) {
97
+ if (!s) {
98
+ return false;
99
+ }
100
+ return indexOf(s, isNotTokenChar) < 0;
101
+ }
102
+ function isNotTokenChar(r) {
103
+ return !isTokenChar(r);
104
+ }
105
+ function isTokenChar(r) {
106
+ const code = r.charCodeAt(0);
107
+ return code > 0x20 && code < 0x7f && !isTSpecial(r);
108
+ }
109
+ function isTSpecial(r) {
110
+ return `()<>@,;:\\"/[]?=`.includes(r[0]);
111
+ }
112
+ const CHAR_CODE_SPACE = " ".charCodeAt(0);
113
+ const CHAR_CODE_TILDE = "~".charCodeAt(0);
114
+ export function needsEncoding(s) {
115
+ for (const b of s) {
116
+ const charCode = b.charCodeAt(0);
117
+ if ((charCode < CHAR_CODE_SPACE || charCode > CHAR_CODE_TILDE) && b !== "\t") {
118
+ return true;
119
+ }
120
+ }
121
+ return false;
122
+ }
@@ -0,0 +1,54 @@
1
+ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
2
+ import { parseMediaType } from "./parse_media_type.js";
3
+ import { typeByExtension } from "./type_by_extension.js";
4
+ import { getCharset } from "./get_charset.js";
5
+ import { formatMediaType } from "./format_media_type.js";
6
+ /**
7
+ * Given an extension or media type, return a full `Content-Type` or
8
+ * `Content-Disposition` header value.
9
+ *
10
+ * The function will treat the `extensionOrType` as a media type when it
11
+ * contains a `/`, otherwise it will process it as an extension, with or without
12
+ * the leading `.`.
13
+ *
14
+ * Returns `undefined` if unable to resolve the media type.
15
+ *
16
+ * > Note: a side effect of `deno/x/media_types` was that you could pass a file
17
+ * > name (e.g. `file.json`) and it would return the content type. This behavior
18
+ * > is intentionally not supported here. If you want to get an extension for a
19
+ * > file name, use `extname()` from `std/path/mod.ts` to determine the
20
+ * > extension and pass it here.
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * import { contentType } from "https://deno.land/std@$STD_VERSION/media_types/content_type.ts";
25
+ *
26
+ * contentType(".json"); // `application/json; charset=UTF-8`
27
+ * contentType("text/html"); // `text/html; charset=UTF-8`
28
+ * contentType("text/html; charset=UTF-8"); // `text/html; charset=UTF-8`
29
+ * contentType("txt"); // `text/plain; charset=UTF-8`
30
+ * contentType("foo"); // undefined
31
+ * contentType("file.json"); // undefined
32
+ * ```
33
+ */
34
+ export function contentType(extensionOrType) {
35
+ try {
36
+ const [mediaType, params = {}] = extensionOrType.includes("/")
37
+ ? parseMediaType(extensionOrType)
38
+ : [typeByExtension(extensionOrType), undefined];
39
+ if (!mediaType) {
40
+ return undefined;
41
+ }
42
+ if (!("charset" in params)) {
43
+ const charset = getCharset(mediaType);
44
+ if (charset) {
45
+ params.charset = charset;
46
+ }
47
+ }
48
+ return formatMediaType(mediaType, params);
49
+ }
50
+ catch {
51
+ // just swallow returning undefined
52
+ }
53
+ return undefined;
54
+ }
@@ -0,0 +1,25 @@
1
+ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
2
+ import { extensionsByType } from "./extensions_by_type.js";
3
+ /**
4
+ * For a given media type, return the most relevant extension, or `undefined`
5
+ * if no extension can be found.
6
+ *
7
+ * Extensions are returned without a leading `.`.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * import { extension } from "https://deno.land/std@$STD_VERSION/media_types/extension.ts";
12
+ *
13
+ * extension("text/plain"); // `txt`
14
+ * extension("application/json"); // `json`
15
+ * extension("text/html; charset=UTF-8"); // `html`
16
+ * extension("application/foo"); // undefined
17
+ * ```
18
+ */
19
+ export function extension(type) {
20
+ const exts = extensionsByType(type);
21
+ if (exts) {
22
+ return exts[0];
23
+ }
24
+ return undefined;
25
+ }
@@ -0,0 +1,30 @@
1
+ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
2
+ import { parseMediaType } from "./parse_media_type.js";
3
+ import { extensions } from "./_util.js";
4
+ export { extensions };
5
+ /**
6
+ * Returns the extensions known to be associated with the media type `type`.
7
+ * The returned extensions will each begin with a leading dot, as in `.html`.
8
+ *
9
+ * When `type` has no associated extensions, the function returns `undefined`.
10
+ *
11
+ * Extensions are returned without a leading `.`.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import { extensionsByType } from "https://deno.land/std@$STD_VERSION/media_types/extensions_by_type.ts";
16
+ *
17
+ * extensionsByType("application/json"); // ["json", "map"]
18
+ * extensionsByType("text/html; charset=UTF-8"); // ["html", "htm", "shtml"]
19
+ * extensionsByType("application/foo"); // undefined
20
+ * ```
21
+ */
22
+ export function extensionsByType(type) {
23
+ try {
24
+ const [mediaType] = parseMediaType(type);
25
+ return extensions.get(mediaType);
26
+ }
27
+ catch {
28
+ // just swallow errors, returning undefined
29
+ }
30
+ }
@@ -0,0 +1,60 @@
1
+ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
2
+ import { isIterator, isToken, needsEncoding } from "./_util.js";
3
+ /** Serializes the media type and the optional parameters as a media type
4
+ * conforming to RFC 2045 and RFC 2616.
5
+ *
6
+ * The type and parameter names are written in lower-case.
7
+ *
8
+ * When any of the arguments results in a standard violation then the return
9
+ * value will be an empty string (`""`).
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * import { formatMediaType } from "https://deno.land/std@$STD_VERSION/media_types/format_media_type.ts";
14
+ *
15
+ * formatMediaType("text/plain", { charset: "UTF-8" }); // `text/plain; charset=UTF-8`
16
+ * ```
17
+ */
18
+ export function formatMediaType(type, param) {
19
+ let b = "";
20
+ const [major, sub] = type.split("/");
21
+ if (!sub) {
22
+ if (!isToken(type)) {
23
+ return "";
24
+ }
25
+ b += type.toLowerCase();
26
+ }
27
+ else {
28
+ if (!isToken(major) || !isToken(sub)) {
29
+ return "";
30
+ }
31
+ b += `${major.toLowerCase()}/${sub.toLowerCase()}`;
32
+ }
33
+ if (param) {
34
+ param = isIterator(param) ? Object.fromEntries(param) : param;
35
+ const attrs = Object.keys(param);
36
+ attrs.sort();
37
+ for (const attribute of attrs) {
38
+ if (!isToken(attribute)) {
39
+ return "";
40
+ }
41
+ const value = param[attribute];
42
+ b += `; ${attribute.toLowerCase()}`;
43
+ const needEnc = needsEncoding(value);
44
+ if (needEnc) {
45
+ b += "*";
46
+ }
47
+ b += "=";
48
+ if (needEnc) {
49
+ b += `utf-8''${encodeURIComponent(value)}`;
50
+ continue;
51
+ }
52
+ if (isToken(value)) {
53
+ b += value;
54
+ continue;
55
+ }
56
+ b += `"${value.replace(/["\\]/gi, (m) => `\\${m}`)}"`;
57
+ }
58
+ }
59
+ return b;
60
+ }
@@ -0,0 +1,36 @@
1
+ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
2
+ import { parseMediaType } from "./parse_media_type.js";
3
+ import { db } from "./_db.js";
4
+ /**
5
+ * Given a media type or header value, identify the encoding charset. If the
6
+ * charset cannot be determined, the function returns `undefined`.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { getCharset } from "https://deno.land/std@$STD_VERSION/media_types/get_charset.ts";
11
+ *
12
+ * getCharset("text/plain"); // `UTF-8`
13
+ * getCharset("application/foo"); // undefined
14
+ * getCharset("application/news-checkgroups"); // `US-ASCII`
15
+ * getCharset("application/news-checkgroups; charset=UTF-8"); // `UTF-8`
16
+ * ```
17
+ */
18
+ export function getCharset(type) {
19
+ try {
20
+ const [mediaType, params] = parseMediaType(type);
21
+ if (params && params["charset"]) {
22
+ return params["charset"];
23
+ }
24
+ const entry = db[mediaType];
25
+ if (entry && entry.charset) {
26
+ return entry.charset;
27
+ }
28
+ if (mediaType.startsWith("text/")) {
29
+ return "UTF-8";
30
+ }
31
+ }
32
+ catch {
33
+ // just swallow errors, returning undefined
34
+ }
35
+ return undefined;
36
+ }
@@ -0,0 +1,22 @@
1
+ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
2
+ // This module is browser compatible.
3
+ /** Utility functions for media types (MIME types).
4
+ *
5
+ * This API is inspired by the GoLang [`mime`](https://pkg.go.dev/mime) package
6
+ * and [jshttp/mime-types](https://github.com/jshttp/mime-types), and is
7
+ * designed to integrate and improve the APIs from
8
+ * [deno.land/x/media_types](https://deno.land/x/media_types).
9
+ *
10
+ * The `vendor` folder contains copy of the
11
+ * [jshttp/mime-db](https://github.com/jshttp/mime-types) `db.json` file along
12
+ * with its license.
13
+ *
14
+ * @module
15
+ */
16
+ export * from "./content_type.js";
17
+ export * from "./extension.js";
18
+ export * from "./extensions_by_type.js";
19
+ export * from "./format_media_type.js";
20
+ export * from "./get_charset.js";
21
+ export * from "./parse_media_type.js";
22
+ export * from "./type_by_extension.js";
@@ -0,0 +1,121 @@
1
+ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
2
+ import { consumeMediaParam, decode2331Encoding } from "./_util.js";
3
+ /**
4
+ * Parses the media type and any optional parameters, per
5
+ * [RFC 1521](https://datatracker.ietf.org/doc/html/rfc1521). Media types are
6
+ * the values in `Content-Type` and `Content-Disposition` headers. On success
7
+ * the function returns a tuple where the first element is the media type and
8
+ * the second element is the optional parameters or `undefined` if there are
9
+ * none.
10
+ *
11
+ * The function will throw if the parsed value is invalid.
12
+ *
13
+ * The returned media type will be normalized to be lower case, and returned
14
+ * params keys will be normalized to lower case, but preserves the casing of
15
+ * the value.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * import { parseMediaType } from "https://deno.land/std@$STD_VERSION/media_types/parse_media_type.ts";
20
+ * import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
21
+ *
22
+ * assertEquals(
23
+ * parseMediaType("application/JSON"),
24
+ * [
25
+ * "application/json",
26
+ * undefined
27
+ * ]
28
+ * );
29
+ *
30
+ * assertEquals(
31
+ * parseMediaType("text/html; charset=UTF-8"),
32
+ * [
33
+ * "application/json",
34
+ * { charset: "UTF-8" },
35
+ * ]
36
+ * );
37
+ * ```
38
+ */
39
+ export function parseMediaType(v) {
40
+ const [base] = v.split(";");
41
+ const mediaType = base.toLowerCase().trim();
42
+ const params = {};
43
+ // Map of base parameter name -> parameter name -> value
44
+ // for parameters containing a '*' character.
45
+ const continuation = new Map();
46
+ v = v.slice(base.length);
47
+ while (v.length) {
48
+ v = v.trimStart();
49
+ if (v.length === 0) {
50
+ break;
51
+ }
52
+ const [key, value, rest] = consumeMediaParam(v);
53
+ if (!key) {
54
+ if (rest.trim() === ";") {
55
+ // ignore trailing semicolons
56
+ break;
57
+ }
58
+ throw new TypeError("Invalid media parameter.");
59
+ }
60
+ let pmap = params;
61
+ const [baseName, rest2] = key.split("*");
62
+ if (baseName && rest2 != null) {
63
+ if (!continuation.has(baseName)) {
64
+ continuation.set(baseName, {});
65
+ }
66
+ pmap = continuation.get(baseName);
67
+ }
68
+ if (key in pmap) {
69
+ throw new TypeError("Duplicate key parsed.");
70
+ }
71
+ pmap[key] = value;
72
+ v = rest;
73
+ }
74
+ // Stitch together any continuations or things with stars
75
+ // (i.e. RFC 2231 things with stars: "foo*0" or "foo*")
76
+ let str = "";
77
+ for (const [key, pieceMap] of continuation) {
78
+ const singlePartKey = `${key}*`;
79
+ const v = pieceMap[singlePartKey];
80
+ if (v) {
81
+ const decv = decode2331Encoding(v);
82
+ if (decv) {
83
+ params[key] = decv;
84
+ }
85
+ continue;
86
+ }
87
+ str = "";
88
+ let valid = false;
89
+ for (let n = 0;; n++) {
90
+ const simplePart = `${key}*${n}`;
91
+ let v = pieceMap[simplePart];
92
+ if (v) {
93
+ valid = true;
94
+ str += v;
95
+ continue;
96
+ }
97
+ const encodedPart = `${simplePart}*`;
98
+ v = pieceMap[encodedPart];
99
+ if (!v) {
100
+ break;
101
+ }
102
+ valid = true;
103
+ if (n === 0) {
104
+ const decv = decode2331Encoding(v);
105
+ if (decv) {
106
+ str += decv;
107
+ }
108
+ }
109
+ else {
110
+ const decv = decodeURI(v);
111
+ str += decv;
112
+ }
113
+ }
114
+ if (valid) {
115
+ params[key] = str;
116
+ }
117
+ }
118
+ return Object.keys(params).length
119
+ ? [mediaType, params]
120
+ : [mediaType, undefined];
121
+ }
@@ -0,0 +1,23 @@
1
+ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
2
+ import { types } from "./_db.js";
3
+ /**
4
+ * Returns the media type associated with the file extension. Values are
5
+ * normalized to lower case and matched irrespective of a leading `.`.
6
+ *
7
+ * When `extension` has no associated type, the function returns `undefined`.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * import { typeByExtension } from "https://deno.land/std@$STD_VERSION/media_types/type_by_extension.ts";
12
+ *
13
+ * typeByExtension("js"); // `application/json`
14
+ * typeByExtension(".HTML"); // `text/html`
15
+ * typeByExtension("foo"); // undefined
16
+ * typeByExtension("file.json"); // undefined
17
+ * ```
18
+ */
19
+ export function typeByExtension(extension) {
20
+ extension = extension.startsWith(".") ? extension.slice(1) : extension;
21
+ // @ts-ignore workaround around denoland/dnt#148
22
+ return types.get(extension.toLowerCase());
23
+ }