Skip to content

Commit 169b15d

Browse files
committed
feat(content_range): add checking format of content-range header
1 parent 068dd87 commit 169b15d

File tree

3 files changed

+69
-6
lines changed

3 files changed

+69
-6
lines changed

content_range.ts

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
// TODO:(miyauci) Packaging and externalization this module.
55

6-
import { isNumber } from "./deps.ts";
6+
import { isNonNegativeInteger, isNumber } from "./deps.ts";
77

88
export interface ContentRange {
99
readonly rangeUnit: string;
@@ -25,7 +25,10 @@ export interface UnsatisfiedRange {
2525
readonly completeLength: number;
2626
}
2727

28-
/** Deserialize {@link ContentRange} into string. */
28+
/** Deserialize {@link ContentRange} into string.
29+
*
30+
* @throws {TypeError} If the {@link ContentRange} is invalid.
31+
*/
2932
export function stringify(contentRange: ContentRange): string {
3033
const fmt = isRangeResp(contentRange.range)
3134
? stringifyRangeResp(contentRange.range)
@@ -45,19 +48,61 @@ function stringifyRangeResp(rangeResp: RangeResp): string {
4548
function stringifyInclRange(inclRange: InclRange): string {
4649
const { firstPos, lastPos } = inclRange;
4750

51+
assertNonNegativeInteger(
52+
firstPos,
53+
Msg.InvalidNonNegativeInt(ABNF.FirstPos, firstPos),
54+
);
55+
56+
assertNonNegativeInteger(
57+
lastPos,
58+
Msg.InvalidNonNegativeInt(ABNF.LastPos, lastPos),
59+
);
60+
4861
return `${firstPos}-${lastPos}`;
4962
}
5063

5164
function stringifyContentLength(completeLength: number | undefined): string {
52-
const length = isNumber(completeLength) ? completeLength : "*";
65+
if (!isNumber(completeLength)) return "*";
66+
67+
assertNonNegativeInteger(
68+
completeLength,
69+
Msg.InvalidNonNegativeInt(ABNF.CompleteLength, completeLength),
70+
);
5371

54-
return length.toString();
72+
return completeLength.toString();
5573
}
5674

5775
function stringifyUnsatisfiedRange(unsatisfiedRange: UnsatisfiedRange): string {
58-
return `*/${unsatisfiedRange.completeLength}`;
76+
const { completeLength } = unsatisfiedRange;
77+
78+
assertNonNegativeInteger(
79+
completeLength,
80+
Msg.InvalidNonNegativeInt(ABNF.CompleteLength, completeLength),
81+
);
82+
83+
return `*/${completeLength}`;
5984
}
6085

6186
function isRangeResp(rangeLike: RangeLike): rangeLike is RangeResp {
6287
return "firstPos" in rangeLike;
6388
}
89+
90+
const enum ABNF {
91+
CompleteLength = "<complete-length>",
92+
FirstPos = "<first-pos>",
93+
LastPos = "<last-pos>",
94+
}
95+
96+
const Msg = {
97+
InvalidNonNegativeInt: (subject: string, actual: unknown) =>
98+
`${subject} is not non-negative integer. ${actual}`,
99+
};
100+
101+
function assertNonNegativeInteger(
102+
input: number,
103+
msg?: string,
104+
): asserts input {
105+
if (!isNonNegativeInteger(input)) {
106+
throw TypeError(msg);
107+
}
108+
}

content_range_test.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { type ContentRange, stringify } from "./content_range.ts";
2-
import { assertEquals, describe, it } from "./_dev_deps.ts";
2+
import { assertEquals, assertThrows, describe, it } from "./_dev_deps.ts";
33

44
describe("stringify", () => {
55
it("should return deserialized string if the content rage is valid", () => {
@@ -22,4 +22,21 @@ describe("stringify", () => {
2222
assertEquals(stringify(contentRange), expected);
2323
});
2424
});
25+
26+
it("should throw error", () => {
27+
const table: ContentRange[] = [
28+
{
29+
rangeUnit: "a",
30+
range: { firstPos: NaN, lastPos: NaN, completeLength: NaN },
31+
},
32+
{
33+
rangeUnit: "a",
34+
range: { firstPos: 0, lastPos: 1, completeLength: -1 },
35+
},
36+
];
37+
38+
table.forEach((contentRange) => {
39+
assertThrows(() => stringify(contentRange));
40+
});
41+
});
2542
});

deps.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
export { Status } from "https://deno.land/[email protected]/http/http_status.ts";
55
export {
6+
isNonNegativeInteger,
67
isNull,
78
isNumber,
89
isString,

0 commit comments

Comments
 (0)