diff options
Diffstat (limited to 'src/cowboy_protocol.erl')
-rw-r--r-- | src/cowboy_protocol.erl | 89 |
1 files changed, 57 insertions, 32 deletions
diff --git a/src/cowboy_protocol.erl b/src/cowboy_protocol.erl index 40be2c0..68a03b1 100644 --- a/src/cowboy_protocol.erl +++ b/src/cowboy_protocol.erl @@ -54,7 +54,7 @@ %% Internal. -export([init/4]). -export([parse_request/3]). --export([parse_host/2]). +-export([parse_host/3]). -export([resume/6]). -type opts() :: [{compress, boolean()} @@ -426,7 +426,7 @@ request(B, State=#state{transport=Transport}, M, P, Q, Version, Headers) -> request(B, State, M, P, Q, Version, Headers, <<>>, default_port(Transport:name())); {_, RawHost} -> - case catch parse_host(RawHost, <<>>) of + case catch parse_host(RawHost, false, <<>>) of {'EXIT', _} -> error_terminate(400, State); {Host, undefined} -> @@ -443,39 +443,43 @@ default_port(ssl) -> 443; default_port(_) -> 80. %% Another hurtful block of code. :) -parse_host(<<>>, Acc) -> +parse_host(<< $[, Rest/bits >>, false, <<>>) -> + parse_host(Rest, true, << $[ >>); +parse_host(<<>>, false, Acc) -> {Acc, undefined}; -parse_host(<< $:, Rest/bits >>, Acc) -> +parse_host(<< $:, Rest/bits >>, false, Acc) -> {Acc, list_to_integer(binary_to_list(Rest))}; -parse_host(<< C, Rest/bits >>, Acc) -> +parse_host(<< $], Rest/bits >>, true, Acc) -> + parse_host(Rest, false, << Acc/binary, $] >>); +parse_host(<< C, Rest/bits >>, E, Acc) -> case C of - $A -> parse_host(Rest, << Acc/binary, $a >>); - $B -> parse_host(Rest, << Acc/binary, $b >>); - $C -> parse_host(Rest, << Acc/binary, $c >>); - $D -> parse_host(Rest, << Acc/binary, $d >>); - $E -> parse_host(Rest, << Acc/binary, $e >>); - $F -> parse_host(Rest, << Acc/binary, $f >>); - $G -> parse_host(Rest, << Acc/binary, $g >>); - $H -> parse_host(Rest, << Acc/binary, $h >>); - $I -> parse_host(Rest, << Acc/binary, $i >>); - $J -> parse_host(Rest, << Acc/binary, $j >>); - $K -> parse_host(Rest, << Acc/binary, $k >>); - $L -> parse_host(Rest, << Acc/binary, $l >>); - $M -> parse_host(Rest, << Acc/binary, $m >>); - $N -> parse_host(Rest, << Acc/binary, $n >>); - $O -> parse_host(Rest, << Acc/binary, $o >>); - $P -> parse_host(Rest, << Acc/binary, $p >>); - $Q -> parse_host(Rest, << Acc/binary, $q >>); - $R -> parse_host(Rest, << Acc/binary, $r >>); - $S -> parse_host(Rest, << Acc/binary, $s >>); - $T -> parse_host(Rest, << Acc/binary, $t >>); - $U -> parse_host(Rest, << Acc/binary, $u >>); - $V -> parse_host(Rest, << Acc/binary, $v >>); - $W -> parse_host(Rest, << Acc/binary, $w >>); - $X -> parse_host(Rest, << Acc/binary, $x >>); - $Y -> parse_host(Rest, << Acc/binary, $y >>); - $Z -> parse_host(Rest, << Acc/binary, $z >>); - _ -> parse_host(Rest, << Acc/binary, C >>) + $A -> parse_host(Rest, E, << Acc/binary, $a >>); + $B -> parse_host(Rest, E, << Acc/binary, $b >>); + $C -> parse_host(Rest, E, << Acc/binary, $c >>); + $D -> parse_host(Rest, E, << Acc/binary, $d >>); + $E -> parse_host(Rest, E, << Acc/binary, $e >>); + $F -> parse_host(Rest, E, << Acc/binary, $f >>); + $G -> parse_host(Rest, E, << Acc/binary, $g >>); + $H -> parse_host(Rest, E, << Acc/binary, $h >>); + $I -> parse_host(Rest, E, << Acc/binary, $i >>); + $J -> parse_host(Rest, E, << Acc/binary, $j >>); + $K -> parse_host(Rest, E, << Acc/binary, $k >>); + $L -> parse_host(Rest, E, << Acc/binary, $l >>); + $M -> parse_host(Rest, E, << Acc/binary, $m >>); + $N -> parse_host(Rest, E, << Acc/binary, $n >>); + $O -> parse_host(Rest, E, << Acc/binary, $o >>); + $P -> parse_host(Rest, E, << Acc/binary, $p >>); + $Q -> parse_host(Rest, E, << Acc/binary, $q >>); + $R -> parse_host(Rest, E, << Acc/binary, $r >>); + $S -> parse_host(Rest, E, << Acc/binary, $s >>); + $T -> parse_host(Rest, E, << Acc/binary, $t >>); + $U -> parse_host(Rest, E, << Acc/binary, $u >>); + $V -> parse_host(Rest, E, << Acc/binary, $v >>); + $W -> parse_host(Rest, E, << Acc/binary, $w >>); + $X -> parse_host(Rest, E, << Acc/binary, $x >>); + $Y -> parse_host(Rest, E, << Acc/binary, $y >>); + $Z -> parse_host(Rest, E, << Acc/binary, $z >>); + _ -> parse_host(Rest, E, << Acc/binary, C >>) end. %% End of request parsing. @@ -589,3 +593,24 @@ error_terminate(Status, Req, State) -> terminate(#state{socket=Socket, transport=Transport}) -> Transport:close(Socket), ok. + +%% Tests. + +-ifdef(TEST). + +parse_host(RawHost) -> + parse_host(RawHost, false, <<>>). + +parse_host_test() -> + {<<"example.org">>, 8080} = parse_host(<<"example.org:8080">>), + {<<"example.org">>, undefined} = parse_host(<<"example.org">>), + {<<"192.0.2.1">>, 8080} = parse_host(<<"192.0.2.1:8080">>), + {<<"192.0.2.1">>, undefined} = parse_host(<<"192.0.2.1">>), + {<<"[2001:db8::1]">>, 8080} = parse_host(<<"[2001:db8::1]:8080">>), + {<<"[2001:db8::1]">>, undefined} = parse_host(<<"[2001:db8::1]">>), + {<<"[::ffff:192.0.2.1]">>, 8080} = + parse_host(<<"[::ffff:192.0.2.1]:8080">>), + {<<"[::ffff:192.0.2.1]">>, undefined} = + parse_host(<<"[::ffff:192.0.2.1]">>). + +-endif. |