1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-24 08:09:08 -05:00

http: add ParseHTTPVersion (denoland/deno_std#452)

Original: 438178541e
This commit is contained in:
Vincent LE GOFF 2019-05-25 18:22:30 +02:00 committed by Ryan Dahl
parent 74498f1e0c
commit 8d94f70bef
2 changed files with 75 additions and 1 deletions

View file

@ -102,6 +102,8 @@ export class ServerRequest {
url: string; url: string;
method: string; method: string;
proto: string; proto: string;
protoMinor: number;
protoMajor: number;
headers: Headers; headers: Headers;
r: BufReader; r: BufReader;
w: BufWriter; 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( export async function readRequest(
bufr: BufReader bufr: BufReader
): Promise<[ServerRequest, BufState]> { ): Promise<[ServerRequest, BufState]> {
@ -229,6 +270,13 @@ export async function readRequest(
return [null, err]; return [null, err];
} }
[req.method, req.url, req.proto] = firstLine.split(" ", 3); [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(); [req.headers, err] = await tp.readMIMEHeader();
fixLength(req); fixLength(req);
// TODO(zekth) : add parsing of headers eg: // TODO(zekth) : add parsing of headers eg:

View file

@ -12,7 +12,8 @@ import {
Response, Response,
ServerRequest, ServerRequest,
writeResponse, writeResponse,
readRequest readRequest,
parseHTTPVersion
} from "./server.ts"; } from "./server.ts";
import { BufReader, BufWriter } from "../io/bufio.ts"; import { BufReader, BufWriter } from "../io/bufio.ts";
import { StringReader } from "../io/readers.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); runIfMain(import.meta);