ninenines / cowlib

Support library for manipulating Web protocols.
ISC License
279 stars 173 forks source link

cow_http_hd:reg_name/2 should accept url encoded values #53

Open fp opened 7 years ago

fp commented 7 years ago

According to RFC 7230, section 5.4, the host header should accept:

Host = uri-host [ ":" port ] ; Section 2.7.1

and uri-host is defined to be:

uri-host      = <host, see [RFC3986], Section 3.2.2>

which in RFC3986, section 3.2.2 is defined to be:

host        = IP-literal / IPv4address / reg-name
reg-name    = *( unreserved / pct-encoded / sub-delims )
pct-encoded   = "%" HEXDIG HEXDIG

and as a result cow_http_hd:reg_name/2 should accept url encoded values.

A patched hackney trace shows this being rejected by the current code in cowboy master:

[hackney trace 40 <0.498.0> 2017:01:28 21:46:36 4833] perform request 
   Content: [{module,hackney_request},
             {line,97},
             {header_data,<<"GET /erllambda/erllambda_test HTTP/1.1\r\naccept: application/json\r\nUser-Agent: hackney/1.6.4\r\nHost: %2ftmp%2ferllambda.sock\r\n\r\n">>},
             {perform_all,true},
             {expect,false}]

[hackney trace 80 <0.498.0> 2017:01:28 21:46:36 4834] got response 
   Content: [{module,hackney},
             {line,372},
             {response,
                 {ok,400,
                     [{<<"content-length">>,<<"0">>}],
                     {client,
                         {1485,639996,831109},
                         {metrics_ng,metrics_dummy},
                         hackney_local_tcp,"/tmp/erllambda.sock",0,
                         <<"/tmp/erllambda.sock:0">>,[],#Port<0.16995>,
                         {default,#Ref<0.0.2.8596>,
                             {"/tmp/erllambda.sock",0,hackney_local_tcp},
                             <0.500.0>,hackney_local_tcp},
                         #Ref<0.0.2.8596>,true,hackney_pool,5000,false,5,
                         false,5,nil,nil,
                         {hparser,response,4096,10,0,on_body,<<>>,
                             {1,1},
                             undefined,[],0,undefined,undefined,undefined,
                             undefined,waiting},
                         connected,waiting,nil,normal,false,false,false,
                         undefined,false,#Fun<hackney_request.send.2>,waiting,
                         nil,4096,<<>>,[],
                         {1,1},
                         0,nil,nil,<<"GET">>,<<"/erllambda/erllambda_test">>,
                         nil}}},
             {client,
                 {client,
                     {1485,639996,831109},
                     {metrics_ng,metrics_dummy},
                     hackney_local_tcp,"/tmp/erllambda.sock",0,
                     <<"/tmp/erllambda.sock:0">>,[],#Port<0.16995>,
                     {default,#Ref<0.0.2.8596>,
                         {"/tmp/erllambda.sock",0,hackney_local_tcp},
                         <0.500.0>,hackney_local_tcp},
                     #Ref<0.0.2.8596>,true,hackney_pool,5000,false,5,false,5,
                     nil,nil,nil,connected,start,nil,normal,false,false,false,
                     undefined,false,nil,waiting,nil,4096,<<>>,[],undefined,
                     nil,nil,nil,nil,undefined,nil}}]
essen commented 7 years ago

Yes I know: https://github.com/ninenines/cowlib/blob/master/src/cow_http_hd.erl#L1897

I didn't have the appropriate function at the time. It's now available in cow_uri. A patch should be straightforward.

fp commented 7 years ago

Completely missed that comment! If it is safe to have reg_name/2 allow percent-encoding, I can produce a PR if that will help.

essen commented 7 years ago

It's safe. We currently just reject completely. Make sure you include tests, and double check if there's any considerations with regard to a percent encoded : or port.