mirror of
https://github.com/denoland/deno.git
synced 2024-12-23 15:49:44 -05:00
http: add ParseHTTPVersion (denoland/deno_std#452)
Original: 438178541e
This commit is contained in:
parent
74498f1e0c
commit
8d94f70bef
2 changed files with 75 additions and 1 deletions
|
@ -102,6 +102,8 @@ export class ServerRequest {
|
|||
url: string;
|
||||
method: string;
|
||||
proto: string;
|
||||
protoMinor: number;
|
||||
protoMajor: number;
|
||||
headers: Headers;
|
||||
r: BufReader;
|
||||
w: BufWriter;
|
||||
|
@ -215,6 +217,45 @@ function fixLength(req: ServerRequest): void {
|
|||
}
|
||||
}
|
||||
|
||||
// ParseHTTPVersion parses a HTTP version string.
|
||||
// "HTTP/1.0" returns (1, 0, true).
|
||||
// Ported from https://github.com/golang/go/blob/f5c43b9/src/net/http/request.go#L766-L792
|
||||
export function parseHTTPVersion(vers: string): [number, number, boolean] {
|
||||
const Big = 1000000; // arbitrary upper bound
|
||||
const digitReg = /^\d+$/; // test if string is only digit
|
||||
let major: number;
|
||||
let minor: number;
|
||||
|
||||
switch (vers) {
|
||||
case "HTTP/1.1":
|
||||
return [1, 1, true];
|
||||
case "HTTP/1.0":
|
||||
return [1, 0, true];
|
||||
}
|
||||
|
||||
if (!vers.startsWith("HTTP/")) {
|
||||
return [0, 0, false];
|
||||
}
|
||||
|
||||
const dot = vers.indexOf(".");
|
||||
if (dot < 0) {
|
||||
return [0, 0, false];
|
||||
}
|
||||
|
||||
let majorStr = vers.substring(vers.indexOf("/") + 1, dot);
|
||||
major = parseInt(majorStr);
|
||||
if (!digitReg.test(majorStr) || isNaN(major) || major < 0 || major > Big) {
|
||||
return [0, 0, false];
|
||||
}
|
||||
|
||||
let minorStr = vers.substring(dot + 1);
|
||||
minor = parseInt(minorStr);
|
||||
if (!digitReg.test(minorStr) || isNaN(minor) || minor < 0 || minor > Big) {
|
||||
return [0, 0, false];
|
||||
}
|
||||
return [major, minor, true];
|
||||
}
|
||||
|
||||
export async function readRequest(
|
||||
bufr: BufReader
|
||||
): Promise<[ServerRequest, BufState]> {
|
||||
|
@ -229,6 +270,13 @@ export async function readRequest(
|
|||
return [null, err];
|
||||
}
|
||||
[req.method, req.url, req.proto] = firstLine.split(" ", 3);
|
||||
|
||||
let ok: boolean;
|
||||
[req.protoMinor, req.protoMajor, ok] = parseHTTPVersion(req.proto);
|
||||
if (!ok) {
|
||||
throw Error(`malformed HTTP version ${req.proto}`);
|
||||
}
|
||||
|
||||
[req.headers, err] = await tp.readMIMEHeader();
|
||||
fixLength(req);
|
||||
// TODO(zekth) : add parsing of headers eg:
|
||||
|
|
|
@ -12,7 +12,8 @@ import {
|
|||
Response,
|
||||
ServerRequest,
|
||||
writeResponse,
|
||||
readRequest
|
||||
readRequest,
|
||||
parseHTTPVersion
|
||||
} from "./server.ts";
|
||||
import { BufReader, BufWriter } from "../io/bufio.ts";
|
||||
import { StringReader } from "../io/readers.ts";
|
||||
|
@ -386,4 +387,29 @@ test(async function testReadRequestError(): Promise<void> {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Ported from https://github.com/golang/go/blob/f5c43b9/src/net/http/request_test.go#L535-L565
|
||||
test({
|
||||
name: "[http] parseHttpVersion",
|
||||
fn(): void {
|
||||
const testCases = [
|
||||
{ in: "HTTP/0.9", want: [0, 9, true] },
|
||||
{ in: "HTTP/1.0", want: [1, 0, true] },
|
||||
{ in: "HTTP/1.1", want: [1, 1, true] },
|
||||
{ in: "HTTP/3.14", want: [3, 14, true] },
|
||||
{ in: "HTTP", want: [0, 0, false] },
|
||||
{ in: "HTTP/one.one", want: [0, 0, false] },
|
||||
{ in: "HTTP/1.1/", want: [0, 0, false] },
|
||||
{ in: "HTTP/-1.0", want: [0, 0, false] },
|
||||
{ in: "HTTP/0.-1", want: [0, 0, false] },
|
||||
{ in: "HTTP/", want: [0, 0, false] },
|
||||
{ in: "HTTP/1,0", want: [0, 0, false] }
|
||||
];
|
||||
for (const t of testCases) {
|
||||
const r = parseHTTPVersion(t.in);
|
||||
assertEquals(r, t.want, t.in);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
runIfMain(import.meta);
|
||||
|
|
Loading…
Reference in a new issue