v/cmd/tools/vdoc/httpserver.v

96 lines
2.6 KiB
V

module main
import io
import net
import strings
fn (mut vd VDoc) serve_html(out Output) {
cfg := vd.cfg
if out.typ == .html {
vd.render_static_html(true, out)
}
docs := vd.render(out)
dkeys := docs.keys()
if dkeys.len < 1 {
eprintln('no documentation created, the module has no `pub` functions')
exit(1)
}
def_name := docs.keys()[0]
server_url := 'http://localhost:' + cfg.server_port.str()
server := net.listen_tcp(cfg.server_port) or { panic(err) }
println('Serving docs on: $server_url')
if cfg.open_docs {
open_url(server_url)
}
content_type := match out.typ {
.html { 'text/html' }
.markdown { 'text/markdown' }
.json { 'application/json' }
else { 'text/plain' }
}
server_context := VdocHttpServerContext{
docs: docs
content_type: content_type
default_filename: def_name
}
for {
mut conn := server.accept() or {
server.close() or { }
panic(err)
}
handle_http_connection(mut conn, server_context)
conn.close() or { eprintln('error closing the connection: $err') }
}
}
struct VdocHttpServerContext {
docs map[string]string
content_type string
default_filename string
}
fn handle_http_connection(mut con net.TcpConn, ctx &VdocHttpServerContext) {
mut reader := io.new_buffered_reader(reader: io.make_reader(con))
first_line := reader.read_line() or {
send_http_response(mut con, 501, ctx.content_type, 'bad request')
return
}
request_parts := first_line.split(' ')
if request_parts.len != 3 {
send_http_response(mut con, 501, ctx.content_type, 'bad request')
return
}
urlpath := request_parts[1]
filename := if urlpath == '/' {
ctx.default_filename.trim_left('/')
} else {
urlpath.trim_left('/')
}
if ctx.docs[filename].len == 0 {
send_http_response(mut con, 404, ctx.content_type, 'file not found')
return
}
send_http_response(mut con, 200, ctx.content_type, ctx.docs[filename])
}
fn send_http_response(mut con net.TcpConn, http_code int, content_type string, html string) {
content_length := html.len.str()
shttp_code := http_code.str()
mut http_response := strings.new_builder(20000)
http_response.write('HTTP/1.1 ')
http_response.write(shttp_code)
http_response.write(' OK\r\n')
http_response.write('Server: VDoc\r\n')
http_response.write('Content-Type: ')
http_response.write(content_type)
http_response.write('\r\n')
http_response.write('Content-Length: ')
http_response.write(content_length)
http_response.write('\r\n')
http_response.write('Connection: close\r\n')
http_response.write('\r\n')
http_response.write(html)
sresponse := http_response.str()
con.write_str(sresponse) or { eprintln('error sending http response: $err') }
}