Improve error handling
This commit is contained in:
parent
4ce86752b3
commit
6b36cfcff5
|
@ -1,5 +1,6 @@
|
|||
use bufio;
|
||||
use encoding::utf8;
|
||||
use errors;
|
||||
use fmt;
|
||||
use io;
|
||||
use net::dial;
|
||||
|
@ -43,7 +44,6 @@ export fn do(client: *client, req: *request) (response | error) = {
|
|||
yield;
|
||||
};
|
||||
|
||||
// TODO: Improve error handling
|
||||
let resp = response { ... };
|
||||
const scan = bufio::newscanner_static(conn, buf);
|
||||
read_statusline(&resp, &scan)?;
|
||||
|
@ -64,32 +64,52 @@ export fn do(client: *client, req: *request) (response | error) = {
|
|||
fn read_statusline(
|
||||
resp: *response,
|
||||
scan: *bufio::scanner,
|
||||
) (void | io::error) = {
|
||||
) (void | error) = {
|
||||
const status = match (bufio::scan_string(scan, "\r\n")) {
|
||||
case let line: const str =>
|
||||
yield line;
|
||||
case let err: io::error =>
|
||||
return err;
|
||||
case utf8::invalid =>
|
||||
abort(); // TODO
|
||||
return protoerr;
|
||||
case io::EOF =>
|
||||
abort(); // TODO
|
||||
return protoerr;
|
||||
};
|
||||
|
||||
// TODO: Error handling
|
||||
const tok = strings::tokenize(status, " ");
|
||||
const version = strings::next_token(&tok) as str;
|
||||
const status = strings::next_token(&tok) as str;
|
||||
const reason = strings::next_token(&tok) as str;
|
||||
|
||||
assert(version == "HTTP/1.1"); // TODO
|
||||
const version = match (strings::next_token(&tok)) {
|
||||
case let ver: str =>
|
||||
yield ver;
|
||||
case void =>
|
||||
return protoerr;
|
||||
};
|
||||
|
||||
const status = match (strings::next_token(&tok)) {
|
||||
case let status: str =>
|
||||
yield status;
|
||||
case void =>
|
||||
return protoerr;
|
||||
};
|
||||
|
||||
const reason = match (strings::next_token(&tok)) {
|
||||
case let reason: str =>
|
||||
yield reason;
|
||||
case void =>
|
||||
return protoerr;
|
||||
};
|
||||
|
||||
const (_, version) = strings::cut(version, "/");
|
||||
const (major, minor) = strings::cut(version, ".");
|
||||
|
||||
resp.version = (
|
||||
strconv::stou(major)!,
|
||||
strconv::stou(minor)!,
|
||||
);
|
||||
|
||||
if (resp.version.0 > 1) {
|
||||
return errors::unsupported;
|
||||
};
|
||||
|
||||
resp.status = strconv::stou(status)!;
|
||||
resp.reason = strings::dup(reason);
|
||||
};
|
||||
|
|
|
@ -4,7 +4,11 @@ use net::dial;
|
|||
// Errors possible while servicing HTTP requests. Note that these errors are for
|
||||
// errors related to the processing of the HTTP connection; semantic HTTP errors
|
||||
// such as [[STATUS_NOTFOUND]] are not handled by this type.
|
||||
export type error = !(dial::error | io::error);
|
||||
export type error = !(dial::error | io::error | protoerr);
|
||||
|
||||
// An HTTP protocol error occurred, indicating that the remote party is not
|
||||
// conformant with HTTP semantics.
|
||||
export type protoerr = void;
|
||||
|
||||
// Converts an [[error]] to a string.
|
||||
export fn strerror(err: error) const str = {
|
||||
|
@ -13,5 +17,7 @@ export fn strerror(err: error) const str = {
|
|||
return dial::strerror(err);
|
||||
case let err: io::error =>
|
||||
return io::strerror(err);
|
||||
case protoerr =>
|
||||
return "HTTP protocol error";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -64,7 +64,7 @@ export fn write_header(sink: io::handle, head: *header) (size | io::error) = {
|
|||
return z;
|
||||
};
|
||||
|
||||
fn read_header(head: *header, scan: *bufio::scanner) (void | io::error) = {
|
||||
fn read_header(head: *header, scan: *bufio::scanner) (void | error) = {
|
||||
for (true) {
|
||||
const item = match (bufio::scan_string(scan, "\r\n")) {
|
||||
case let line: const str =>
|
||||
|
@ -74,15 +74,19 @@ fn read_header(head: *header, scan: *bufio::scanner) (void | io::error) = {
|
|||
case let err: io::error =>
|
||||
return err;
|
||||
case utf8::invalid =>
|
||||
abort(); // TODO
|
||||
return protoerr;
|
||||
};
|
||||
if (item == "") {
|
||||
break;
|
||||
};
|
||||
|
||||
// TODO: validate field-name
|
||||
let (name, val) = strings::cut(item, ":");
|
||||
val = strings::trim(val);
|
||||
if (val == "") {
|
||||
return protoerr;
|
||||
};
|
||||
// TODO: validate field-name
|
||||
|
||||
header_add(head, name, val);
|
||||
};
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue