Outline
export function TypedHeaders(): ParameterDecorator;
Request headers decorator, type safe.
@TypedHeaders()
is a decorator function parsing request headers to a typed object. It validates the request header values through typia.assert<T>()
. If the request header values are invalid, it will throw 400 bad request exception.
It is almost same with original @Headers()
of NestJS
, but much type safe.
@TypedHeaders()
is not essential for Swagger Documents or SDK Library building.
Therefore, it is not a matter to use @TypedHeaders()
or @Headers()
of the original NestJS.
How to use
import { Controller } from "@nestjs/common";
import core from "@nestia/core";
import { IHeaders } from "@api/lib/structures/IHeaders";
@Controller("headers/:section")
export class HeadersController {
/**
* Emplace headers.
*
* @param headers Headers for authentication
* @param section Target section code
* @returns Store article
*
* @author Samchon
*/
@core.TypedRoute.Patch()
public emplace(
@core.TypedHeaders() headers: IHeaders,
@core.TypedParam("section", "string") section: string,
): void {
headers;
section;
}
}
Just call @TypedHeaders()
function on the request headers parameter, that’s all.
Nestia
will analyze your type (IHeaders
), and write optimal conversion and validation code for the target type, in the compilation level. If you click the “Compiled JavaScript File” tab of above, you can see the optimal code.
Also, as you can see from the “Compiled JavaScript File”, when upper case alphabet is used in the header key name like IHeaders["X-Descriptions"]
, @TypedHeaders()
would automatically convert to the upper case alphabet key named property from lower case key named property of raw data.
Such optimization is called AOT (Ahead of Time) compilation, and it is the secret of @TypedHeaders
Besides, the original
@Headers()
decorator ofNestJS
does not support such automatic upper case conversion. When you’ve define upper-cased property name in DTO,undefined
value always be assigned, even if you’ve sent upper-cased property in the client side.
Special Tags
You can enhance validation logic, of @TypedHeaders()
, through comment tags.
You know what? @TypedHeaders()
utilizes typia.assert<T>()
function for query data validation, and the typia.assert<T>()
function supports additional type checking logics through comment tags. For reference, “Type Tag” means a intersection type with atomic type and special tag type of typia
like number & tags.Type<"uint32">
, and “Comment Tag” means a comment starting from @
symbol following @${name} ${value}
format.
With those type and comment tags, you can add additional validation logics. If you want to add a custom validation logic, you also can do it. Read below Guide Docments of typia, and see the example code. You may understand how to utilize such type and comment tags, in a few minutes.
import typia, { tags } from "typia";
export const checkSpecialTag = typia.createIs<SpecialTag>();
interface SpecialTag {
int32: number & tags.Type<"int32">;
range?: number & tags.ExclusiveMinimum<19> & tags.Maximum<100>;
minLength: string & tags.MinLength<3>;
pattern: string & tags.Pattern<"^[a-z]+$">;
date: null | (string & tags.Format<"date">);
ip: string & (tags.Format<"ipv4"> | tags.Format<"ipv6">);
uuids: Array<string & tags.Format<"uuid">> &
tags.MinItems<3> &
tags.MaxItems<100>;
}
Restriction
When using @TypedHeaders()
, you’ve to follow such restrictions.
At first, type of @TypedHeaders()
must be a pure object type. It does not allow union type. Also, nullable types are not allowed, either. Note that, request headers type must be a sole object type without any extra definition. Of course, the word object does not contain array type.
At next, type of properties must be atomic, or array of atomic type. In the atomic type case, the atomic type allows both nullable and undefindable types. However, mixed union atomic type like string | number
or "1" | "2" | 3
are not allowed. Also, the array type does not allow both nullable and undefindable types, either.
boolean
number
bigint
string
At last, HTTP headers has special restriction on value types for specific key names. For example, Set-Cookie
must be Array type, and Authorization
must be an atomic type like string
. Therefore, @TypedHeaders()
also restricts the value type of specific key names, and it is described in below.
- Only array type allowed:
set-cookie
- Only atomic type allowed:
age
authorization
content-length
content-type
etag
expires
from
host
if-modified-since
if-unmodified-since
last-modified
location
max-forwards
proxy-authorization
referer
retry-after
server
user-agent
export interface SomeHeadersDto {
//----
// ATOMIC TYPES
//----
// ALLOWED
boolean: boolean;
number: number;
string: string;
bigint: bigint;
optional_number?: number;
nullable_string: string | null;
literal_union: "A" | "B" | "C" | "D";
// NOT ALLOWED
mixed_union: string | number | boolean;
mixed_literal: "A" | "B" | 3;
//----
// ARRAY TYPES
//----
// ALLOWED
nullable_element_array: (string | null)[];
string_array: string[];
number_array: number[];
literal_union_array: ("A" | "B" | "C")[];
literal_tuple: ["A", "B", "C"];
// NOT ALLOWED
optional_element_array: (string | undefined)[];
optional_array: string[] | undefined;
nullable_array: string[] | null;
union_atomic_array: (string | number)[];
mixed_literal_array: ("A", "B", 3)[];
mixed_tuple: ["A", "B", 3];
//----
// SPECIAL CASES
//----
// MUST BE ARRAY
"Set-Cookie": string[];
// MUST BE ATOMIC
Accept: string;
Authorization: string;
// NOT ALLOWED - MUST BE ATOMIC
referer: string[];
age: number[];
}