HTTP

Constant HTTP 

Source
pub const HTTP: &str = "\"stream.spl\" import\n\"net.spl\" import\n\n\"http\" net:register\n\nconstruct net:http namespace {\n    Request\n    Response\n    help\n    ;\n    register { | with name this ;\n        name \"net:http\" register-field\n    }\n    urlencode { str | with str this ;\n        [ { | with x ;\n            x\n            x \"0\" :_char lt not\n            x \"9\" :_char gt not and\n            x \"a\" :_char lt not\n            x \"z\" :_char gt not and or\n            x \"A\" :_char lt not\n            x \"Z\" :_char gt not and or\n            not\n            if {\n                pop\n                \"%\" :_char\n                x _mega:_str_radix<16> _array =x\n                x:len 1 eq if { \"0\" :_char }\n                x:to-stack\n            } \n        } str _array :foreach ] _str\n    }\n    urldecode { str | with str this ;\n        str _array =str\n        [ \n            def i 0 =i\n            while { i str:len lt } {\n                i str:get dup \"%\" :_char eq if {\n                    pop\n                    i ++ =i\n                    i i 2 + str:sub _str :_mega_radix<16> _int\n                    i ++ =i\n                }\n                i ++ =i\n            }\n        ] _str\n    }\n}\n\nconstruct net:http:Request {\n    host port\n    method path\n    headers\n    body\n    ;\n    construct { this | with host port method path this ;\n        host this:=host\n        port this:=port\n        method this:=method\n        path this:=path\n        List:new this:=headers\n        \"\" this:=body\n        this\n    }\n    add-header { this | with header this ;\n        header this:headers:push\n        this\n    }\n    set-body { this | with body this ;\n        body this:=body\n        this\n    }\n    send { net:http:Response | with this ;\n        def stream this:host this:port StreamTypes:tcp:create =stream\n        def response net:http:Response:new =response\n\n        this:method:to-bytes stream:write-exact;\n        \" \" :to-bytes stream:write-exact;\n        this:path:to-bytes stream:write-exact;\n        \" HTTP/1.0\\r\\n\" :to-bytes stream:write-exact;\n\n        \"Host: \" :to-bytes stream:write-exact;\n        this:host:to-bytes stream:write-exact;\n        \"\\r\\nConnection: Close\\r\\nUser-Agent: http.spl v0.1 2023-03 (spl@mail.tudbut.de)\\r\\n\"\n            :to-bytes stream:write-exact;\n\n        { | with header ;\n            header:to-bytes stream:write-exact;\n            \"\\r\\n\" stream:write-exact;\n        } this:headers:foreach\n\n        \"Content-Length: \" :to-bytes stream:write-exact;\n        def body this:body:to-bytes =body\n        body:len _str:to-bytes stream:write-exact;\n        \"\\r\\n\\r\\n\" :to-bytes stream:write-exact;\n        \n        body stream:write-exact;\n        stream:flush;\n\n        def response 1024 stream:read-to-end =response\n\n        response net:http:Response:new:read-from-bytes\n\n        stream:close;\n    }\n}\n\nconstruct net:http:help namespace {\n    ;\n    assert-str { | with expected iter _ ;\n            [ { | pop iter:next } (expected _array):len:foreach ] _str\n            expected _str\n        eq not if {\n            \"Expected \" expected concat throw\n        }\n    }\n    until-str { str | with expected iter _ ;\n        def match 0 =match\n        def bytes expected:to-bytes =bytes\n        [\n            while { match bytes:len eq not } {\n                iter:next dup (match bytes:get) eq dup if {\n                    match ++ =match\n                } not if {\n                    0 =match\n                }\n            } \n            { | pop pop } match:foreach\n        ] _str\n    }\n}\n\nconstruct net:http:Response {\n    version\n    state-num state-msg\n    headers\n    body\n    ;\n    construct { this | with this ;\n        MicroMap:new this:=headers\n        \"\" this:=body\n        this\n    }\n    read-from-bytes { this | with bytes this ;\n        use net:http:help\n        bytes:iter =bytes\n        \"HTTP/\" bytes help:assert-str\n        \" \" bytes help:until-str this:=version\n        \" \" bytes help:until-str _mega this:=state-num\n        \"\\r\\n\" bytes help:until-str this:=state-msg\n        while { \"\\r\\n\" bytes help:until-str dup \"\" eq not } {\n            def iter \": \" swap:split:iter =iter\n            (\n                iter:next \": \"\n                iter:join \n            ) this:headers:set;\n        } pop\n        0 (\"Content-Length\" this:headers:get _mega) bytes:collect:sub this:=body\n        this\n    }\n    content-type { str | with this ;\n        \"Content-Type\" this:headers:get\n    }\n}\n";