mirror of
https://github.com/denoland/std.git
synced 2024-11-22 04:59:05 +00:00
b8df2b3494
* fix(http): less restrictive types * tweaks --------- Co-authored-by: Asher Gomez <ashersaupingomez@gmail.com>
208 lines
6.6 KiB
TypeScript
208 lines
6.6 KiB
TypeScript
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
|
// This module is browser compatible.
|
|
|
|
/**
|
|
* 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";
|
|
|
|
/**
|
|
* Returns an array of media types accepted by the request, in order of
|
|
* preference. If there are no media types supplied in the request, then any
|
|
* media type selector will be returned.
|
|
*
|
|
* @example Usage
|
|
* ```ts
|
|
* import { accepts } from "@std/http/negotiation";
|
|
* import { assertEquals } from "@std/assert";
|
|
*
|
|
* const request = new Request("https://example.com/", {
|
|
* headers: {
|
|
* accept:
|
|
* "text/html, application/xhtml+xml, application/xml;q=0.9, image/webp, *\/*;q=0.8",
|
|
* },
|
|
* });
|
|
*
|
|
* assertEquals(accepts(request), [
|
|
* "text/html",
|
|
* "application/xhtml+xml",
|
|
* "image/webp",
|
|
* "application/xml",
|
|
* "*\/*",
|
|
* ]);
|
|
* ```
|
|
*
|
|
* @param request The request to get the acceptable media types for.
|
|
* @returns An array of acceptable media types.
|
|
*/
|
|
export function accepts(request: Pick<Request, "headers">): string[];
|
|
/**
|
|
* 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`.
|
|
*
|
|
* @example Usage
|
|
* ```ts
|
|
* import { accepts } from "@std/http/negotiation";
|
|
* import { assertEquals } from "@std/assert";
|
|
*
|
|
* const request = new Request("https://example.com/", {
|
|
* headers: {
|
|
* accept:
|
|
* "text/html, application/xhtml+xml, application/xml;q=0.9, image/webp, *\/*;q=0.8",
|
|
* },
|
|
* });
|
|
*
|
|
* assertEquals(accepts(request, "text/html", "image/webp"), "text/html");
|
|
* ```
|
|
*
|
|
* @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.
|
|
*/
|
|
export function accepts(
|
|
request: Pick<Request, "headers">,
|
|
...types: string[]
|
|
): string | undefined;
|
|
export function accepts(
|
|
request: Pick<Request, "headers">,
|
|
...types: string[]
|
|
): string | string[] | undefined {
|
|
const accept = request.headers.get("accept");
|
|
return types.length
|
|
? accept ? preferredMediaTypes(accept, types)[0] : types[0]
|
|
: accept
|
|
? preferredMediaTypes(accept)
|
|
: ["*/*"];
|
|
}
|
|
|
|
/**
|
|
* Returns an array of content encodings accepted by the request, in order of
|
|
* preference. If there are no encoding supplied in the request, then `["*"]`
|
|
* is returned, implying any encoding is accepted.
|
|
*
|
|
* @example Usage
|
|
* ```ts
|
|
* import { acceptsEncodings } from "@std/http/negotiation";
|
|
* import { assertEquals } from "@std/assert";
|
|
*
|
|
* const request = new Request("https://example.com/", {
|
|
* headers: { "accept-encoding": "deflate, gzip;q=1.0, *;q=0.5" },
|
|
* });
|
|
*
|
|
* assertEquals(acceptsEncodings(request), ["deflate", "gzip", "*"]);
|
|
* ```
|
|
*
|
|
* @param request The request to get the acceptable content encodings for.
|
|
* @returns An array of content encodings this request accepts.
|
|
*/
|
|
export function acceptsEncodings(request: Pick<Request, "headers">): string[];
|
|
/**
|
|
* For a given set of content encodings, return the best match accepted in the
|
|
* 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
|
|
* of the request.
|
|
*
|
|
* @example Usage
|
|
* ```ts
|
|
* import { acceptsEncodings } from "@std/http/negotiation";
|
|
* import { assertEquals } from "@std/assert";
|
|
*
|
|
* const request = new Request("https://example.com/", {
|
|
* headers: { "accept-encoding": "deflate, gzip;q=1.0, *;q=0.5" },
|
|
* });
|
|
*
|
|
* assertEquals(acceptsEncodings(request, "gzip", "identity"), "gzip");
|
|
* ```
|
|
*
|
|
* @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.
|
|
*/
|
|
export function acceptsEncodings(
|
|
request: Pick<Request, "headers">,
|
|
...encodings: string[]
|
|
): string | undefined;
|
|
export function acceptsEncodings(
|
|
request: Pick<Request, "headers">,
|
|
...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)
|
|
: ["*"];
|
|
}
|
|
|
|
/**
|
|
* Returns an array of languages accepted by the request, in order of
|
|
* preference. If there are no languages supplied in the request, then `["*"]`
|
|
* is returned, imply any language is accepted.
|
|
*
|
|
* @example Usage
|
|
* ```ts
|
|
* import { acceptsLanguages } from "@std/http/negotiation";
|
|
* import { assertEquals } from "@std/assert";
|
|
*
|
|
* const request = new Request("https://example.com/", {
|
|
* headers: {
|
|
* "accept-language": "fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5",
|
|
* },
|
|
* });
|
|
*
|
|
* assertEquals(acceptsLanguages(request), ["fr-CH", "fr", "en", "de", "*"]);
|
|
* ```
|
|
*
|
|
* @param request The request to get the acceptable languages for.
|
|
* @returns An array of languages this request accepts.
|
|
*/
|
|
export function acceptsLanguages(request: Pick<Request, "headers">): string[];
|
|
/**
|
|
* For a given set of languages, return the best match accepted in the request.
|
|
* If no languages match, then the function returns `undefined`.
|
|
*
|
|
* @example Usage
|
|
* ```ts
|
|
* import { acceptsLanguages } from "@std/http/negotiation";
|
|
* import { assertEquals } from "@std/assert";
|
|
*
|
|
* const request = new Request("https://example.com/", {
|
|
* headers: {
|
|
* "accept-language": "fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5",
|
|
* },
|
|
* });
|
|
*
|
|
* assertEquals(acceptsLanguages(request, "en-gb", "en-us", "en"), "en");
|
|
* ```
|
|
*
|
|
* @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.
|
|
*/
|
|
export function acceptsLanguages(
|
|
request: Pick<Request, "headers">,
|
|
...langs: string[]
|
|
): string | undefined;
|
|
export function acceptsLanguages(
|
|
request: Pick<Request, "headers">,
|
|
...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)
|
|
: ["*"];
|
|
}
|