1 // This is free and unencumbered software released into the public domain.
3 // Anyone is free to copy, modify, publish, use, compile, sell, or
4 // distribute this software, either in source code form or as a compiled
5 // binary, for any purpose, commercial or non-commercial, and by any
8 // In jurisdictions that recognize copyright laws, the author or authors
9 // of this software dedicate any and all copyright interest in the
10 // software to the public domain. We make this dedication for the benefit
11 // of the public at large and to the detriment of our heirs and
12 // successors. We intend this dedication to be an overt act of
13 // relinquishment in perpetuity of all present and future rights to this
14 // software under copyright law.
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 // OTHER DEALINGS IN THE SOFTWARE.
28 export type reswriter = struct {
32 hdrdone: bool, // done with the headers
33 done: bool, // done with the response
34 wrotedone: bool, // written the done chunk
35 chunked: bool, // chunk the reply
38 const reswriter_vtable: io::vtable = io::vtable {
39 writer = &reswriter_write,
40 closer = &reswriter_close,
44 fn new_reswriter(s: io::handle) reswriter = {
46 vtable = &reswriter_vtable,
47 dst = new_dynstream(s),
52 fn reswriter_write(s: *io::stream, buf: const []u8) (size | io::error) = {
53 let res = s: *reswriter;
57 header(res, "Transfer-Encoding", "chunked")?;
59 header(res, "Connection", "closed")?;
61 fmt::fprint(&res.dst, "\r\n")?;
66 fmt::fprintf(&res.dst, "{:x}\r\n", len(buf))?;
67 io::write(&res.dst, buf)?;
68 fmt::fprint(&res.dst, "\r\n")?;
71 return io::write(&res.dst, buf)?;
75 fn reswriter_flush(res: *reswriter) (void | io::error) = {
76 if (res.chunked && res.done && !res.wrotedone) {
77 fmt::fprint(&res.dst, "0\r\n\r\n")?;
80 dynstream_flush(&res.dst)?;
83 fn reswriter_close(s: *io::stream) (void | io::error) = {
84 let w = s: *reswriter;
94 ) (void | io::error) = {
95 log::printfln("> {} {}", code, status);
99 let version = if (req.version == version::HTTP_1_0)
100 "HTTP/1.0" else "HTTP/1.1";
102 fmt::fprintf(&res.dst, "{} {} {}\r\n", version, code, status)?;
109 ) (void | io::error) = {
110 fmt::fprintf(&res.dst, "{}: {}\r\n", header, value)?;