module HTTPMessages export Message, requests, responses, Headers const Headers = Vector{Pair{String,String}} mutable struct Message name::String raw::String method::String status_code::Int response_status::String request_path::String request_url::String fragment::String query_string::String body::String body_size::Int host::String userinfo::String port::String num_headers::Int headers::Headers should_keep_alive::Bool upgrade::String http_major::Int http_minor::Int Message(name::String) = new(name, "", "GET", 200, "", "", "", "", "", "", 0, "", "", "", 0, Headers(), true, "", 1, 1) end function Message(; name::String="", kwargs...) m = Message(name) for (k, v) in kwargs try setfield!(m, k, v) catch e error("error setting k=$k, v=$v") end end return m end #= * R E Q U E S T S * =# const requests = Message[ Message(name= "curl get" ,raw= "GET /test HTTP/1.1\r\n" * "User-Agent: curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1\r\n" * "Host:0.0.0.0=5000\r\n" * # missing space after colon "Accept: */*\r\n" * "\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "GET" ,query_string= "" ,fragment= "" ,request_path= "/test" ,request_url= "/test" ,num_headers= 3 ,headers=[ "User-Agent"=> "curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1" , "Host"=> "0.0.0.0=5000" , "Accept"=> "*/*" ] ,body= "" ), Message(name= "firefox get" ,raw= "GET /favicon.ico HTTP/1.1\r\n" * "Host: 0.0.0.0=5000\r\n" * "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0\r\n" * "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" * "Accept-Language: en-us,en;q=0.5\r\n" * "Accept-Encoding: gzip,deflate\r\n" * "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" * "Keep-Alive: 300\r\n" * "Connection: keep-alive\r\n" * "\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "GET" ,query_string= "" ,fragment= "" ,request_path= "/favicon.ico" ,request_url= "/favicon.ico" ,num_headers= 8 ,headers=[ "Host"=> "0.0.0.0=5000" , "User-Agent"=> "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0" , "Accept"=> "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" , "Accept-Language"=> "en-us,en;q=0.5" , "Accept-Encoding"=> "gzip,deflate" , "Accept-Charset"=> "ISO-8859-1,utf-8;q=0.7,*;q=0.7" , "Keep-Alive"=> "300" , "Connection"=> "keep-alive" ] ,body= "" ), Message(name= "abcdefgh" ,raw= "GET /abcdefgh HTTP/1.1\r\n" * "aaaaaaaaaaaaa:++++++++++\r\n" * "\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "GET" ,query_string= "" ,fragment= "" ,request_path= "/abcdefgh" ,request_url= "/abcdefgh" ,num_headers= 1 ,headers=[ "Aaaaaaaaaaaaa"=> "++++++++++" ] ,body= "" ), Message(name= "fragment in url" ,raw= "GET /forums/1/topics/2375?page=1#posts-17408 HTTP/1.1\r\n" * "\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "GET" ,query_string= "page=1" ,fragment= "posts-17408" ,request_path= "/forums/1/topics/2375" #= XXX request url does include fragment? =# ,request_url= "/forums/1/topics/2375?page=1#posts-17408" ,num_headers= 0 ,body= "" ), Message(name= "get no headers no body" ,raw= "GET /get_no_headers_no_body/world HTTP/1.1\r\n" * "\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "GET" ,query_string= "" ,fragment= "" ,request_path= "/get_no_headers_no_body/world" ,request_url= "/get_no_headers_no_body/world" ,num_headers= 0 ,body= "" ), Message(name= "get one header no body" ,raw= "GET /get_one_header_no_body HTTP/1.1\r\n" * "Accept: */*\r\n" * "\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "GET" ,query_string= "" ,fragment= "" ,request_path= "/get_one_header_no_body" ,request_url= "/get_one_header_no_body" ,num_headers= 1 ,headers=[ "Accept" => "*/*" ] ,body= "" ), Message(name= "get funky content length body hello" ,raw= "GET /get_funky_content_length_body_hello HTTP/1.0\r\n" * "conTENT-Length: 5\r\n" * "\r\n" * "HELLO" ,should_keep_alive= false ,http_major= 1 ,http_minor= 0 ,method= "GET" ,query_string= "" ,fragment= "" ,request_path= "/get_funky_content_length_body_hello" ,request_url= "/get_funky_content_length_body_hello" ,num_headers= 1 ,headers=[ "Content-Length" => "5" ] ,body= "HELLO" ), Message(name= "post identity body world" ,raw= "POST /post_identity_body_world?q=search#hey HTTP/1.1\r\n" * "Accept: */*\r\n" * "Transfer-Encoding: identity\r\n" * "Content-Length: 5\r\n" * "\r\n" * "World" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "POST" ,query_string= "q=search" ,fragment= "hey" ,request_path= "/post_identity_body_world" ,request_url= "/post_identity_body_world?q=search#hey" ,num_headers= 3 ,headers=[ "Accept"=> "*/*" , "Transfer-Encoding"=> "identity" , "Content-Length"=> "5" ] ,body= "World" ), Message(name= "post - chunked body: all your base are belong to us" ,raw= "POST /post_chunked_all_your_base HTTP/1.1\r\n" * "Transfer-Encoding: chunked\r\n" * "\r\n" * "1e\r\nall your base are belong to us\r\n" * "0\r\n" * "\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "POST" ,query_string= "" ,fragment= "" ,request_path= "/post_chunked_all_your_base" ,request_url= "/post_chunked_all_your_base" ,num_headers= 1 ,headers=[ "Transfer-Encoding" => "chunked" ] ,body= "all your base are belong to us" ), Message(name= "two chunks ; triple zero ending" ,raw= "POST /two_chunks_mult_zero_end HTTP/1.1\r\n" * "Transfer-Encoding: chunked\r\n" * "\r\n" * "5\r\nhello\r\n" * "6\r\n world\r\n" * "000\r\n" * "\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "POST" ,query_string= "" ,fragment= "" ,request_path= "/two_chunks_mult_zero_end" ,request_url= "/two_chunks_mult_zero_end" ,num_headers= 1 ,headers=[ "Transfer-Encoding"=> "chunked" ] ,body= "hello world" ), Message(name= "chunked with trailing headers. blech." ,raw= "POST /chunked_w_trailing_headers HTTP/1.1\r\n" * "Transfer-Encoding: chunked\r\n" * "\r\n" * "5\r\nhello\r\n" * "6\r\n world\r\n" * "0\r\n" * "Vary: *\r\n" * "Content-Type: text/plain\r\n" * "\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "POST" ,query_string= "" ,fragment= "" ,request_path= "/chunked_w_trailing_headers" ,request_url= "/chunked_w_trailing_headers" ,num_headers= 3 ,headers=[ "Transfer-Encoding"=> "chunked" , "Vary"=> "*" , "Content-Type"=> "text/plain" ] ,body= "hello world" ), Message(name= "with excessss after the length" ,raw= "POST /chunked_w_excessss_after_length HTTP/1.1\r\n" * "Transfer-Encoding: chunked\r\n" * "\r\n" * "5; ihatew3;whattheheck=aretheseparametersfor\r\nhello\r\n" * "6; blahblah; blah\r\n world\r\n" * "0\r\n" * "\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "POST" ,query_string= "" ,fragment= "" ,request_path= "/chunked_w_excessss_after_length" ,request_url= "/chunked_w_excessss_after_length" ,num_headers= 1 ,headers=[ "Transfer-Encoding"=> "chunked" ] ,body= "hello world" ), Message(name= "with quotes" ,raw= "GET /with_\"stupid\"_quotes?foo=\"bar\" HTTP/1.1\r\n\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "GET" ,query_string= "foo=\"bar\"" ,fragment= "" ,request_path= "/with_\"stupid\"_quotes" ,request_url= "/with_\"stupid\"_quotes?foo=\"bar\"" ,num_headers= 0 ,headers=Headers() ,body= "" ), Message(name = "apachebench get" ,raw= "GET /test HTTP/1.0\r\n" * "Host: 0.0.0.0:5000\r\n" * "User-Agent: ApacheBench/2.3\r\n" * "Accept: */*\r\n\r\n" ,should_keep_alive= false ,http_major= 1 ,http_minor= 0 ,method= "GET" ,query_string= "" ,fragment= "" ,request_path= "/test" ,request_url= "/test" ,num_headers= 3 ,headers=[ "Host"=> "0.0.0.0:5000" , "User-Agent"=> "ApacheBench/2.3" , "Accept"=> "*/*" ] ,body= "" ), Message(name = "query url with question mark" ,raw= "GET /test.cgi?foo=bar?baz HTTP/1.1\r\n\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "GET" ,query_string= "foo=bar?baz" ,fragment= "" ,request_path= "/test.cgi" ,request_url= "/test.cgi?foo=bar?baz" ,num_headers= 0 ,headers=Headers() ,body= "" ), Message(name = "newline prefix get" ,raw= "\r\nGET /test HTTP/1.1\r\n\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "GET" ,query_string= "" ,fragment= "" ,request_path= "/test" ,request_url= "/test" ,num_headers= 0 ,headers=Headers() ,body= "" ), Message(name = "upgrade request" ,raw= "GET /demo HTTP/1.1\r\n" * "Host: example.com\r\n" * "Connection: Upgrade\r\n" * "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00\r\n" * "Sec-WebSocket-Protocol: sample\r\n" * "Upgrade: WebSocket\r\n" * "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n" * "Origin: http://example.com\r\n" * "\r\n" * "Hot diggity dogg" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "GET" ,query_string= "" ,fragment= "" ,request_path= "/demo" ,request_url= "/demo" ,num_headers= 7 ,upgrade="Hot diggity dogg" ,headers=[ "Host"=> "example.com" , "Connection"=> "Upgrade" , "Sec-Websocket-Key2"=> "12998 5 Y3 1 .P00" , "Sec-Websocket-Protocol"=> "sample" , "Upgrade"=> "WebSocket" , "Sec-Websocket-Key1"=> "4 @1 46546xW%0l 1 5" , "Origin"=> "http://example.com" ] ,body= "" ), Message(name = "connect request" ,raw= "CONNECT 0-home0.netscape.com:443 HTTP/1.0\r\n" * "User-agent: Mozilla/1.1N\r\n" * "Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n" * "\r\n" * "some data\r\n" * "and yet even more data" ,should_keep_alive= false ,http_major= 1 ,http_minor= 0 ,method= "CONNECT" ,query_string= "" ,fragment= "" ,request_path= "" ,host="0-home0.netscape.com" ,port="443" ,request_url= "0-home0.netscape.com:443" ,num_headers= 2 ,upgrade="some data\r\nand yet even more data" ,headers=[ "User-Agent"=> "Mozilla/1.1N" , "Proxy-Authorization"=> "basic aGVsbG86d29ybGQ=" ] ,body= "" ), Message(name= "report request" ,raw= "REPORT /test HTTP/1.1\r\n" * "\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "REPORT" ,query_string= "" ,fragment= "" ,request_path= "/test" ,request_url= "/test" ,num_headers= 0 ,headers=Headers() ,body= "" #= ), Message(name= "request with no http version" ,raw= "GET /\r\n" * "\r\n" ,should_keep_alive= false ,http_major= 0 ,http_minor= 9 ,method= "GET" ,query_string= "" ,fragment= "" ,request_path= "/" ,request_url= "/" ,num_headers= 0 ,headers=Headers() ,body= "" =# ), Message(name= "m-search request" ,raw= "M-SEARCH * HTTP/1.1\r\n" * "HOST: 239.255.255.250:1900\r\n" * "MAN: \"ssdp:discover\"\r\n" * "ST: \"ssdp:all\"\r\n" * "\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "M-SEARCH" ,query_string= "" ,fragment= "" ,request_path= "*" ,request_url= "*" ,num_headers= 3 ,headers=[ "Host"=> "239.255.255.250:1900" , "Man"=> "\"ssdp:discover\"" , "St"=> "\"ssdp:all\"" ] ,body= "" ), Message(name= "host terminated by a query string" ,raw= "GET http://hypnotoad.org?hail=all HTTP/1.1\r\n" * "\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "GET" ,query_string= "hail=all" ,fragment= "" ,request_path= "" ,request_url= "http://hypnotoad.org?hail=all" ,host= "hypnotoad.org" ,num_headers= 0 ,headers=Headers() ,body= "" ), Message(name= "host:port terminated by a query string" ,raw= "GET http://hypnotoad.org:1234?hail=all HTTP/1.1\r\n" * "\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "GET" ,query_string= "hail=all" ,fragment= "" ,request_path= "" ,request_url= "http://hypnotoad.org:1234?hail=all" ,host= "hypnotoad.org" ,port= "1234" ,num_headers= 0 ,headers=Headers() ,body= "" ), Message(name= "host:port terminated by a space" ,raw= "GET http://hypnotoad.org:1234 HTTP/1.1\r\n" * "\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "GET" ,query_string= "" ,fragment= "" ,request_path= "" ,request_url= "http://hypnotoad.org:1234" ,host= "hypnotoad.org" ,port= "1234" ,num_headers= 0 ,headers=Headers() ,body= "" ), Message(name = "PATCH request" ,raw= "PATCH /file.txt HTTP/1.1\r\n" * "Host: www.example.com\r\n" * "Content-Type: application/example\r\n" * "If-Match: \"e0023aa4e\"\r\n" * "Content-Length: 10\r\n" * "\r\n" * "cccccccccc" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "PATCH" ,query_string= "" ,fragment= "" ,request_path= "/file.txt" ,request_url= "/file.txt" ,num_headers= 4 ,headers=[ "Host"=> "www.example.com" , "Content-Type"=> "application/example" , "If-Match"=> "\"e0023aa4e\"" , "Content-Length"=> "10" ] ,body= "cccccccccc" ), Message(name = "connect caps request" ,raw= "CONNECT HOME0.NETSCAPE.COM:443 HTTP/1.0\r\n" * "User-agent: Mozilla/1.1N\r\n" * "Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n" * "\r\n" ,should_keep_alive= false ,http_major= 1 ,http_minor= 0 ,method= "CONNECT" ,query_string= "" ,fragment= "" ,request_path= "" ,request_url= "HOME0.NETSCAPE.COM:443" ,host="HOME0.NETSCAPE.COM" ,port="443" ,num_headers= 2 ,upgrade="" ,headers=[ "User-Agent"=> "Mozilla/1.1N" , "Proxy-Authorization"=> "basic aGVsbG86d29ybGQ=" ] ,body= "" ), Message(name= "utf-8 path request" ,raw= "GET /δ¶/δt/pope?q=1#narf HTTP/1.1\r\n" * "Host: github.com\r\n" * "\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "GET" ,query_string= "q=1" ,fragment= "narf" ,request_path= "/δ¶/δt/pope" ,request_url= "/δ¶/δt/pope?q=1#narf" ,num_headers= 1 ,headers=["Host" => "github.com"] ,body= "" ), Message(name = "hostname underscore" ,raw= "CONNECT home_0.netscape.com:443 HTTP/1.0\r\n" * "User-agent: Mozilla/1.1N\r\n" * "Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n" * "\r\n" ,should_keep_alive= false ,http_major= 1 ,http_minor= 0 ,method= "CONNECT" ,query_string= "" ,fragment= "" ,request_path= "" ,request_url= "home_0.netscape.com:443" ,host="home_0.netscape.com" ,port="443" ,num_headers= 2 ,upgrade="" ,headers=[ "User-Agent"=> "Mozilla/1.1N" , "Proxy-Authorization"=> "basic aGVsbG86d29ybGQ=" ] ,body= "" ), Message(name = "eat CRLF between requests, no \"Connection: close\" header" ,raw= "POST / HTTP/1.1\r\n" * "Host: www.example.com\r\n" * "Content-Type: application/x-www-form-urlencoded\r\n" * "Content-Length: 4\r\n" * "\r\n" * "q=42\r\n" #= note the trailing CRLF =# ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "POST" ,query_string= "" ,fragment= "" ,request_path= "/" ,request_url= "/" ,num_headers= 3 ,upgrade= "" ,headers=[ "Host"=> "www.example.com" , "Content-Type"=> "application/x-www-form-urlencoded" , "Content-Length"=> "4" ] ,body= "q=42" ), Message(name = "eat CRLF between requests even if \"Connection: close\" is set" ,raw= "POST / HTTP/1.1\r\n" * "Host: www.example.com\r\n" * "Content-Type: application/x-www-form-urlencoded\r\n" * "Content-Length: 4\r\n" * "Connection: close\r\n" * "\r\n" * "q=42\r\n" #= note the trailing CRLF =# ,should_keep_alive= false ,http_major= 1 ,http_minor= 1 ,method= "POST" ,query_string= "" ,fragment= "" ,request_path= "/" ,request_url= "/" ,num_headers= 4 ,upgrade= "" ,headers=[ "Host"=> "www.example.com" , "Content-Type"=> "application/x-www-form-urlencoded" , "Content-Length"=> "4" , "Connection"=> "close" ] ,body= "q=42" ), Message(name = "PURGE request" ,raw= "PURGE /file.txt HTTP/1.1\r\n" * "Host: www.example.com\r\n" * "\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "PURGE" ,query_string= "" ,fragment= "" ,request_path= "/file.txt" ,request_url= "/file.txt" ,num_headers= 1 ,headers=[ "Host"=> "www.example.com" ] ,body= "" ), Message(name = "SEARCH request" ,raw= "SEARCH / HTTP/1.1\r\n" * "Host: www.example.com\r\n" * "\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "SEARCH" ,query_string= "" ,fragment= "" ,request_path= "/" ,request_url= "/" ,num_headers= 1 ,headers=[ "Host"=> "www.example.com"] ,body= "" ), Message(name= "host:port and basic_auth" ,raw= "GET http://a%12:b!&*\$@hypnotoad.org:1234/toto HTTP/1.1\r\n" * "\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "GET" ,fragment= "" ,request_path= "/toto" ,request_url= "http://a%12:b!&*\$@hypnotoad.org:1234/toto" ,host= "hypnotoad.org" ,userinfo= "a%12:b!&*\$" ,port= "1234" ,num_headers= 0 ,headers=Headers() ,body= "" ), Message(name = "upgrade post request" ,raw= "POST /demo HTTP/1.1\r\n" * "Host: example.com\r\n" * "Connection: Upgrade\r\n" * "Upgrade: HTTP/2.0\r\n" * "Content-Length: 15\r\n" * "\r\n" * "sweet post body" * "Hot diggity dogg" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "POST" ,request_path= "/demo" ,request_url= "/demo" ,num_headers= 4 ,upgrade="Hot diggity dogg" ,headers=[ "Host"=> "example.com" , "Connection"=> "Upgrade" , "Upgrade"=> "HTTP/2.0" , "Content-Length"=> "15" ] ,body= "sweet post body" ), Message(name = "connect with body request" ,raw= "CONNECT foo.bar.com:443 HTTP/1.0\r\n" * "User-agent: Mozilla/1.1N\r\n" * "Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n" * "Content-Length: 10\r\n" * "\r\n" * "blarfcicle" ,should_keep_alive= false ,http_major= 1 ,http_minor= 0 ,method= "CONNECT" ,request_url= "foo.bar.com:443" ,host="foo.bar.com" ,port="443" ,num_headers= 3 ,upgrade="" ,headers=[ "User-Agent"=> "Mozilla/1.1N" , "Proxy-Authorization"=> "basic aGVsbG86d29ybGQ=" , "Content-Length"=> "10" ] ,body= "blarfcicle" ), Message(name = "link request" ,raw= "LINK /images/my_dog.jpg HTTP/1.1\r\n" * "Host: example.com\r\n" * "Link: ; rel=\"tag\"\r\n" * "Link: ; rel=\"tag\"\r\n" * "\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "LINK" ,request_path= "/images/my_dog.jpg" ,request_url= "/images/my_dog.jpg" ,query_string= "" ,fragment= "" ,num_headers= 2 ,headers=[ "Host"=> "example.com" , "Link"=> "; rel=\"tag\", ; rel=\"tag\"" ] ,body= "" ), Message(name = "link request" ,raw= "UNLINK /images/my_dog.jpg HTTP/1.1\r\n" * "Host: example.com\r\n" * "Link: ; rel=\"tag\"\r\n" * "\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "UNLINK" ,request_path= "/images/my_dog.jpg" ,request_url= "/images/my_dog.jpg" ,query_string= "" ,fragment= "" ,num_headers= 2 ,headers=[ "Host"=> "example.com" , "Link"=> "; rel=\"tag\"" ] ,body= "" ), Message(name = "multiple connection header values with folding" ,raw= "GET /demo HTTP/1.1\r\n" * "Host: example.com\r\n" * "Connection: Something,\r\n" * " Upgrade, ,Keep-Alive\r\n" * "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00\r\n" * "Sec-WebSocket-Protocol: sample\r\n" * "Upgrade: WebSocket\r\n" * "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n" * "Origin: http://example.com\r\n" * "\r\n" * "Hot diggity dogg" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "GET" ,query_string= "" ,fragment= "" ,request_path= "/demo" ,request_url= "/demo" ,num_headers= 7 ,upgrade="Hot diggity dogg" ,headers=[ "Host"=> "example.com" , "Connection"=> "Something, Upgrade, ,Keep-Alive" , "Sec-Websocket-Key2"=> "12998 5 Y3 1 .P00" , "Sec-Websocket-Protocol"=> "sample" , "Upgrade"=> "WebSocket" , "Sec-Websocket-Key1"=> "4 @1 46546xW%0l 1 5" , "Origin"=> "http://example.com" ] ,body= "" ), Message(name= "line folding in header value" ,raw= "GET / HTTP/1.1\r\n" * "Line1: abc\r\n" * "\tdef\r\n" * " ghi\r\n" * "\t\tjkl\r\n" * " mno \r\n" * "\t \tqrs\r\n" * "Line2: \t line2\t\r\n" * "Line3:\r\n" * " line3\r\n" * "Line4: \r\n" * " \r\n" * "Connection:\r\n" * " close\r\n" * "\r\n" ,should_keep_alive= false ,http_major= 1 ,http_minor= 1 ,method= "GET" ,query_string= "" ,fragment= "" ,request_path= "/" ,request_url= "/" ,num_headers= 5 ,headers=[ "Line1"=> "abc\tdef ghi\t\tjkl mno \t \tqrs" , "Line2"=> "line2" , "Line3"=> " line3" , "Line4"=> " " , "Connection"=> " close" ] ,body= "" ), Message(name = "multiple connection header values with folding and lws" ,raw= "GET /demo HTTP/1.1\r\n" * "Connection: keep-alive, upgrade\r\n" * "Upgrade: WebSocket\r\n" * "\r\n" * "Hot diggity dogg" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "GET" ,query_string= "" ,fragment= "" ,request_path= "/demo" ,request_url= "/demo" ,num_headers= 2 ,upgrade="Hot diggity dogg" ,headers=[ "Connection"=> "keep-alive, upgrade" , "Upgrade"=> "WebSocket" ] ,body= "" ), Message(name = "multiple connection header values with folding and lws" ,raw= "GET /demo HTTP/1.1\r\n" * "Connection: keep-alive, \r\n upgrade\r\n" * "Upgrade: WebSocket\r\n" * "\r\n" * "Hot diggity dogg" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,method= "GET" ,query_string= "" ,fragment= "" ,request_path= "/demo" ,request_url= "/demo" ,num_headers= 2 ,upgrade="Hot diggity dogg" ,headers=[ "Connection"=> "keep-alive, upgrade" , "Upgrade"=> "WebSocket" ] ,body= "" ), Message(name= "line folding in header value" ,raw= "GET / HTTP/1.1\n" * "Line1: abc\n" * "\tdef\n" * " ghi\n" * "\t\tjkl\n" * " mno \n" * "\t \tqrs\n" * "Line2: \t line2\t\n" * "Line3:\n" * " line3\n" * "Line4: \n" * " \n" * "Connection:\n" * " close\n" * "\n" ,should_keep_alive= false ,http_major= 1 ,http_minor= 1 ,method= "GET" ,query_string= "" ,fragment= "" ,request_path= "/" ,request_url= "/" ,num_headers= 5 ,headers=[ "Line1"=> "abc\tdef ghi\t\tjkl mno \t \tqrs" , "Line2"=> "line2" , "Line3"=> " line3" , "Line4"=> " " , "Connection"=> " close" ] ,body= "" ) ] #= * R E S P O N S E S * =# const responses = Message[ Message(name= "google 301" ,raw= "HTTP/1.1 301 Moved Permanently\r\n" * "Location: http://www.google.com/\r\n" * "Content-Type: text/html; charset=UTF-8\r\n" * "Date: Sun, 26 Apr 2009 11:11:49 GMT\r\n" * "Expires: Tue, 26 May 2009 11:11:49 GMT\r\n" * "X-\$PrototypeBI-Version: 1.6.0.3\r\n" * #= $ char in header field =# "Cache-Control: public, max-age=2592000\r\n" * "Server: gws\r\n" * "Content-Length: 219 \r\n" * "\r\n" * "\n" * "301 Moved\n" * "

301 Moved

\n" * "The document has moved\n" * "here.\r\n" * "\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,status_code= 301 ,response_status= "Moved Permanently" ,num_headers= 8 ,headers=[ "Location"=> "http://www.google.com/" , "Content-Type"=> "text/html; charset=UTF-8" , "Date"=> "Sun, 26 Apr 2009 11:11:49 GMT" , "Expires"=> "Tue, 26 May 2009 11:11:49 GMT" , "X-\$prototypebi-Version"=> "1.6.0.3" , "Cache-Control"=> "public, max-age=2592000" , "Server"=> "gws" , "Content-Length"=> "219" ] ,body= "\n" * "301 Moved\n" * "

301 Moved

\n" * "The document has moved\n" * "here.\r\n" * "\r\n" ), Message(name= "no content-length response" ,raw= "HTTP/1.1 200 OK\r\n" * "Date: Tue, 04 Aug 2009 07:59:32 GMT\r\n" * "Server: Apache\r\n" * "X-Powered-By: Servlet/2.5 JSP/2.1\r\n" * "Content-Type: text/xml; charset=utf-8\r\n" * "Connection: close\r\n" * "\r\n" * "\n" * "\n" * " \n" * " \n" * " SOAP-ENV:Client\n" * " Client Error\n" * " \n" * " \n" * "" ,should_keep_alive= false ,http_major= 1 ,http_minor= 1 ,status_code= 200 ,response_status= "OK" ,num_headers= 5 ,headers=[ "Date"=> "Tue, 04 Aug 2009 07:59:32 GMT" , "Server"=> "Apache" , "X-Powered-By"=> "Servlet/2.5 JSP/2.1" , "Content-Type"=> "text/xml; charset=utf-8" , "Connection"=> "close" ] ,body= "\n" * "\n" * " \n" * " \n" * " SOAP-ENV:Client\n" * " Client Error\n" * " \n" * " \n" * "" ), Message(name= "404 no headers no body" ,raw= "HTTP/1.1 404 Not Found\r\n\r\n" ,should_keep_alive= false ,http_major= 1 ,http_minor= 1 ,status_code= 404 ,response_status= "Not Found" ,num_headers= 0 ,headers=Headers() ,body_size= 0 ,body= "" ), Message(name= "301 no response phrase" ,raw= "HTTP/1.1 301\r\n\r\n" ,should_keep_alive = false ,http_major= 1 ,http_minor= 1 ,status_code= 301 ,response_status= "Moved Permanently" ,num_headers= 0 ,headers=Headers() ,body= "" ), Message(name="200 trailing space on chunked body" ,raw= "HTTP/1.1 200 OK\r\n" * "Content-Type: text/plain\r\n" * "Transfer-Encoding: chunked\r\n" * "\r\n" * "25 \r\n" * "This is the data in the first chunk\r\n" * "\r\n" * "1C\r\n" * "and this is the second one\r\n" * "\r\n" * "0 \r\n" * "\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,status_code= 200 ,response_status= "OK" ,num_headers= 2 ,headers=[ "Content-Type"=> "text/plain" , "Transfer-Encoding"=> "chunked" ] ,body_size = 37+28 ,body = "This is the data in the first chunk\r\n" * "and this is the second one\r\n" ), Message(name="no carriage ret" ,raw= "HTTP/1.1 200 OK\n" * "Content-Type: text/html; charset=utf-8\n" * "Connection: close\n" * "\n" * "these headers are from http://news.ycombinator.com/" ,should_keep_alive= false ,http_major= 1 ,http_minor= 1 ,status_code= 200 ,response_status= "OK" ,num_headers= 2 ,headers=[ "Content-Type"=> "text/html; charset=utf-8" , "Connection"=> "close" ] ,body= "these headers are from http://news.ycombinator.com/" ), Message(name="proxy connection" ,raw= "HTTP/1.1 200 OK\r\n" * "Content-Type: text/html; charset=UTF-8\r\n" * "Content-Length: 11\r\n" * "Proxy-Connection: close\r\n" * "Date: Thu, 31 Dec 2009 20:55:48 +0000\r\n" * "\r\n" * "hello world" ,should_keep_alive= false ,http_major= 1 ,http_minor= 1 ,status_code= 200 ,response_status= "OK" ,num_headers= 4 ,headers=[ "Content-Type"=> "text/html; charset=UTF-8" , "Content-Length"=> "11" , "Proxy-Connection"=> "close" , "Date"=> "Thu, 31 Dec 2009 20:55:48 +0000" ] ,body= "hello world" ), Message(name="underscore header key" ,raw= "HTTP/1.1 200 OK\r\n" * "Server: DCLK-AdSvr\r\n" * "Content-Type: text/xml\r\n" * "Content-Length: 0\r\n" * "DCLK_imp: v7;x;114750856;0-0;0;17820020;0/0;21603567/21621457/1;;~okv=;dcmt=text/xml;;~cs=o\r\n\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,status_code= 200 ,response_status= "OK" ,num_headers= 4 ,headers=[ "Server"=> "DCLK-AdSvr" , "Content-Type"=> "text/xml" , "Content-Length"=> "0" , "Dclk_imp"=> "v7;x;114750856;0-0;0;17820020;0/0;21603567/21621457/1;;~okv=;dcmt=text/xml;;~cs=o" ] ,body= "" ), Message(name= "bonjourmadame.fr" ,raw= "HTTP/1.0 301 Moved Permanently\r\n" * "Date: Thu, 03 Jun 2010 09:56:32 GMT\r\n" * "Server: Apache/2.2.3 (Red Hat)\r\n" * "Cache-Control: public\r\n" * "Pragma: \r\n" * "Location: http://www.bonjourmadame.fr/\r\n" * "Vary: Accept-Encoding\r\n" * "Content-Length: 0\r\n" * "Content-Type: text/html; charset=UTF-8\r\n" * "Connection: keep-alive\r\n" * "\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 0 ,status_code= 301 ,response_status= "Moved Permanently" ,num_headers= 9 ,headers=[ "Date"=> "Thu, 03 Jun 2010 09:56:32 GMT" , "Server"=> "Apache/2.2.3 (Red Hat)" , "Cache-Control"=> "public" , "Pragma"=> "" , "Location"=> "http://www.bonjourmadame.fr/" , "Vary"=> "Accept-Encoding" , "Content-Length"=> "0" , "Content-Type"=> "text/html; charset=UTF-8" , "Connection"=> "keep-alive" ] ,body= "" ), Message(name= "field underscore" ,raw= "HTTP/1.1 200 OK\r\n" * "Date: Tue, 28 Sep 2010 01:14:13 GMT\r\n" * "Server: Apache\r\n" * "Cache-Control: no-cache, must-revalidate\r\n" * "Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n" * ".et-Cookie: PlaxoCS=1274804622353690521; path=/; domain=.plaxo.com\r\n" * "Vary: Accept-Encoding\r\n" * "_eep-Alive: timeout=45\r\n" * #= semantic value ignored =# "_onnection: Keep-Alive\r\n" * #= semantic value ignored =# "Transfer-Encoding: chunked\r\n" * "Content-Type: text/html\r\n" * "Connection: close\r\n" * "\r\n" * "0\r\n\r\n" ,should_keep_alive= false ,http_major= 1 ,http_minor= 1 ,status_code= 200 ,response_status= "OK" ,num_headers= 11 ,headers=[ "Date"=> "Tue, 28 Sep 2010 01:14:13 GMT" , "Server"=> "Apache" , "Cache-Control"=> "no-cache, must-revalidate" , "Expires"=> "Mon, 26 Jul 1997 05:00:00 GMT" , ".et-Cookie"=> "PlaxoCS=1274804622353690521; path=/; domain=.plaxo.com" , "Vary"=> "Accept-Encoding" , "_eep-Alive"=> "timeout=45" , "_onnection"=> "Keep-Alive" , "Transfer-Encoding"=> "chunked" , "Content-Type"=> "text/html" , "Connection"=> "close" ] ,body= "" ), Message(name= "non-ASCII in status line" ,raw= "HTTP/1.1 500 Oriëntatieprobleem\r\n" * "Date: Fri, 5 Nov 2010 23:07:12 GMT+2\r\n" * "Content-Length: 0\r\n" * "Connection: close\r\n" * "\r\n" ,should_keep_alive= false ,http_major= 1 ,http_minor= 1 ,status_code= 500 ,response_status= "Internal Server Error" ,num_headers= 3 ,headers=[ "Date"=> "Fri, 5 Nov 2010 23:07:12 GMT+2" , "Content-Length"=> "0" , "Connection"=> "close" ] ,body= "" ), Message(name= "http version 0.9" ,raw= "HTTP/0.9 200 OK\r\n" * "\r\n" ,should_keep_alive= false ,http_major= 0 ,http_minor= 9 ,status_code= 200 ,response_status= "OK" ,num_headers= 0 ,headers=Headers() ,body= "" ), Message(name= "neither content-length nor transfer-encoding response" ,raw= "HTTP/1.1 200 OK\r\n" * "Content-Type: text/plain\r\n" * "\r\n" * "hello world" ,should_keep_alive= false ,http_major= 1 ,http_minor= 1 ,status_code= 200 ,response_status= "OK" ,num_headers= 1 ,headers=[ "Content-Type"=> "text/plain" ] ,body= "hello world" ), Message(name= "HTTP/1.0 with keep-alive and EOF-terminated 200 status" ,raw= "HTTP/1.0 200 OK\r\n" * "Connection: keep-alive\r\n" * "\r\n" ,should_keep_alive= false ,http_major= 1 ,http_minor= 0 ,status_code= 200 ,response_status= "OK" ,num_headers= 1 ,headers=[ "Connection"=> "keep-alive" ] ,body_size= 0 ,body= "" ), Message(name= "HTTP/1.0 with keep-alive and a 204 status" ,raw= "HTTP/1.0 204 No content\r\n" * "Connection: keep-alive\r\n" * "\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 0 ,status_code= 204 ,response_status= "No Content" ,num_headers= 1 ,headers=[ "Connection"=> "keep-alive" ] ,body_size= 0 ,body= "" ), Message(name= "HTTP/1.1 with an EOF-terminated 200 status" ,raw= "HTTP/1.1 200 OK\r\n" * "\r\n" ,should_keep_alive= false ,http_major= 1 ,http_minor= 1 ,status_code= 200 ,response_status= "OK" ,num_headers= 0 ,headers=Headers() ,body_size= 0 ,body= "" ), Message(name= "HTTP/1.1 with a 204 status" ,raw= "HTTP/1.1 204 No content\r\n" * "\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,status_code= 204 ,response_status= "No Content" ,num_headers= 0 ,headers=Headers() ,body_size= 0 ,body= "" ), Message(name= "HTTP/1.1 with a 204 status and keep-alive disabled" ,raw= "HTTP/1.1 204 No content\r\n" * "Connection: close\r\n" * "\r\n" ,should_keep_alive= false ,http_major= 1 ,http_minor= 1 ,status_code= 204 ,response_status= "No Content" ,num_headers= 1 ,headers=[ "Connection"=> "close" ] ,body_size= 0 ,body= "" ), Message(name= "HTTP/1.1 with chunked endocing and a 200 response" ,raw= "HTTP/1.1 200 OK\r\n" * "Transfer-Encoding: chunked\r\n" * "\r\n" * "0\r\n" * "\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,status_code= 200 ,response_status= "OK" ,num_headers= 1 ,headers=[ "Transfer-Encoding"=> "chunked" ] ,body_size= 0 ,body= "" #= No reference to source of this was provided when requested here: https://github.com/nodejs/http-parser/pull/64#issuecomment-2042429 ), Message(name= "field space" ,raw= "HTTP/1.1 200 OK\r\n" * "Server: Microsoft-IIS/6.0\r\n" * "X-Powered-By: ASP.NET\r\n" * "en-US Content-Type: text/xml\r\n" * #= this is the problem =# "Content-Type: text/xml\r\n" * "Content-Length: 16\r\n" * "Date: Fri, 23 Jul 2010 18:45:38 GMT\r\n" * "Connection: keep-alive\r\n" * "\r\n" * "hello" #= fake body =# ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,status_code= 200 ,response_status= "OK" ,num_headers= 7 ,headers=[ "Server"=> "Microsoft-IIS/6.0" , "X-Powered-By"=> "ASP.NET" , "En-Us content-Type"=> "text/xml" , "Content-Type"=> "text/xml" , "Content-Length"=> "16" , "Date"=> "Fri, 23 Jul 2010 18:45:38 GMT" , "Connection"=> "keep-alive" ] ,body= "hello" =# ), Message(name= "amazon.com" ,raw= "HTTP/1.1 301 MovedPermanently\r\n" * "Date: Wed, 15 May 2013 17:06:33 GMT\r\n" * "Server: Server\r\n" * "x-amz-id-1: 0GPHKXSJQ826RK7GZEB2\r\n" * "p3p: policyref=\"http://www.amazon.com/w3c/p3p.xml\",CP=\"CAO DSP LAW CUR ADM IVAo IVDo CONo OTPo OUR DELi PUBi OTRi BUS PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA HEA PRE LOC GOV OTC \"\r\n" * "x-amz-id-2: STN69VZxIFSz9YJLbz1GDbxpbjG6Qjmmq5E3DxRhOUw+Et0p4hr7c/Q8qNcx4oAD\r\n" * "Location: http://www.amazon.com/Dan-Brown/e/B000AP9DSU/ref=s9_pop_gw_al1?_encoding=UTF8&refinementId=618073011&pf_rd_m=ATVPDKIKX0DER&pf_rd_s=center-2&pf_rd_r=0SHYY5BZXN3KR20BNFAY&pf_rd_t=101&pf_rd_p=1263340922&pf_rd_i=507846\r\n" * "Vary: Accept-Encoding,User-Agent\r\n" * "Content-Type: text/html; charset=ISO-8859-1\r\n" * "Transfer-Encoding: chunked\r\n" * "\r\n" * "1\r\n" * "\n\r\n" * "0\r\n" * "\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,status_code= 301 ,response_status= "Moved Permanently" ,num_headers= 9 ,headers=[ "Date"=> "Wed, 15 May 2013 17:06:33 GMT" , "Server"=> "Server" , "X-Amz-Id-1"=> "0GPHKXSJQ826RK7GZEB2" , "P3p"=> "policyref=\"http://www.amazon.com/w3c/p3p.xml\",CP=\"CAO DSP LAW CUR ADM IVAo IVDo CONo OTPo OUR DELi PUBi OTRi BUS PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA HEA PRE LOC GOV OTC \"" , "X-Amz-Id-2"=> "STN69VZxIFSz9YJLbz1GDbxpbjG6Qjmmq5E3DxRhOUw+Et0p4hr7c/Q8qNcx4oAD" , "Location"=> "http://www.amazon.com/Dan-Brown/e/B000AP9DSU/ref=s9_pop_gw_al1?_encoding=UTF8&refinementId=618073011&pf_rd_m=ATVPDKIKX0DER&pf_rd_s=center-2&pf_rd_r=0SHYY5BZXN3KR20BNFAY&pf_rd_t=101&pf_rd_p=1263340922&pf_rd_i=507846" , "Vary"=> "Accept-Encoding,User-Agent" , "Content-Type"=> "text/html; charset=ISO-8859-1" , "Transfer-Encoding"=> "chunked" ] ,body= "\n" ), Message(name= "empty reason phrase after space" ,raw= "HTTP/1.1 200 \r\n" * "\r\n" ,should_keep_alive= false ,http_major= 1 ,http_minor= 1 ,status_code= 200 ,response_status= "OK" ,num_headers= 0 ,headers=Headers() ,body= "" ), Message(name= "Content-Length-X" ,raw= "HTTP/1.1 200 OK\r\n" * "Content-Length-X: 0\r\n" * "Transfer-Encoding: chunked\r\n" * "\r\n" * "2\r\n" * "OK\r\n" * "0\r\n" * "\r\n" ,should_keep_alive= true ,http_major= 1 ,http_minor= 1 ,status_code= 200 ,response_status= "OK" ,num_headers= 2 ,headers=[ "Content-Length-X"=> "0" , "Transfer-Encoding"=> "chunked" ] ,body= "OK" ) ] end # module HTTPMessages