mirror of
https://github.com/ninenines/cowboy.git
synced 2025-07-14 12:20:24 +00:00
Run the dispatcher as early as possible to quickly dismiss 404 errors.
This commit is contained in:
parent
da72255940
commit
786a05a129
1 changed files with 19 additions and 17 deletions
|
@ -23,6 +23,7 @@
|
||||||
socket :: socket(),
|
socket :: socket(),
|
||||||
transport :: module(),
|
transport :: module(),
|
||||||
dispatch :: dispatch(),
|
dispatch :: dispatch(),
|
||||||
|
handler :: {Handler::module(), Opts::term()},
|
||||||
timeout :: timeout(),
|
timeout :: timeout(),
|
||||||
connection = keepalive :: keepalive | close
|
connection = keepalive :: keepalive | close
|
||||||
}).
|
}).
|
||||||
|
@ -81,12 +82,19 @@ wait_header(Req, State=#state{socket=Socket,
|
||||||
|
|
||||||
-spec header({http_header, I::integer(), Field::http_header(), R::term(),
|
-spec header({http_header, I::integer(), Field::http_header(), R::term(),
|
||||||
Value::string()} | http_eoh, Req::#http_req{}, State::#state{}) -> ok.
|
Value::string()} | http_eoh, Req::#http_req{}, State::#state{}) -> ok.
|
||||||
header({http_header, _I, 'Host', _R, Value}, Req, State) ->
|
header({http_header, _I, 'Host', _R, Value}, Req=#http_req{path=Path},
|
||||||
|
State=#state{dispatch=Dispatch}) ->
|
||||||
Host = cowboy_dispatcher:split_host(Value),
|
Host = cowboy_dispatcher:split_host(Value),
|
||||||
%% @todo We have Host and Path at this point, dispatch right away and
|
%% @todo We probably want to filter the Host and Path here to allow
|
||||||
%% error_terminate(404) early if it fails.
|
%% things like url rewriting.
|
||||||
wait_header(Req#http_req{host=Host,
|
case cowboy_dispatcher:match(Host, Path, Dispatch) of
|
||||||
headers=[{'Host', Value}|Req#http_req.headers]}, State);
|
{ok, Handler, Opts, Binds} ->
|
||||||
|
wait_header(Req#http_req{host=Host, bindings=Binds,
|
||||||
|
headers=[{'Host', Value}|Req#http_req.headers]},
|
||||||
|
State#state{handler={Handler, Opts}});
|
||||||
|
{error, notfound} ->
|
||||||
|
error_terminate(404, State)
|
||||||
|
end;
|
||||||
header({http_header, _I, 'Connection', _R, Connection}, Req, State) ->
|
header({http_header, _I, 'Connection', _R, Connection}, Req, State) ->
|
||||||
wait_header(Req#http_req{
|
wait_header(Req#http_req{
|
||||||
headers=[{'Connection', Connection}|Req#http_req.headers]},
|
headers=[{'Connection', Connection}|Req#http_req.headers]},
|
||||||
|
@ -97,22 +105,16 @@ header({http_header, _I, Field, _R, Value}, Req, State) ->
|
||||||
%% The Host header is required.
|
%% The Host header is required.
|
||||||
header(http_eoh, #http_req{host=undefined}, State) ->
|
header(http_eoh, #http_req{host=undefined}, State) ->
|
||||||
error_terminate(400, State);
|
error_terminate(400, State);
|
||||||
header(http_eoh, Req=#http_req{host=Host, path=Path},
|
header(http_eoh, Req, State) ->
|
||||||
State=#state{dispatch=Dispatch}) ->
|
handler_loop(Req, State).
|
||||||
%% @todo We probably want to filter the Host and Patch here to allow
|
|
||||||
%% things like url rewriting.
|
|
||||||
dispatch(cowboy_dispatcher:match(Host, Path, Dispatch), Req, State).
|
|
||||||
|
|
||||||
-spec dispatch({ok, Handler::module(), Opts::term(), Binds::bindings()}
|
-spec handler_loop(Req::#http_req{}, State::#state{}) -> ok.
|
||||||
| {error, notfound}, Req::#http_req{}, State::#state{}) -> ok.
|
handler_loop(Req, State=#state{handler={Handler, Opts}}) ->
|
||||||
dispatch({ok, Handler, Opts, Binds}, Req, State) ->
|
case Handler:handle(Opts, Req) of
|
||||||
case Handler:handle(Opts, Req#http_req{bindings=Binds}) of
|
|
||||||
{reply, RCode, RHeaders, RBody} ->
|
{reply, RCode, RHeaders, RBody} ->
|
||||||
reply(RCode, RHeaders, RBody, State)
|
reply(RCode, RHeaders, RBody, State)
|
||||||
%% @todo stream_reply, request_body, stream_request_body...
|
%% @todo stream_reply, request_body, stream_request_body...
|
||||||
end;
|
end.
|
||||||
dispatch({error, notfound}, _Req, State) ->
|
|
||||||
error_terminate(404, State).
|
|
||||||
|
|
||||||
-spec error_terminate(Code::http_status(), State::#state{}) -> ok.
|
-spec error_terminate(Code::http_status(), State::#state{}) -> ok.
|
||||||
error_terminate(Code, State) ->
|
error_terminate(Code, State) ->
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue