diff --git a/jsr.json b/jsr.json index 8b281419..09c22785 100644 --- a/jsr.json +++ b/jsr.json @@ -88,6 +88,7 @@ "./utils/encode": "./src/utils/encode.ts", "./utils/filepath": "./src/utils/filepath.ts", "./utils/handler": "./src/utils/handler.ts", + "./utils/headers": "./src/utils/headers.ts", "./utils/html": "./src/utils/html.ts", "./utils/http-status": "./src/utils/http-status.ts", "./utils/jwt": "./src/utils/jwt/index.ts", diff --git a/src/context.ts b/src/context.ts index b46783df..7acab14f 100644 --- a/src/context.ts +++ b/src/context.ts @@ -9,6 +9,7 @@ import type { RouterRoute, TypedResponse, } from './types' +import type { ResponseHeader } from './utils/headers' import { HtmlEscapedCallbackPhase, resolveCallback } from './utils/html' import type { RedirectStatusCode, StatusCode } from './utils/http-status' import type { BaseMime } from './utils/mime' @@ -236,77 +237,6 @@ interface SetHeadersOptions { append?: boolean } -type ResponseHeader = - | 'Access-Control-Allow-Credentials' - | 'Access-Control-Allow-Headers' - | 'Access-Control-Allow-Methods' - | 'Access-Control-Allow-Origin' - | 'Access-Control-Expose-Headers' - | 'Access-Control-Max-Age' - | 'Age' - | 'Allow' - | 'Cache-Control' - | 'Clear-Site-Data' - | 'Content-Disposition' - | 'Content-Encoding' - | 'Content-Language' - | 'Content-Length' - | 'Content-Location' - | 'Content-Range' - | 'Content-Security-Policy' - | 'Content-Security-Policy-Report-Only' - | 'Content-Type' - | 'Cookie' - | 'Cross-Origin-Embedder-Policy' - | 'Cross-Origin-Opener-Policy' - | 'Cross-Origin-Resource-Policy' - | 'Date' - | 'ETag' - | 'Expires' - | 'Last-Modified' - | 'Location' - | 'Permissions-Policy' - | 'Pragma' - | 'Retry-After' - | 'Save-Data' - | 'Sec-CH-Prefers-Color-Scheme' - | 'Sec-CH-Prefers-Reduced-Motion' - | 'Sec-CH-UA' - | 'Sec-CH-UA-Arch' - | 'Sec-CH-UA-Bitness' - | 'Sec-CH-UA-Form-Factor' - | 'Sec-CH-UA-Full-Version' - | 'Sec-CH-UA-Full-Version-List' - | 'Sec-CH-UA-Mobile' - | 'Sec-CH-UA-Model' - | 'Sec-CH-UA-Platform' - | 'Sec-CH-UA-Platform-Version' - | 'Sec-CH-UA-WoW64' - | 'Sec-Fetch-Dest' - | 'Sec-Fetch-Mode' - | 'Sec-Fetch-Site' - | 'Sec-Fetch-User' - | 'Sec-GPC' - | 'Server' - | 'Server-Timing' - | 'Service-Worker-Navigation-Preload' - | 'Set-Cookie' - | 'Strict-Transport-Security' - | 'Timing-Allow-Origin' - | 'Trailer' - | 'Transfer-Encoding' - | 'Upgrade' - | 'Vary' - | 'WWW-Authenticate' - | 'Warning' - | 'X-Content-Type-Options' - | 'X-DNS-Prefetch-Control' - | 'X-Frame-Options' - | 'X-Permitted-Cross-Domain-Policies' - | 'X-Powered-By' - | 'X-Robots-Tag' - | 'X-XSS-Protection' - interface SetHeaders { (name: 'Content-Type', value?: BaseMime, options?: SetHeadersOptions): void (name: ResponseHeader, value?: string, options?: SetHeadersOptions): void diff --git a/src/helper/accepts/accepts.ts b/src/helper/accepts/accepts.ts index f767da82..85052c3f 100644 --- a/src/helper/accepts/accepts.ts +++ b/src/helper/accepts/accepts.ts @@ -1,13 +1,5 @@ import type { Context } from '../../context' - -export type AcceptHeader = - | 'Accept' - | 'Accept-Charset' - | 'Accept-Encoding' - | 'Accept-Language' - | 'Accept-Patch' - | 'Accept-Post' - | 'Accept-Ranges' +import type { AcceptHeader } from '../../utils/headers' export interface Accept { type: string diff --git a/src/helper/cookie/index.ts b/src/helper/cookie/index.ts index f2ca99b3..a7060db3 100644 --- a/src/helper/cookie/index.ts +++ b/src/helper/cookie/index.ts @@ -93,7 +93,7 @@ export const setCookie = (c: Context, name: string, value: string, opt?: CookieO } else { cookie = serialize(name, value, { path: '/', ...opt }) } - c.header('set-cookie', cookie, { append: true }) + c.header('Set-Cookie', cookie, { append: true }) } export const setSignedCookie = async ( diff --git a/src/request.ts b/src/request.ts index ffd40fa6..63ab2a37 100644 --- a/src/request.ts +++ b/src/request.ts @@ -11,6 +11,7 @@ import type { } from './types' import { parseBody } from './utils/body' import type { BodyData, ParseBodyOptions } from './utils/body' +import type { CustomHeader, RequestHeader } from './utils/headers' import type { Simplify, UnionToIntersection } from './utils/types' import { decodeURIComponent_, getQueryParam, getQueryParams } from './utils/url' @@ -171,8 +172,9 @@ export class HonoRequest

{ * }) * ``` */ + header(name: RequestHeader): string | undefined header(name: string): string | undefined - header(): Record + header(): Record header(name?: string) { if (name) { return this.raw.headers.get(name.toLowerCase()) ?? undefined diff --git a/src/types.ts b/src/types.ts index e5b24003..09bfeb97 100644 --- a/src/types.ts +++ b/src/types.ts @@ -7,6 +7,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import type { Context } from './context' import type { Hono } from './hono' +import type { CustomHeader, RequestHeader } from './utils/headers' import type { StatusCode } from './utils/http-status' import type { IfAnyThenEmptyObject, @@ -1924,7 +1925,7 @@ export type ValidationTargets query: Record param: Record - header: Record + header: Record cookie: Record } diff --git a/src/utils/headers.ts b/src/utils/headers.ts new file mode 100644 index 00000000..dd899a8d --- /dev/null +++ b/src/utils/headers.ts @@ -0,0 +1,333 @@ +/** + * @module + * HTTP Headers utility. + */ + +// note: https://www.iana.org/assignments/http-fields/http-fields.xhtml + +export type RequestHeader = + | 'A-IM' + | 'Accept' + | 'Accept-Additions' + | 'Accept-CH' + | 'Accept-Charset' + | 'Accept-Datetime' + | 'Accept-Encoding' + | 'Accept-Features' + | 'Accept-Language' + | 'Accept-Patch' + | 'Accept-Post' + | 'Accept-Ranges' + | 'Accept-Signature' + | 'Access-Control' + | 'Access-Control-Allow-Credentials' + | 'Access-Control-Allow-Headers' + | 'Access-Control-Allow-Methods' + | 'Access-Control-Allow-Origin' + | 'Access-Control-Expose-Headers' + | 'Access-Control-Max-Age' + | 'Access-Control-Request-Headers' + | 'Access-Control-Request-Method' + | 'Age' + | 'Allow' + | 'ALPN' + | 'Alt-Svc' + | 'Alt-Used' + | 'Alternates' + | 'AMP-Cache-Transform' + | 'Apply-To-Redirect-Ref' + | 'Authentication-Control' + | 'Authentication-Info' + | 'Authorization' + | 'Available-Dictionary' + | 'C-Ext' + | 'C-Man' + | 'C-Opt' + | 'C-PEP' + | 'C-PEP-Info' + | 'Cache-Control' + | 'Cache-Status' + | 'Cal-Managed-ID' + | 'CalDAV-Timezones' + | 'Capsule-Protocol' + | 'CDN-Cache-Control' + | 'CDN-Loop' + | 'Cert-Not-After' + | 'Cert-Not-Before' + | 'Clear-Site-Data' + | 'Client-Cert' + | 'Client-Cert-Chain' + | 'Close' + | 'CMCD-Object' + | 'CMCD-Request' + | 'CMCD-Session' + | 'CMCD-Status' + | 'CMSD-Dynamic' + | 'CMSD-Static' + | 'Concealed-Auth-Export' + | 'Configuration-Context' + | 'Connection' + | 'Content-Base' + | 'Content-Digest' + | 'Content-Disposition' + | 'Content-Encoding' + | 'Content-ID' + | 'Content-Language' + | 'Content-Length' + | 'Content-Location' + | 'Content-MD5' + | 'Content-Range' + | 'Content-Script-Type' + | 'Content-Security-Policy' + | 'Content-Security-Policy-Report-Only' + | 'Content-Style-Type' + | 'Content-Type' + | 'Content-Version' + | 'Cookie' + | 'Cookie2' + | 'Cross-Origin-Embedder-Policy' + | 'Cross-Origin-Embedder-Policy-Report-Only' + | 'Cross-Origin-Opener-Policy' + | 'Cross-Origin-Opener-Policy-Report-Only' + | 'Cross-Origin-Resource-Policy' + | 'CTA-Common-Access-Token' + | 'DASL' + | 'Date' + | 'DAV' + | 'Default-Style' + | 'Delta-Base' + | 'Deprecation' + | 'Depth' + | 'Derived-From' + | 'Destination' + | 'Differential-ID' + | 'Dictionary-ID' + | 'Digest' + | 'DPoP' + | 'DPoP-Nonce' + | 'Early-Data' + | 'EDIINT-Features' + | 'ETag' + | 'Expect' + | 'Expect-CT' + | 'Expires' + | 'Ext' + | 'Forwarded' + | 'From' + | 'GetProfile' + | 'Hobareg' + | 'Host' + | 'HTTP2-Settings' + | 'If' + | 'If-Match' + | 'If-Modified-Since' + | 'If-None-Match' + | 'If-Range' + | 'If-Schedule-Tag-Match' + | 'If-Unmodified-Since' + | 'IM' + | 'Include-Referred-Token-Binding-ID' + | 'Isolation' + | 'Keep-Alive' + | 'Label' + | 'Last-Event-ID' + | 'Last-Modified' + | 'Link' + | 'Link-Template' + | 'Location' + | 'Lock-Token' + | 'Man' + | 'Max-Forwards' + | 'Memento-Datetime' + | 'Meter' + | 'Method-Check' + | 'Method-Check-Expires' + | 'MIME-Version' + | 'Negotiate' + | 'NEL' + | 'OData-EntityId' + | 'OData-Isolation' + | 'OData-MaxVersion' + | 'OData-Version' + | 'Opt' + | 'Optional-WWW-Authenticate' + | 'Ordering-Type' + | 'Origin' + | 'Origin-Agent-Cluster' + | 'OSCORE' + | 'OSLC-Core-Version' + | 'Overwrite' + | 'P3P' + | 'PEP' + | 'PEP-Info' + | 'Permissions-Policy' + | 'PICS-Label' + | 'Ping-From' + | 'Ping-To' + | 'Position' + | 'Pragma' + | 'Prefer' + | 'Preference-Applied' + | 'Priority' + | 'ProfileObject' + | 'Protocol' + | 'Protocol-Info' + | 'Protocol-Query' + | 'Protocol-Request' + | 'Proxy-Authenticate' + | 'Proxy-Authentication-Info' + | 'Proxy-Authorization' + | 'Proxy-Features' + | 'Proxy-Instruction' + | 'Proxy-Status' + | 'Public' + | 'Public-Key-Pins' + | 'Public-Key-Pins-Report-Only' + | 'Range' + | 'Redirect-Ref' + | 'Referer' + | 'Referer-Root' + | 'Referrer-Policy' + | 'Refresh' + | 'Repeatability-Client-ID' + | 'Repeatability-First-Sent' + | 'Repeatability-Request-ID' + | 'Repeatability-Result' + | 'Replay-Nonce' + | 'Reporting-Endpoints' + | 'Repr-Digest' + | 'Retry-After' + | 'Safe' + | 'Schedule-Reply' + | 'Schedule-Tag' + | 'Sec-GPC' + | 'Sec-Purpose' + | 'Sec-Token-Binding' + | 'Sec-WebSocket-Accept' + | 'Sec-WebSocket-Extensions' + | 'Sec-WebSocket-Key' + | 'Sec-WebSocket-Protocol' + | 'Sec-WebSocket-Version' + | 'Security-Scheme' + | 'Server' + | 'Server-Timing' + | 'Set-Cookie' + | 'Set-Cookie2' + | 'SetProfile' + | 'Signature' + | 'Signature-Input' + | 'SLUG' + | 'SoapAction' + | 'Status-URI' + | 'Strict-Transport-Security' + | 'Sunset' + | 'Surrogate-Capability' + | 'Surrogate-Control' + | 'TCN' + | 'TE' + | 'Timeout' + | 'Timing-Allow-Origin' + | 'Topic' + | 'Traceparent' + | 'Tracestate' + | 'Trailer' + | 'Transfer-Encoding' + | 'TTL' + | 'Upgrade' + | 'Urgency' + | 'URI' + | 'Use-As-Dictionary' + | 'User-Agent' + | 'Variant-Vary' + | 'Vary' + | 'Via' + | 'Want-Content-Digest' + | 'Want-Digest' + | 'Want-Repr-Digest' + | 'Warning' + | 'WWW-Authenticate' + | 'X-Content-Type-Options' + | 'X-Frame-Options' + +export type ResponseHeader = + | 'Access-Control-Allow-Credentials' + | 'Access-Control-Allow-Headers' + | 'Access-Control-Allow-Methods' + | 'Access-Control-Allow-Origin' + | 'Access-Control-Expose-Headers' + | 'Access-Control-Max-Age' + | 'Age' + | 'Allow' + | 'Cache-Control' + | 'Clear-Site-Data' + | 'Content-Disposition' + | 'Content-Encoding' + | 'Content-Language' + | 'Content-Length' + | 'Content-Location' + | 'Content-Range' + | 'Content-Security-Policy' + | 'Content-Security-Policy-Report-Only' + | 'Content-Type' + | 'Cookie' + | 'Cross-Origin-Embedder-Policy' + | 'Cross-Origin-Opener-Policy' + | 'Cross-Origin-Resource-Policy' + | 'Date' + | 'ETag' + | 'Expires' + | 'Last-Modified' + | 'Location' + | 'Permissions-Policy' + | 'Pragma' + | 'Retry-After' + | 'Save-Data' + | 'Sec-CH-Prefers-Color-Scheme' + | 'Sec-CH-Prefers-Reduced-Motion' + | 'Sec-CH-UA' + | 'Sec-CH-UA-Arch' + | 'Sec-CH-UA-Bitness' + | 'Sec-CH-UA-Form-Factor' + | 'Sec-CH-UA-Full-Version' + | 'Sec-CH-UA-Full-Version-List' + | 'Sec-CH-UA-Mobile' + | 'Sec-CH-UA-Model' + | 'Sec-CH-UA-Platform' + | 'Sec-CH-UA-Platform-Version' + | 'Sec-CH-UA-WoW64' + | 'Sec-Fetch-Dest' + | 'Sec-Fetch-Mode' + | 'Sec-Fetch-Site' + | 'Sec-Fetch-User' + | 'Sec-GPC' + | 'Server' + | 'Server-Timing' + | 'Service-Worker-Navigation-Preload' + | 'Set-Cookie' + | 'Strict-Transport-Security' + | 'Timing-Allow-Origin' + | 'Trailer' + | 'Transfer-Encoding' + | 'Upgrade' + | 'Vary' + | 'WWW-Authenticate' + | 'Warning' + | 'X-Content-Type-Options' + | 'X-DNS-Prefetch-Control' + | 'X-Frame-Options' + | 'X-Permitted-Cross-Domain-Policies' + | 'X-Powered-By' + | 'X-Robots-Tag' + | 'X-XSS-Protection' + +export type AcceptHeader = + | 'Accept' + | 'Accept-Charset' + | 'Accept-Encoding' + | 'Accept-Language' + | 'Accept-Patch' + | 'Accept-Post' + | 'Accept-Ranges' + +// note: `X-${string}` is deprecated +export type CustomHeader = string & {}