mirror of
https://github.com/ninenines/cowboy.git
synced 2025-07-14 12:20:24 +00:00
Add cowboy_req:url/1 to return the full request URL
Use it in cowboy_websocket for hixie76, replacing http by ws.
This commit is contained in:
parent
cd54214def
commit
27d591180c
2 changed files with 59 additions and 52 deletions
|
@ -35,6 +35,7 @@
|
||||||
-export([qs_val/3]).
|
-export([qs_val/3]).
|
||||||
-export([qs_vals/1]).
|
-export([qs_vals/1]).
|
||||||
-export([raw_qs/1]).
|
-export([raw_qs/1]).
|
||||||
|
-export([url/1]).
|
||||||
-export([binding/2]).
|
-export([binding/2]).
|
||||||
-export([binding/3]).
|
-export([binding/3]).
|
||||||
-export([bindings/1]).
|
-export([bindings/1]).
|
||||||
|
@ -82,6 +83,7 @@
|
||||||
-export([transport/1]).
|
-export([transport/1]).
|
||||||
|
|
||||||
-include("http.hrl").
|
-include("http.hrl").
|
||||||
|
-include_lib("eunit/include/eunit.hrl").
|
||||||
|
|
||||||
-type req() :: #http_req{}.
|
-type req() :: #http_req{}.
|
||||||
-export_type([req/0]).
|
-export_type([req/0]).
|
||||||
|
@ -195,6 +197,29 @@ qs_vals(Req=#http_req{qs_vals=QsVals}) ->
|
||||||
raw_qs(Req) ->
|
raw_qs(Req) ->
|
||||||
{Req#http_req.raw_qs, Req}.
|
{Req#http_req.raw_qs, Req}.
|
||||||
|
|
||||||
|
%% @doc Return the full request URL as a binary.
|
||||||
|
%%
|
||||||
|
%% The URL includes the scheme, host, port, path and query string.
|
||||||
|
-spec url(Req) -> {binary(), Req} when Req::req().
|
||||||
|
url(Req=#http_req{transport=Transport, host=Host, port=Port,
|
||||||
|
path=Path, raw_qs=QS}) ->
|
||||||
|
TransportName = Transport:name(),
|
||||||
|
Secure = case TransportName of
|
||||||
|
ssl -> <<"s">>;
|
||||||
|
_ -> <<>>
|
||||||
|
end,
|
||||||
|
PortBin = case {TransportName, Port} of
|
||||||
|
{ssl, 443} -> <<>>;
|
||||||
|
{tcp, 80} -> <<>>;
|
||||||
|
_ -> << ":", (list_to_binary(integer_to_list(Port)))/binary >>
|
||||||
|
end,
|
||||||
|
QS2 = case QS of
|
||||||
|
<<>> -> <<>>;
|
||||||
|
_ -> << "?", QS/binary >>
|
||||||
|
end,
|
||||||
|
{<< "http", Secure/binary, "://", Host/binary, PortBin/binary,
|
||||||
|
Path/binary, QS2/binary >>, Req}.
|
||||||
|
|
||||||
%% @equiv binding(Name, Req, undefined)
|
%% @equiv binding(Name, Req, undefined)
|
||||||
-spec binding(atom(), Req) -> {binary() | undefined, Req} when Req::req().
|
-spec binding(atom(), Req) -> {binary() | undefined, Req} when Req::req().
|
||||||
binding(Name, Req) when is_atom(Name) ->
|
binding(Name, Req) when is_atom(Name) ->
|
||||||
|
@ -1026,3 +1051,33 @@ header_to_binary('Cookie') -> <<"Cookie">>;
|
||||||
header_to_binary('Keep-Alive') -> <<"Keep-Alive">>;
|
header_to_binary('Keep-Alive') -> <<"Keep-Alive">>;
|
||||||
header_to_binary('Proxy-Connection') -> <<"Proxy-Connection">>;
|
header_to_binary('Proxy-Connection') -> <<"Proxy-Connection">>;
|
||||||
header_to_binary(B) when is_binary(B) -> B.
|
header_to_binary(B) when is_binary(B) -> B.
|
||||||
|
|
||||||
|
%% Tests.
|
||||||
|
|
||||||
|
-ifdef(TEST).
|
||||||
|
|
||||||
|
url_test() ->
|
||||||
|
{<<"http://localhost/path">>, _ } =
|
||||||
|
url(#http_req{transport=ranch_tcp, host= <<"localhost">>, port=80,
|
||||||
|
path= <<"/path">>, raw_qs= <<>>, pid=self()}),
|
||||||
|
{<<"http://localhost:443/path">>, _} =
|
||||||
|
url(#http_req{transport=ranch_tcp, host= <<"localhost">>, port=443,
|
||||||
|
path= <<"/path">>, raw_qs= <<>>, pid=self()}),
|
||||||
|
{<<"http://localhost:8080/path">>, _} =
|
||||||
|
url(#http_req{transport=ranch_tcp, host= <<"localhost">>, port=8080,
|
||||||
|
path= <<"/path">>, raw_qs= <<>>, pid=self()}),
|
||||||
|
{<<"http://localhost:8080/path?dummy=2785">>, _} =
|
||||||
|
url(#http_req{transport=ranch_tcp, host= <<"localhost">>, port=8080,
|
||||||
|
path= <<"/path">>, raw_qs= <<"dummy=2785">>, pid=self()}),
|
||||||
|
{<<"https://localhost/path">>, _} =
|
||||||
|
url(#http_req{transport=ranch_ssl, host= <<"localhost">>, port=443,
|
||||||
|
path= <<"/path">>, raw_qs= <<>>, pid=self()}),
|
||||||
|
{<<"https://localhost:8443/path">>, _} =
|
||||||
|
url(#http_req{transport=ranch_ssl, host= <<"localhost">>, port=8443,
|
||||||
|
path= <<"/path">>, raw_qs= <<>>, pid=self()}),
|
||||||
|
{<<"https://localhost:8443/path?dummy=2785">>, _} =
|
||||||
|
url(#http_req{transport=ranch_ssl, host= <<"localhost">>, port=8443,
|
||||||
|
path= <<"/path">>, raw_qs= <<"dummy=2785">>, pid=self()}),
|
||||||
|
ok.
|
||||||
|
|
||||||
|
-endif.
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
-export([handler_loop/4]).
|
-export([handler_loop/4]).
|
||||||
|
|
||||||
-include("http.hrl").
|
-include("http.hrl").
|
||||||
-include_lib("eunit/include/eunit.hrl").
|
|
||||||
|
|
||||||
-type opcode() :: 0 | 1 | 2 | 8 | 9 | 10.
|
-type opcode() :: 0 | 1 | 2 | 8 | 9 | 10.
|
||||||
-type mask_key() :: 0..16#ffffffff.
|
-type mask_key() :: 0..16#ffffffff.
|
||||||
|
@ -164,15 +163,14 @@ upgrade_denied(#http_req{socket=Socket, transport=Transport,
|
||||||
-spec websocket_handshake(#state{}, cowboy_req:req(), any()) -> closed.
|
-spec websocket_handshake(#state{}, cowboy_req:req(), any()) -> closed.
|
||||||
websocket_handshake(State=#state{socket=Socket, transport=Transport,
|
websocket_handshake(State=#state{socket=Socket, transport=Transport,
|
||||||
version=0, origin=Origin, challenge={Key1, Key2}},
|
version=0, origin=Origin, challenge={Key1, Key2}},
|
||||||
Req=#http_req{host=Host, port=Port, path=Path, raw_qs=QS},
|
Req, HandlerState) ->
|
||||||
HandlerState) ->
|
{<< "http", Location/binary >>, Req1} = cowboy_req:url(Req),
|
||||||
Location = hixie76_location(Transport:name(), Host, Port, Path, QS),
|
|
||||||
{ok, Req2} = cowboy_req:upgrade_reply(
|
{ok, Req2} = cowboy_req:upgrade_reply(
|
||||||
<<"101 WebSocket Protocol Handshake">>,
|
<<"101 WebSocket Protocol Handshake">>,
|
||||||
[{<<"Upgrade">>, <<"WebSocket">>},
|
[{<<"Upgrade">>, <<"WebSocket">>},
|
||||||
{<<"Sec-Websocket-Location">>, Location},
|
{<<"Sec-Websocket-Location">>, << "ws", Location/binary >>},
|
||||||
{<<"Sec-Websocket-Origin">>, Origin}],
|
{<<"Sec-Websocket-Origin">>, Origin}],
|
||||||
Req),
|
Req1),
|
||||||
%% Flush the resp_sent message before moving on.
|
%% Flush the resp_sent message before moving on.
|
||||||
receive {cowboy_req, resp_sent} -> ok after 0 -> ok end,
|
receive {cowboy_req, resp_sent} -> ok after 0 -> ok end,
|
||||||
%% We replied with a proper response. Proxies should be happy enough,
|
%% We replied with a proper response. Proxies should be happy enough,
|
||||||
|
@ -554,29 +552,6 @@ hixie76_key_to_integer(Key) ->
|
||||||
Spaces = length([C || << C >> <= Key, C =:= 32]),
|
Spaces = length([C || << C >> <= Key, C =:= 32]),
|
||||||
Number div Spaces.
|
Number div Spaces.
|
||||||
|
|
||||||
-spec hixie76_location(atom(), binary(), inet:port_number(),
|
|
||||||
binary(), binary()) -> binary().
|
|
||||||
hixie76_location(Protocol, Host, Port, Path, <<>>) ->
|
|
||||||
<< (hixie76_location_protocol(Protocol))/binary, "://", Host/binary,
|
|
||||||
(hixie76_location_port(Protocol, Port))/binary, Path/binary>>;
|
|
||||||
hixie76_location(Protocol, Host, Port, Path, QS) ->
|
|
||||||
<< (hixie76_location_protocol(Protocol))/binary, "://", Host/binary,
|
|
||||||
(hixie76_location_port(Protocol, Port))/binary, Path/binary, "?", QS/binary >>.
|
|
||||||
|
|
||||||
-spec hixie76_location_protocol(atom()) -> binary().
|
|
||||||
hixie76_location_protocol(ssl) -> <<"wss">>;
|
|
||||||
hixie76_location_protocol(_) -> <<"ws">>.
|
|
||||||
|
|
||||||
%% @todo We should add a secure/0 function to transports
|
|
||||||
%% instead of relying on their name.
|
|
||||||
-spec hixie76_location_port(atom(), inet:port_number()) -> binary().
|
|
||||||
hixie76_location_port(ssl, 443) ->
|
|
||||||
<<>>;
|
|
||||||
hixie76_location_port(tcp, 80) ->
|
|
||||||
<<>>;
|
|
||||||
hixie76_location_port(_, Port) ->
|
|
||||||
<<":", (list_to_binary(integer_to_list(Port)))/binary>>.
|
|
||||||
|
|
||||||
%% hybi specific.
|
%% hybi specific.
|
||||||
|
|
||||||
-spec hybi_challenge(binary()) -> binary().
|
-spec hybi_challenge(binary()) -> binary().
|
||||||
|
@ -592,26 +567,3 @@ hybi_payload_length(N) ->
|
||||||
N when N =< 16#ffff -> << 126:7, N:16 >>;
|
N when N =< 16#ffff -> << 126:7, N:16 >>;
|
||||||
N when N =< 16#7fffffffffffffff -> << 127:7, N:64 >>
|
N when N =< 16#7fffffffffffffff -> << 127:7, N:64 >>
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% Tests.
|
|
||||||
|
|
||||||
-ifdef(TEST).
|
|
||||||
|
|
||||||
hixie76_location_test() ->
|
|
||||||
?assertEqual(<<"ws://localhost/path">>,
|
|
||||||
hixie76_location(tcp, <<"localhost">>, 80, <<"/path">>, <<>>)),
|
|
||||||
?assertEqual(<<"ws://localhost:443/path">>,
|
|
||||||
hixie76_location(tcp, <<"localhost">>, 443, <<"/path">>, <<>>)),
|
|
||||||
?assertEqual(<<"ws://localhost:8080/path">>,
|
|
||||||
hixie76_location(tcp, <<"localhost">>, 8080, <<"/path">>, <<>>)),
|
|
||||||
?assertEqual(<<"ws://localhost:8080/path?dummy=2785">>,
|
|
||||||
hixie76_location(tcp, <<"localhost">>, 8080, <<"/path">>, <<"dummy=2785">>)),
|
|
||||||
?assertEqual(<<"wss://localhost/path">>,
|
|
||||||
hixie76_location(ssl, <<"localhost">>, 443, <<"/path">>, <<>>)),
|
|
||||||
?assertEqual(<<"wss://localhost:8443/path">>,
|
|
||||||
hixie76_location(ssl, <<"localhost">>, 8443, <<"/path">>, <<>>)),
|
|
||||||
?assertEqual(<<"wss://localhost:8443/path?dummy=2785">>,
|
|
||||||
hixie76_location(ssl, <<"localhost">>, 8443, <<"/path">>, <<"dummy=2785">>)),
|
|
||||||
ok.
|
|
||||||
|
|
||||||
-endif.
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue