mirror of
https://github.com/denoland/deno.git
synced 2024-12-25 00:29:09 -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;
|
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:
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue