Blame


1 94eeacc5 2023-12-21 op // This is free and unencumbered software released into the public domain.
2 94eeacc5 2023-12-21 op //
3 94eeacc5 2023-12-21 op // Anyone is free to copy, modify, publish, use, compile, sell, or
4 94eeacc5 2023-12-21 op // distribute this software, either in source code form or as a compiled
5 94eeacc5 2023-12-21 op // binary, for any purpose, commercial or non-commercial, and by any
6 94eeacc5 2023-12-21 op // means.
7 94eeacc5 2023-12-21 op //
8 94eeacc5 2023-12-21 op // In jurisdictions that recognize copyright laws, the author or authors
9 94eeacc5 2023-12-21 op // of this software dedicate any and all copyright interest in the
10 94eeacc5 2023-12-21 op // software to the public domain. We make this dedication for the benefit
11 94eeacc5 2023-12-21 op // of the public at large and to the detriment of our heirs and
12 94eeacc5 2023-12-21 op // successors. We intend this dedication to be an overt act of
13 94eeacc5 2023-12-21 op // relinquishment in perpetuity of all present and future rights to this
14 94eeacc5 2023-12-21 op // software under copyright law.
15 94eeacc5 2023-12-21 op //
16 94eeacc5 2023-12-21 op // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 94eeacc5 2023-12-21 op // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 94eeacc5 2023-12-21 op // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 94eeacc5 2023-12-21 op // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 94eeacc5 2023-12-21 op // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 94eeacc5 2023-12-21 op // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 94eeacc5 2023-12-21 op // OTHER DEALINGS IN THE SOFTWARE.
23 94eeacc5 2023-12-21 op
24 94eeacc5 2023-12-21 op use fmt;
25 94eeacc5 2023-12-21 op use io;
26 94eeacc5 2023-12-21 op use log;
27 94eeacc5 2023-12-21 op
28 94eeacc5 2023-12-21 op export type reswriter = struct {
29 94eeacc5 2023-12-21 op vtable: io::stream,
30 5b302645 2023-12-21 op dst: dynstream,
31 158720aa 2023-12-22 op code: int,
32 94eeacc5 2023-12-21 op hdrdone: bool, // done with the headers
33 94eeacc5 2023-12-21 op done: bool, // done with the response
34 94eeacc5 2023-12-21 op wrotedone: bool, // written the done chunk
35 94eeacc5 2023-12-21 op chunked: bool, // chunk the reply
36 94eeacc5 2023-12-21 op };
37 94eeacc5 2023-12-21 op
38 94eeacc5 2023-12-21 op const reswriter_vtable: io::vtable = io::vtable {
39 94eeacc5 2023-12-21 op writer = &reswriter_write,
40 94eeacc5 2023-12-21 op closer = &reswriter_close,
41 94eeacc5 2023-12-21 op ...
42 94eeacc5 2023-12-21 op };
43 94eeacc5 2023-12-21 op
44 94eeacc5 2023-12-21 op fn new_reswriter(s: io::handle) reswriter = {
45 5b302645 2023-12-21 op return reswriter {
46 94eeacc5 2023-12-21 op vtable = &reswriter_vtable,
47 5b302645 2023-12-21 op dst = new_dynstream(s),
48 94eeacc5 2023-12-21 op ...
49 94eeacc5 2023-12-21 op };
50 94eeacc5 2023-12-21 op };
51 94eeacc5 2023-12-21 op
52 94eeacc5 2023-12-21 op fn reswriter_write(s: *io::stream, buf: const []u8) (size | io::error) = {
53 94eeacc5 2023-12-21 op let res = s: *reswriter;
54 94eeacc5 2023-12-21 op
55 94eeacc5 2023-12-21 op if (!res.hdrdone) {
56 94eeacc5 2023-12-21 op if (res.chunked) {
57 94eeacc5 2023-12-21 op header(res, "Transfer-Encoding", "chunked")?;
58 94eeacc5 2023-12-21 op };
59 94eeacc5 2023-12-21 op header(res, "Connection", "closed")?;
60 94eeacc5 2023-12-21 op
61 94eeacc5 2023-12-21 op fmt::fprint(&res.dst, "\r\n")?;
62 94eeacc5 2023-12-21 op res.hdrdone = true;
63 94eeacc5 2023-12-21 op };
64 94eeacc5 2023-12-21 op
65 94eeacc5 2023-12-21 op if (res.chunked) {
66 668cb435 2023-12-22 op fmt::fprintf(&res.dst, "{:x}\r\n", len(buf))?;
67 668cb435 2023-12-22 op io::write(&res.dst, buf)?;
68 668cb435 2023-12-22 op fmt::fprint(&res.dst, "\r\n")?;
69 668cb435 2023-12-22 op return len(buf);
70 94eeacc5 2023-12-21 op } else {
71 94eeacc5 2023-12-21 op return io::write(&res.dst, buf)?;
72 94eeacc5 2023-12-21 op };
73 94eeacc5 2023-12-21 op };
74 94eeacc5 2023-12-21 op
75 94eeacc5 2023-12-21 op fn reswriter_flush(res: *reswriter) (void | io::error) = {
76 f27a90cb 2023-12-22 op if (res.chunked && res.done && !res.wrotedone) {
77 94eeacc5 2023-12-21 op fmt::fprint(&res.dst, "0\r\n\r\n")?;
78 94eeacc5 2023-12-21 op res.wrotedone = true;
79 94eeacc5 2023-12-21 op };
80 5b302645 2023-12-21 op dynstream_flush(&res.dst)?;
81 94eeacc5 2023-12-21 op };
82 94eeacc5 2023-12-21 op
83 94eeacc5 2023-12-21 op fn reswriter_close(s: *io::stream) (void | io::error) = {
84 94eeacc5 2023-12-21 op let w = s: *reswriter;
85 94eeacc5 2023-12-21 op
86 94eeacc5 2023-12-21 op io::close(&w.dst)?;
87 94eeacc5 2023-12-21 op };
88 94eeacc5 2023-12-21 op
89 94eeacc5 2023-12-21 op export fn reply(
90 94eeacc5 2023-12-21 op req: *request,
91 94eeacc5 2023-12-21 op res: *reswriter,
92 94eeacc5 2023-12-21 op code: int,
93 94eeacc5 2023-12-21 op status: str
94 94eeacc5 2023-12-21 op ) (void | io::error) = {
95 94eeacc5 2023-12-21 op log::printfln("> {} {}", code, status);
96 94eeacc5 2023-12-21 op
97 158720aa 2023-12-22 op res.code = code;
98 158720aa 2023-12-22 op
99 94eeacc5 2023-12-21 op let version = if (req.version == version::HTTP_1_0)
100 94eeacc5 2023-12-21 op "HTTP/1.0" else "HTTP/1.1";
101 94eeacc5 2023-12-21 op
102 94eeacc5 2023-12-21 op fmt::fprintf(&res.dst, "{} {} {}\r\n", version, code, status)?;
103 94eeacc5 2023-12-21 op };
104 94eeacc5 2023-12-21 op
105 c4c2cf10 2023-12-21 op export fn header(
106 c4c2cf10 2023-12-21 op res: *reswriter,
107 c4c2cf10 2023-12-21 op header: str,
108 c4c2cf10 2023-12-21 op value: str
109 c4c2cf10 2023-12-21 op ) (void | io::error) = {
110 94eeacc5 2023-12-21 op fmt::fprintf(&res.dst, "{}: {}\r\n", header, value)?;
111 94eeacc5 2023-12-21 op };