2024-01-01 21:11:32 +00:00
|
|
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
2023-03-18 12:36:00 +00:00
|
|
|
// This module is browser compatible.
|
2022-07-04 07:26:56 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Contains the functions {@linkcode accepts}, {@linkcode acceptsEncodings}, and
|
|
|
|
* {@linkcode acceptsLanguages} to provide content negotiation capabilities.
|
|
|
|
*
|
|
|
|
* @module
|
|
|
|
*/
|
|
|
|
|
|
|
|
import { preferredEncodings } from "./_negotiation/encoding.ts";
|
|
|
|
import { preferredLanguages } from "./_negotiation/language.ts";
|
|
|
|
import { preferredMediaTypes } from "./_negotiation/media_type.ts";
|
|
|
|
|
2022-11-25 11:40:23 +00:00
|
|
|
/**
|
|
|
|
* Returns an array of media types accepted by the request, in order of
|
2022-07-04 07:26:56 +00:00
|
|
|
* preference. If there are no media types supplied in the request, then any
|
2022-11-25 11:40:23 +00:00
|
|
|
* media type selector will be returned.
|
|
|
|
*
|
2024-05-22 19:09:08 +00:00
|
|
|
* @example Usage
|
2022-11-25 11:40:23 +00:00
|
|
|
* ```ts
|
2024-04-29 02:57:30 +00:00
|
|
|
* import { accepts } from "@std/http/negotiation";
|
refactor(assert,async,bytes,cli,collections,crypto,csv,data-structures,datetime,dotenv,encoding,expect,fmt,front-matter,fs,html,http,ini,internal,io,json,jsonc,log,media-types,msgpack,net,path,semver,streams,testing,text,toml,ulid,url,uuid,webgpu,yaml): import from `@std/assert` (#5199)
* refactor: import from `@std/assert`
* update
2024-06-30 08:30:10 +00:00
|
|
|
* import { assertEquals } from "@std/assert";
|
2022-11-25 11:40:23 +00:00
|
|
|
*
|
2024-06-03 04:10:27 +00:00
|
|
|
* const request = new Request("https://example.com/", {
|
2022-11-25 11:40:23 +00:00
|
|
|
* headers: {
|
2024-06-03 04:10:27 +00:00
|
|
|
* accept:
|
2022-11-25 11:40:23 +00:00
|
|
|
* "text/html, application/xhtml+xml, application/xml;q=0.9, image/webp, *\/*;q=0.8",
|
|
|
|
* },
|
|
|
|
* });
|
|
|
|
*
|
2024-06-03 04:10:27 +00:00
|
|
|
* assertEquals(accepts(request), [
|
|
|
|
* "text/html",
|
|
|
|
* "application/xhtml+xml",
|
|
|
|
* "image/webp",
|
|
|
|
* "application/xml",
|
|
|
|
* "*\/*",
|
|
|
|
* ]);
|
2022-11-25 11:40:23 +00:00
|
|
|
* ```
|
2024-05-22 19:09:08 +00:00
|
|
|
*
|
|
|
|
* @param request The request to get the acceptable media types for.
|
|
|
|
* @returns An array of acceptable media types.
|
2022-11-25 11:40:23 +00:00
|
|
|
*/
|
2024-08-29 00:09:44 +00:00
|
|
|
export function accepts(request: Pick<Request, "headers">): string[];
|
2022-11-25 11:40:23 +00:00
|
|
|
/**
|
|
|
|
* For a given set of media types, return the best match accepted in the
|
|
|
|
* request. If no media type matches, then the function returns `undefined`.
|
|
|
|
*
|
2024-05-22 19:09:08 +00:00
|
|
|
* @example Usage
|
2022-11-25 11:40:23 +00:00
|
|
|
* ```ts
|
2024-04-29 02:57:30 +00:00
|
|
|
* import { accepts } from "@std/http/negotiation";
|
refactor(assert,async,bytes,cli,collections,crypto,csv,data-structures,datetime,dotenv,encoding,expect,fmt,front-matter,fs,html,http,ini,internal,io,json,jsonc,log,media-types,msgpack,net,path,semver,streams,testing,text,toml,ulid,url,uuid,webgpu,yaml): import from `@std/assert` (#5199)
* refactor: import from `@std/assert`
* update
2024-06-30 08:30:10 +00:00
|
|
|
* import { assertEquals } from "@std/assert";
|
2022-11-25 11:40:23 +00:00
|
|
|
*
|
2024-06-03 04:10:27 +00:00
|
|
|
* const request = new Request("https://example.com/", {
|
2022-11-25 11:40:23 +00:00
|
|
|
* headers: {
|
2024-06-03 04:10:27 +00:00
|
|
|
* accept:
|
2022-11-25 11:40:23 +00:00
|
|
|
* "text/html, application/xhtml+xml, application/xml;q=0.9, image/webp, *\/*;q=0.8",
|
|
|
|
* },
|
|
|
|
* });
|
|
|
|
*
|
2024-06-03 04:10:27 +00:00
|
|
|
* assertEquals(accepts(request, "text/html", "image/webp"), "text/html");
|
2022-11-25 11:40:23 +00:00
|
|
|
* ```
|
2024-05-22 19:09:08 +00:00
|
|
|
*
|
|
|
|
* @param request The request to get the acceptable media types for.
|
|
|
|
* @param types An array of media types to find the best matching one from.
|
|
|
|
* @returns The best matching media type, if any match.
|
2022-11-25 11:40:23 +00:00
|
|
|
*/
|
2022-07-04 07:26:56 +00:00
|
|
|
export function accepts(
|
2024-08-29 00:09:44 +00:00
|
|
|
request: Pick<Request, "headers">,
|
2022-07-04 07:26:56 +00:00
|
|
|
...types: string[]
|
|
|
|
): string | undefined;
|
|
|
|
export function accepts(
|
2024-08-29 00:09:44 +00:00
|
|
|
request: Pick<Request, "headers">,
|
2022-07-04 07:26:56 +00:00
|
|
|
...types: string[]
|
|
|
|
): string | string[] | undefined {
|
|
|
|
const accept = request.headers.get("accept");
|
|
|
|
return types.length
|
|
|
|
? accept ? preferredMediaTypes(accept, types)[0] : types[0]
|
|
|
|
: accept
|
|
|
|
? preferredMediaTypes(accept)
|
|
|
|
: ["*/*"];
|
|
|
|
}
|
|
|
|
|
2022-11-25 11:40:23 +00:00
|
|
|
/**
|
|
|
|
* Returns an array of content encodings accepted by the request, in order of
|
2022-07-04 07:26:56 +00:00
|
|
|
* preference. If there are no encoding supplied in the request, then `["*"]`
|
2022-11-25 11:40:23 +00:00
|
|
|
* is returned, implying any encoding is accepted.
|
|
|
|
*
|
2024-05-22 19:09:08 +00:00
|
|
|
* @example Usage
|
2022-11-25 11:40:23 +00:00
|
|
|
* ```ts
|
2024-04-29 02:57:30 +00:00
|
|
|
* import { acceptsEncodings } from "@std/http/negotiation";
|
refactor(assert,async,bytes,cli,collections,crypto,csv,data-structures,datetime,dotenv,encoding,expect,fmt,front-matter,fs,html,http,ini,internal,io,json,jsonc,log,media-types,msgpack,net,path,semver,streams,testing,text,toml,ulid,url,uuid,webgpu,yaml): import from `@std/assert` (#5199)
* refactor: import from `@std/assert`
* update
2024-06-30 08:30:10 +00:00
|
|
|
* import { assertEquals } from "@std/assert";
|
2022-11-25 11:40:23 +00:00
|
|
|
*
|
2024-06-03 04:10:27 +00:00
|
|
|
* const request = new Request("https://example.com/", {
|
2022-11-25 11:40:23 +00:00
|
|
|
* headers: { "accept-encoding": "deflate, gzip;q=1.0, *;q=0.5" },
|
|
|
|
* });
|
|
|
|
*
|
2024-06-03 04:10:27 +00:00
|
|
|
* assertEquals(acceptsEncodings(request), ["deflate", "gzip", "*"]);
|
2022-11-25 11:40:23 +00:00
|
|
|
* ```
|
2024-05-22 19:09:08 +00:00
|
|
|
*
|
|
|
|
* @param request The request to get the acceptable content encodings for.
|
|
|
|
* @returns An array of content encodings this request accepts.
|
2022-11-25 11:40:23 +00:00
|
|
|
*/
|
2024-08-29 00:09:44 +00:00
|
|
|
export function acceptsEncodings(request: Pick<Request, "headers">): string[];
|
2022-11-25 11:40:23 +00:00
|
|
|
/**
|
|
|
|
* For a given set of content encodings, return the best match accepted in the
|
2022-07-04 07:26:56 +00:00
|
|
|
* request. If no content encodings match, then the function returns
|
|
|
|
* `undefined`.
|
|
|
|
*
|
|
|
|
* **NOTE:** You should always supply `identity` as one of the encodings
|
|
|
|
* to ensure that there is a match when the `Accept-Encoding` header is part
|
2022-11-25 11:40:23 +00:00
|
|
|
* of the request.
|
|
|
|
*
|
2024-05-22 19:09:08 +00:00
|
|
|
* @example Usage
|
2022-11-25 11:40:23 +00:00
|
|
|
* ```ts
|
2024-04-29 02:57:30 +00:00
|
|
|
* import { acceptsEncodings } from "@std/http/negotiation";
|
refactor(assert,async,bytes,cli,collections,crypto,csv,data-structures,datetime,dotenv,encoding,expect,fmt,front-matter,fs,html,http,ini,internal,io,json,jsonc,log,media-types,msgpack,net,path,semver,streams,testing,text,toml,ulid,url,uuid,webgpu,yaml): import from `@std/assert` (#5199)
* refactor: import from `@std/assert`
* update
2024-06-30 08:30:10 +00:00
|
|
|
* import { assertEquals } from "@std/assert";
|
2022-11-25 11:40:23 +00:00
|
|
|
*
|
2024-06-03 04:10:27 +00:00
|
|
|
* const request = new Request("https://example.com/", {
|
2022-11-25 11:40:23 +00:00
|
|
|
* headers: { "accept-encoding": "deflate, gzip;q=1.0, *;q=0.5" },
|
|
|
|
* });
|
|
|
|
*
|
2024-06-03 04:10:27 +00:00
|
|
|
* assertEquals(acceptsEncodings(request, "gzip", "identity"), "gzip");
|
2022-11-25 11:40:23 +00:00
|
|
|
* ```
|
2024-05-22 19:09:08 +00:00
|
|
|
*
|
|
|
|
* @param request The request to get the acceptable content encodings for.
|
|
|
|
* @param encodings An array of encodings to find the best matching one from.
|
|
|
|
* @returns The best matching encoding, if any match.
|
2022-11-25 11:40:23 +00:00
|
|
|
*/
|
2022-07-04 07:26:56 +00:00
|
|
|
export function acceptsEncodings(
|
2024-08-29 00:09:44 +00:00
|
|
|
request: Pick<Request, "headers">,
|
2022-07-04 07:26:56 +00:00
|
|
|
...encodings: string[]
|
|
|
|
): string | undefined;
|
|
|
|
export function acceptsEncodings(
|
2024-08-29 00:09:44 +00:00
|
|
|
request: Pick<Request, "headers">,
|
2022-07-04 07:26:56 +00:00
|
|
|
...encodings: string[]
|
|
|
|
): string | string[] | undefined {
|
|
|
|
const acceptEncoding = request.headers.get("accept-encoding");
|
|
|
|
return encodings.length
|
|
|
|
? acceptEncoding
|
|
|
|
? preferredEncodings(acceptEncoding, encodings)[0]
|
|
|
|
: encodings[0]
|
|
|
|
: acceptEncoding
|
|
|
|
? preferredEncodings(acceptEncoding)
|
|
|
|
: ["*"];
|
|
|
|
}
|
|
|
|
|
2022-11-25 11:40:23 +00:00
|
|
|
/**
|
|
|
|
* Returns an array of languages accepted by the request, in order of
|
2022-07-04 07:26:56 +00:00
|
|
|
* preference. If there are no languages supplied in the request, then `["*"]`
|
2022-11-25 11:40:23 +00:00
|
|
|
* is returned, imply any language is accepted.
|
|
|
|
*
|
2024-05-22 19:09:08 +00:00
|
|
|
* @example Usage
|
2022-11-25 11:40:23 +00:00
|
|
|
* ```ts
|
2024-04-29 02:57:30 +00:00
|
|
|
* import { acceptsLanguages } from "@std/http/negotiation";
|
refactor(assert,async,bytes,cli,collections,crypto,csv,data-structures,datetime,dotenv,encoding,expect,fmt,front-matter,fs,html,http,ini,internal,io,json,jsonc,log,media-types,msgpack,net,path,semver,streams,testing,text,toml,ulid,url,uuid,webgpu,yaml): import from `@std/assert` (#5199)
* refactor: import from `@std/assert`
* update
2024-06-30 08:30:10 +00:00
|
|
|
* import { assertEquals } from "@std/assert";
|
2022-11-25 11:40:23 +00:00
|
|
|
*
|
2024-06-03 04:10:27 +00:00
|
|
|
* const request = new Request("https://example.com/", {
|
2022-11-25 11:40:23 +00:00
|
|
|
* headers: {
|
|
|
|
* "accept-language": "fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5",
|
|
|
|
* },
|
|
|
|
* });
|
|
|
|
*
|
2024-06-03 04:10:27 +00:00
|
|
|
* assertEquals(acceptsLanguages(request), ["fr-CH", "fr", "en", "de", "*"]);
|
2022-11-25 11:40:23 +00:00
|
|
|
* ```
|
2024-05-22 19:09:08 +00:00
|
|
|
*
|
|
|
|
* @param request The request to get the acceptable languages for.
|
|
|
|
* @returns An array of languages this request accepts.
|
2022-11-25 11:40:23 +00:00
|
|
|
*/
|
2024-08-29 00:09:44 +00:00
|
|
|
export function acceptsLanguages(request: Pick<Request, "headers">): string[];
|
2022-11-25 11:40:23 +00:00
|
|
|
/**
|
|
|
|
* For a given set of languages, return the best match accepted in the request.
|
|
|
|
* If no languages match, then the function returns `undefined`.
|
|
|
|
*
|
2024-05-22 19:09:08 +00:00
|
|
|
* @example Usage
|
2022-11-25 11:40:23 +00:00
|
|
|
* ```ts
|
2024-04-29 02:57:30 +00:00
|
|
|
* import { acceptsLanguages } from "@std/http/negotiation";
|
refactor(assert,async,bytes,cli,collections,crypto,csv,data-structures,datetime,dotenv,encoding,expect,fmt,front-matter,fs,html,http,ini,internal,io,json,jsonc,log,media-types,msgpack,net,path,semver,streams,testing,text,toml,ulid,url,uuid,webgpu,yaml): import from `@std/assert` (#5199)
* refactor: import from `@std/assert`
* update
2024-06-30 08:30:10 +00:00
|
|
|
* import { assertEquals } from "@std/assert";
|
2022-11-25 11:40:23 +00:00
|
|
|
*
|
2024-06-03 04:10:27 +00:00
|
|
|
* const request = new Request("https://example.com/", {
|
2022-11-25 11:40:23 +00:00
|
|
|
* headers: {
|
|
|
|
* "accept-language": "fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5",
|
|
|
|
* },
|
|
|
|
* });
|
|
|
|
*
|
2024-06-03 04:10:27 +00:00
|
|
|
* assertEquals(acceptsLanguages(request, "en-gb", "en-us", "en"), "en");
|
2022-11-25 11:40:23 +00:00
|
|
|
* ```
|
2024-05-22 19:09:08 +00:00
|
|
|
*
|
|
|
|
* @param request The request to get the acceptable language for.
|
|
|
|
* @param langs An array of languages to find the best matching one from.
|
|
|
|
* @returns The best matching language, if any match.
|
2022-11-25 11:40:23 +00:00
|
|
|
*/
|
2022-07-04 07:26:56 +00:00
|
|
|
export function acceptsLanguages(
|
2024-08-29 00:09:44 +00:00
|
|
|
request: Pick<Request, "headers">,
|
2022-07-04 07:26:56 +00:00
|
|
|
...langs: string[]
|
|
|
|
): string | undefined;
|
|
|
|
export function acceptsLanguages(
|
2024-08-29 00:09:44 +00:00
|
|
|
request: Pick<Request, "headers">,
|
2022-07-04 07:26:56 +00:00
|
|
|
...langs: string[]
|
|
|
|
): string | string[] | undefined {
|
|
|
|
const acceptLanguage = request.headers.get("accept-language");
|
|
|
|
return langs.length
|
|
|
|
? acceptLanguage ? preferredLanguages(acceptLanguage, langs)[0] : langs[0]
|
|
|
|
: acceptLanguage
|
|
|
|
? preferredLanguages(acceptLanguage)
|
|
|
|
: ["*"];
|
|
|
|
}
|