CCCPaste

single-threaded 9.5ms latency

namespace eval ::userdb::http {

    proc Send {res chan} {
        # translation mode is crlf, no need to insert \r
        fileevent $chan writable {}
        fileevent $chan readable {}
        set len [string length $res]
        puts -nonewline $chan \
            "HTTP/1.0 200 OK\nContent-Type: text/plain; charset=UTF-8\nContent-Length: $len\n\n"
        puts -nonewline $chan $res
        catch {chan close $chan}
    }

    proc BadRequest {chan} {
        puts $chan "HTTP/1.0 400 Bad Request\n\n"
        catch {chan close $chan}
    }

    proc Read {ctx lines chan} {
        if {[gets $chan line] >= 0} {
            if {$line eq ""} {
                # End of Full-Request. Ignore everything after Request-Line
                foreach {method path rest} [split [lindex $lines 0]] {
                    switch $method {
                        GET {
                            set res [[dict get $ctx GET] $ctx $path]
                            fileevent $chan writable [list [namespace current]::Send $res $chan]
                        }
                        default {
                            fileevent $chan writable [list [namespace current]::BadRequest $chan]
                        }
                    }
                }
            }

            # Replace handler with new state
            fileevent $chan readable [list [namespace current]::Read $ctx [lappend lines $line] $chan]
        }

        if {[eof $chan]} {
            close $chan
        }
    }

    proc Server {ctx chan clientaddr clientport} {
        chan configure $chan -blocking 0 -buffering line -translation crlf -encoding utf-8
        fileevent $chan readable [list [namespace current]::Read $ctx {} $chan]
    }

    proc HandleGet {ctx path} {
        return "hello, world."
    }

    proc serve {} {
        set ctx [dict create GET [namespace current]::HandleGet]

        puts "Listening on http://127.0.0.1:8112"
        socket -server [list [namespace current]::Server $ctx] -myaddr 127.0.0.1 8112
        vwait forever
    }
}