2023-02-10 09:13:30 +00:00
|
|
|
use bufio;
|
|
|
|
use fmt;
|
|
|
|
use io;
|
|
|
|
use net::dial;
|
|
|
|
use net::uri;
|
|
|
|
use net;
|
|
|
|
use os;
|
|
|
|
|
|
|
|
// Performs an HTTP [[request]] with the given [[client]]. The request is
|
|
|
|
// performed synchronously; this function blocks until the server has returned
|
|
|
|
// the response status and all HTTP headers associated with the response.
|
|
|
|
export fn do(client: *client, req: *request) (response | error) = {
|
2023-02-10 09:16:18 +00:00
|
|
|
assert(req.target.scheme == "http"); // TODO: https
|
2023-02-10 09:13:30 +00:00
|
|
|
const conn = dial::dial_uri("tcp", req.target)?;
|
|
|
|
|
2023-02-10 09:34:57 +00:00
|
|
|
let buf: [os::BUFSIZ]u8 = [0...];
|
|
|
|
let file = bufio::buffered(conn, [], buf);
|
|
|
|
bufio::setflush(&file, []);
|
|
|
|
|
|
|
|
fmt::fprintf(&file, "{} ", req.method)?;
|
2023-02-10 09:13:30 +00:00
|
|
|
|
|
|
|
// TODO: Support other request-targets than origin-form
|
2023-02-10 09:47:19 +00:00
|
|
|
const target = uri_origin_form(req.target);
|
2023-02-10 09:34:57 +00:00
|
|
|
uri::fmt(&file, &target)?;
|
|
|
|
fmt::fprintf(&file, " HTTP/1.1\r\n")?;
|
2023-02-10 09:13:30 +00:00
|
|
|
|
|
|
|
// TODO: Handle Content-Length and Transfer-Encoding chunked/gzip
|
|
|
|
// properly
|
|
|
|
|
2023-02-10 09:34:57 +00:00
|
|
|
write_header(&file, &req.header)?;
|
|
|
|
fmt::fprintf(&file, "\r\n")?;
|
|
|
|
bufio::flush(&file)?;
|
2023-02-10 09:13:30 +00:00
|
|
|
|
|
|
|
match (req.body) {
|
|
|
|
case void =>
|
|
|
|
yield;
|
|
|
|
case let body: io::handle =>
|
|
|
|
// Copy to conn directly so we can use sendfile(2) if
|
|
|
|
// appropriate
|
|
|
|
io::copy(conn, body)?;
|
|
|
|
};
|
|
|
|
|
2023-02-10 09:47:19 +00:00
|
|
|
// Switch buffer to read mode
|
|
|
|
file = bufio::buffered(conn, buf, []);
|
|
|
|
|
2023-02-10 09:13:30 +00:00
|
|
|
// TODO: Parse resposne
|
|
|
|
return response {
|
|
|
|
body = conn,
|
|
|
|
...
|
|
|
|
};
|
|
|
|
};
|