Skip to content

Commit c11449f

Browse files
committed
feat(token): add http token utilities
1 parent 23abf77 commit c11449f

File tree

3 files changed

+295
-0
lines changed

3 files changed

+295
-0
lines changed

README.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,46 @@ assert(response.headers.get(header), value);
542542
assert(init !== response);
543543
```
544544

545+
## Tokens
546+
547+
Compliant with
548+
[RFC 9110, 5.6.2. Tokens](https://www.rfc-editor.org/rfc/rfc9110.html#section-5.6.2).
549+
550+
### isTchar
551+
552+
Whether the input is
553+
[tchar](https://www.rfc-editor.org/rfc/rfc9110.html#section-5.6.2-2) or not.
554+
555+
```ts
556+
import { isTchar } from "https://deno.land/x/http_utils@$VERSION/token.ts";
557+
import {
558+
assert,
559+
assertFalse,
560+
} from "https://deno.land/std@$VERSION/testing/asserts.ts";
561+
562+
assert(isTchar("!"));
563+
assert(isTchar("a"));
564+
assert(isTchar("Z"));
565+
assertFalse(isTchar(""));
566+
```
567+
568+
### isToken
569+
570+
Whether the input is
571+
[token](https://www.rfc-editor.org/rfc/rfc9110.html#section-5.6.2-2) or not.
572+
573+
```ts
574+
import { isToken } from "https://deno.land/x/http_utils@$VERSION/token.ts";
575+
import {
576+
assert,
577+
assertFalse,
578+
} from "https://deno.land/std@$VERSION/testing/asserts.ts";
579+
580+
assert(isToken("token"));
581+
assert(isTchar("*!~"));
582+
assertFalse(isToken(""));
583+
```
584+
545585
## License
546586

547587
Copyright © 2023-present [httpland](https://github.com/httpland).

token.ts

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
// Copyright 2023-latest the httpland authors. All rights reserved. MIT license.
2+
// This module is browser compatible.
3+
4+
type _Digit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
5+
type UppercaseLetter =
6+
| "A"
7+
| "B"
8+
| "C"
9+
| "D"
10+
| "E"
11+
| "F"
12+
| "G"
13+
| "H"
14+
| "I"
15+
| "J"
16+
| "K"
17+
| "L"
18+
| "M"
19+
| "N"
20+
| "O"
21+
| "P"
22+
| "Q"
23+
| "R"
24+
| "S"
25+
| "T"
26+
| "U"
27+
| "V"
28+
| "W"
29+
| "X"
30+
| "Y"
31+
| "Z";
32+
type LowercaseLetter = Lowercase<UppercaseLetter>;
33+
34+
/** Alphabet letter. */
35+
export type Alpha = UppercaseLetter | LowercaseLetter;
36+
37+
/** Digit letter. */
38+
export type Digit = `${_Digit}`;
39+
40+
/** [tchar](https://www.rfc-editor.org/rfc/rfc9110.html#section-5.6.2-2) letter. */
41+
export type Tchar =
42+
| "!"
43+
| "#"
44+
| "$"
45+
| "%"
46+
| "&"
47+
| "'"
48+
| "*"
49+
| "+"
50+
| "-"
51+
| "."
52+
| "^"
53+
| "_"
54+
| "`"
55+
| "|"
56+
| "~"
57+
| Digit
58+
| Alpha;
59+
60+
/**
61+
* ```abnf
62+
* token = 1*tchar
63+
* ```
64+
*/
65+
const reToken = /^[\w!#$%&'*+.^`|~-]+$/;
66+
67+
/** Whether the input is [token](https://www.rfc-editor.org/rfc/rfc9110.html#section-5.6.2-2) or not.
68+
*
69+
* @example
70+
* ```ts
71+
* import { isToken } from "https://deno.land/x/http_utils@$VERSION/token.ts";
72+
* import {
73+
* assert,
74+
* assertFalse,
75+
* } from "https://deno.land/std@$VERSION/testing/asserts.ts";
76+
*
77+
* assert(isToken("token"));
78+
* assert(isTchar("*!~"));
79+
* assertFalse(isToken(""));
80+
* ```
81+
*/
82+
export function isToken(input: string): boolean {
83+
return reToken.test(input);
84+
}
85+
86+
/**
87+
* ```abnf
88+
* tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*"
89+
* / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
90+
* / DIGIT / ALPHA
91+
* ; any VCHAR, except delimiters
92+
* ```
93+
*/
94+
const reTchar = /^[\w!#$%&'*+.^`|~-]$/;
95+
96+
/** Whether the input is [tchar](https://www.rfc-editor.org/rfc/rfc9110.html#section-5.6.2-2) or not.
97+
*
98+
* @example
99+
* ```ts
100+
* import { isTchar } from "https://deno.land/x/http_utils@$VERSION/token.ts";
101+
* import {
102+
* assert,
103+
* assertFalse,
104+
* } from "https://deno.land/std@$VERSION/testing/asserts.ts";
105+
*
106+
* assert(isTchar("!"));
107+
* assert(isTchar("a"));
108+
* assert(isTchar("Z"));
109+
* assertFalse(isTchar(""));
110+
* ```
111+
*/
112+
export function isTchar(input: string): input is Tchar {
113+
return reTchar.test(input);
114+
}

token_test.ts

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
import { isTchar, isToken } from "./token.ts";
2+
import { assert, assertFalse, describe, it } from "./_dev_deps.ts";
3+
4+
const table: string[] = [
5+
"!",
6+
"#",
7+
"$",
8+
"%",
9+
"&",
10+
"'",
11+
"*",
12+
"+",
13+
"-",
14+
".",
15+
"^",
16+
"_",
17+
"`",
18+
"|",
19+
"~",
20+
"0",
21+
"1",
22+
"2",
23+
"3",
24+
"4",
25+
"5",
26+
"6",
27+
"7",
28+
"8",
29+
"9",
30+
"A",
31+
"B",
32+
"C",
33+
"D",
34+
"E",
35+
"F",
36+
"G",
37+
"H",
38+
"I",
39+
"J",
40+
"K",
41+
"L",
42+
"M",
43+
"N",
44+
"O",
45+
"P",
46+
"Q",
47+
"R",
48+
"S",
49+
"T",
50+
"U",
51+
"V",
52+
"W",
53+
"X",
54+
"Y",
55+
"Z",
56+
"a",
57+
"b",
58+
"c",
59+
"d",
60+
"e",
61+
"f",
62+
"g",
63+
"h",
64+
"i",
65+
"j",
66+
"k",
67+
"l",
68+
"m",
69+
"n",
70+
"o",
71+
"p",
72+
"q",
73+
"r",
74+
"s",
75+
"t",
76+
"u",
77+
"v",
78+
"w",
79+
"x",
80+
"y",
81+
"z",
82+
];
83+
84+
describe("isTchar", () => {
85+
it("should return true", () => {
86+
table.forEach((input) => {
87+
assert(isTchar(input));
88+
});
89+
});
90+
91+
it("should return false", () => {
92+
const table: string[] = [
93+
"",
94+
"\x00",
95+
" ",
96+
`"`,
97+
"aa",
98+
"AA",
99+
"あ",
100+
];
101+
102+
table.forEach((input) => {
103+
assertFalse(isTchar(input));
104+
});
105+
});
106+
});
107+
108+
describe("isToken", () => {
109+
it("should be tchar", () => {
110+
table.forEach((input) => {
111+
assert(isToken(input));
112+
});
113+
});
114+
115+
it("should return true", () => {
116+
const table: string[] = [
117+
"aa",
118+
"abcdefghijklmnopqrstuvwxyz",
119+
"!#$%&'*+.^`|~-",
120+
"0123456789",
121+
];
122+
123+
table.forEach((input) => {
124+
assert(isToken(input));
125+
});
126+
});
127+
128+
it("should return false", () => {
129+
const table: string[] = [
130+
"",
131+
"\x00",
132+
" ",
133+
`"`,
134+
"あ",
135+
];
136+
137+
table.forEach((input) => {
138+
assertFalse(isToken(input));
139+
});
140+
});
141+
});

0 commit comments

Comments
 (0)