2017-01-02 19:36:36 +01:00
|
|
|
%% Copyright (c) 2011-2017, Loïc Hoguin <essen@ninenines.eu>
|
2011-03-29 13:49:48 +02:00
|
|
|
%% Copyright (c) 2011, Anthony Ramine <nox@dev-extend.eu>
|
2011-03-07 22:59:22 +01:00
|
|
|
%%
|
|
|
|
%% Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
%% purpose with or without fee is hereby granted, provided that the above
|
|
|
|
%% copyright notice and this permission notice appear in all copies.
|
|
|
|
%%
|
|
|
|
%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
|
2012-08-27 13:28:57 +02:00
|
|
|
-module(cowboy_req).
|
2011-03-18 22:38:26 +01:00
|
|
|
|
2018-06-27 17:52:25 +02:00
|
|
|
-ifdef(OTP_RELEASE).
|
|
|
|
-compile({nowarn_deprecated_function, [{erlang, get_stacktrace, 0}]}).
|
|
|
|
-endif.
|
|
|
|
|
2016-08-10 11:49:31 +02:00
|
|
|
%% Request.
|
2012-08-27 12:16:07 +02:00
|
|
|
-export([method/1]).
|
|
|
|
-export([version/1]).
|
|
|
|
-export([peer/1]).
|
2017-10-25 20:17:21 +01:00
|
|
|
-export([sock/1]).
|
|
|
|
-export([cert/1]).
|
2016-06-20 17:29:53 +02:00
|
|
|
-export([scheme/1]).
|
2012-08-27 12:16:07 +02:00
|
|
|
-export([host/1]).
|
|
|
|
-export([host_info/1]).
|
|
|
|
-export([port/1]).
|
|
|
|
-export([path/1]).
|
|
|
|
-export([path_info/1]).
|
2012-09-17 11:46:45 +02:00
|
|
|
-export([qs/1]).
|
2014-09-23 16:43:29 +03:00
|
|
|
-export([parse_qs/1]).
|
|
|
|
-export([match_qs/2]).
|
2016-06-21 19:04:52 +02:00
|
|
|
-export([uri/1]).
|
|
|
|
-export([uri/2]).
|
2012-08-27 12:16:07 +02:00
|
|
|
-export([binding/2]).
|
|
|
|
-export([binding/3]).
|
|
|
|
-export([bindings/1]).
|
|
|
|
-export([header/2]).
|
|
|
|
-export([header/3]).
|
|
|
|
-export([headers/1]).
|
|
|
|
-export([parse_header/2]).
|
|
|
|
-export([parse_header/3]).
|
2014-09-23 16:43:29 +03:00
|
|
|
-export([parse_cookies/1]).
|
|
|
|
-export([match_cookies/2]).
|
2012-08-27 12:16:07 +02:00
|
|
|
|
2016-08-10 11:49:31 +02:00
|
|
|
%% Request body.
|
2012-08-27 12:16:07 +02:00
|
|
|
-export([has_body/1]).
|
|
|
|
-export([body_length/1]).
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
-export([read_body/1]).
|
|
|
|
-export([read_body/2]).
|
2016-08-10 11:49:31 +02:00
|
|
|
-export([read_urlencoded_body/1]).
|
|
|
|
-export([read_urlencoded_body/2]).
|
2018-09-07 13:56:12 +02:00
|
|
|
-export([read_and_match_urlencoded_body/2]).
|
|
|
|
-export([read_and_match_urlencoded_body/3]).
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
|
2016-08-10 11:49:31 +02:00
|
|
|
%% Multipart.
|
2016-08-10 15:09:04 +02:00
|
|
|
-export([read_part/1]).
|
|
|
|
-export([read_part/2]).
|
|
|
|
-export([read_part_body/1]).
|
|
|
|
-export([read_part_body/2]).
|
2014-02-06 19:36:25 +01:00
|
|
|
|
2016-08-10 11:49:31 +02:00
|
|
|
%% Response.
|
|
|
|
-export([set_resp_cookie/3]).
|
2012-08-27 12:16:07 +02:00
|
|
|
-export([set_resp_cookie/4]).
|
2016-11-13 15:39:40 +01:00
|
|
|
-export([resp_header/2]).
|
|
|
|
-export([resp_header/3]).
|
|
|
|
-export([resp_headers/1]).
|
2012-08-27 12:16:07 +02:00
|
|
|
-export([set_resp_header/3]).
|
2016-11-13 15:39:40 +01:00
|
|
|
-export([set_resp_headers/2]).
|
2012-08-27 12:16:07 +02:00
|
|
|
-export([has_resp_header/2]).
|
2012-09-16 01:55:40 +02:00
|
|
|
-export([delete_resp_header/2]).
|
2017-01-02 16:47:16 +01:00
|
|
|
-export([set_resp_body/2]).
|
2016-08-10 11:52:41 +02:00
|
|
|
%% @todo set_resp_body/3 with a ContentType or even Headers argument, to set content headers.
|
2016-08-10 11:49:31 +02:00
|
|
|
-export([has_resp_body/1]).
|
2017-10-29 19:52:27 +00:00
|
|
|
-export([inform/2]).
|
|
|
|
-export([inform/3]).
|
2012-08-27 12:16:07 +02:00
|
|
|
-export([reply/2]).
|
|
|
|
-export([reply/3]).
|
|
|
|
-export([reply/4]).
|
2016-08-10 11:49:31 +02:00
|
|
|
-export([stream_reply/2]).
|
|
|
|
-export([stream_reply/3]).
|
2017-02-05 20:45:36 +01:00
|
|
|
%% @todo stream_body/2 (nofin)
|
2016-08-10 11:49:31 +02:00
|
|
|
-export([stream_body/3]).
|
2018-06-25 15:56:29 +02:00
|
|
|
%% @todo stream_events/2 (nofin)
|
|
|
|
-export([stream_events/3]).
|
2017-11-15 14:58:49 +01:00
|
|
|
-export([stream_trailers/2]).
|
2016-08-10 11:49:31 +02:00
|
|
|
-export([push/3]).
|
|
|
|
-export([push/4]).
|
2012-08-27 12:16:07 +02:00
|
|
|
|
2016-08-12 17:01:01 +02:00
|
|
|
%% Internal.
|
|
|
|
-export([response_headers/2]).
|
2012-08-27 12:16:07 +02:00
|
|
|
|
2017-01-02 16:47:16 +01:00
|
|
|
%% @todo Get rid of this type, use cow_cookie directly.
|
|
|
|
-type cookie_opts() :: map().
|
2012-12-07 14:54:45 +01:00
|
|
|
-export_type([cookie_opts/0]).
|
|
|
|
|
2017-01-02 16:47:16 +01:00
|
|
|
-type read_body_opts() :: #{
|
2017-07-10 14:02:54 -07:00
|
|
|
length => non_neg_integer() | infinity,
|
2016-08-10 11:49:31 +02:00
|
|
|
period => non_neg_integer(),
|
|
|
|
timeout => timeout()
|
|
|
|
}.
|
2017-01-02 16:47:16 +01:00
|
|
|
-export_type([read_body_opts/0]).
|
Add request body reading options
The options were added to allow developers to fix timeout
issues when reading large bodies. It is also a cleaner and
easier to extend interface.
This commit deprecates the functions init_stream, stream_body
and skip_body which are no longer needed. They will be removed
in 1.0.
The body function can now take an additional argument that is a
list of options. The body_qs, part and part_body functions can
too and simply pass this argument down to the body call.
There are options for disabling the automatic continue reply,
setting a maximum length to be returned (soft limit), setting
the read length and read timeout, and setting the transfer and
content decode functions.
The return value of the body and body_qs have changed slightly.
The body function now works similarly to the part_body function,
in that it returns either an ok or a more tuple depending on
whether there is additional data to be read. The body_qs function
can return a badlength tuple if the body is too big. The default
size has been increased from 16KB to 64KB.
The default read length and timeout have been tweaked and vary
depending on the function called.
The body function will now adequately process chunked bodies,
which means that the body_qs function will too. But this means
that the behavior has changed slightly and your code should be
tested properly when updating your code.
The body and body_qs still accept a length as first argument
for compatibility purpose with older code. Note that this form
is deprecated and will be removed in 1.0. The part and part_body
function, being new and never having been in a release yet, have
this form completely removed in this commit.
Again, while most code should work as-is, you should make sure
that it actually does before pushing this to production.
2014-06-02 23:09:43 +02:00
|
|
|
|
2016-08-10 11:49:31 +02:00
|
|
|
%% While sendfile allows a Len of 0 that means "everything past Offset",
|
|
|
|
%% Cowboy expects the real length as it is used as metadata.
|
|
|
|
%% @todo We should probably explicitly reject it.
|
|
|
|
-type resp_body() :: iodata()
|
2017-09-04 20:48:07 +02:00
|
|
|
| {sendfile, non_neg_integer(), non_neg_integer(), file:name_all()}.
|
2016-08-10 11:49:31 +02:00
|
|
|
-export_type([resp_body/0]).
|
|
|
|
|
2017-01-02 16:47:16 +01:00
|
|
|
-type push_opts() :: #{
|
|
|
|
method => binary(),
|
|
|
|
scheme => binary(),
|
|
|
|
host => binary(),
|
2018-05-16 10:42:25 +02:00
|
|
|
port => inet:port_number(),
|
2017-01-02 16:47:16 +01:00
|
|
|
qs => binary()
|
|
|
|
}.
|
2016-08-10 17:52:44 +02:00
|
|
|
-export_type([push_opts/0]).
|
|
|
|
|
2018-10-31 11:45:04 +01:00
|
|
|
-type req() :: #{
|
|
|
|
%% Public interface.
|
|
|
|
method := binary(),
|
|
|
|
version := cowboy:http_version() | atom(),
|
|
|
|
scheme := binary(),
|
|
|
|
host := binary(),
|
|
|
|
port := inet:port_number(),
|
|
|
|
path := binary(),
|
|
|
|
qs := binary(),
|
|
|
|
headers := cowboy:http_headers(),
|
|
|
|
peer := {inet:ip_address(), inet:port_number()},
|
|
|
|
sock := {inet:ip_address(), inet:port_number()},
|
|
|
|
cert := binary() | undefined,
|
|
|
|
|
|
|
|
%% Private interface.
|
|
|
|
ref := ranch:ref(),
|
|
|
|
pid := pid(),
|
|
|
|
streamid := cowboy_stream:streamid(),
|
|
|
|
|
|
|
|
host_info => cowboy_router:tokens(),
|
|
|
|
path_info => cowboy_router:tokens(),
|
|
|
|
bindings => cowboy_router:bindings(),
|
|
|
|
|
|
|
|
has_body := boolean(),
|
|
|
|
body_length := non_neg_integer() | undefined,
|
|
|
|
has_read_body => true,
|
|
|
|
multipart => {binary(), binary()} | done,
|
|
|
|
|
|
|
|
has_sent_resp => headers | true,
|
|
|
|
resp_cookies => #{iodata() => iodata()},
|
|
|
|
resp_headers => #{binary() => iodata()},
|
|
|
|
resp_body => resp_body(),
|
|
|
|
|
|
|
|
proxy_header => ranch_proxy_header:proxy_info(),
|
|
|
|
media_type => {binary(), binary(), [{binary(), binary()}]},
|
|
|
|
language => binary() | undefined,
|
|
|
|
charset => binary() | undefined,
|
2018-11-07 18:55:06 +01:00
|
|
|
range => {binary(), binary()
|
|
|
|
| [{non_neg_integer(), non_neg_integer() | infinity} | neg_integer()]},
|
2018-10-31 11:45:04 +01:00
|
|
|
websocket_version => 7 | 8 | 13
|
|
|
|
}.
|
2012-08-27 14:27:41 +02:00
|
|
|
-export_type([req/0]).
|
|
|
|
|
2016-08-10 11:49:31 +02:00
|
|
|
%% Request.
|
2011-03-07 22:59:22 +01:00
|
|
|
|
2014-09-23 16:43:29 +03:00
|
|
|
-spec method(req()) -> binary().
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
method(#{method := Method}) ->
|
|
|
|
Method.
|
2011-03-07 22:59:22 +01:00
|
|
|
|
2014-09-23 16:43:29 +03:00
|
|
|
-spec version(req()) -> cowboy:http_version().
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
version(#{version := Version}) ->
|
|
|
|
Version.
|
2011-03-07 22:59:22 +01:00
|
|
|
|
2016-06-20 17:28:59 +02:00
|
|
|
-spec peer(req()) -> {inet:ip_address(), inet:port_number()}.
|
|
|
|
peer(#{peer := Peer}) ->
|
|
|
|
Peer.
|
2011-03-07 22:59:22 +01:00
|
|
|
|
2017-10-25 20:17:21 +01:00
|
|
|
-spec sock(req()) -> {inet:ip_address(), inet:port_number()}.
|
|
|
|
sock(#{sock := Sock}) ->
|
|
|
|
Sock.
|
|
|
|
|
|
|
|
-spec cert(req()) -> binary() | undefined.
|
|
|
|
cert(#{cert := Cert}) ->
|
|
|
|
Cert.
|
|
|
|
|
2016-06-20 17:29:53 +02:00
|
|
|
-spec scheme(req()) -> binary().
|
|
|
|
scheme(#{scheme := Scheme}) ->
|
|
|
|
Scheme.
|
|
|
|
|
2014-09-23 16:43:29 +03:00
|
|
|
-spec host(req()) -> binary().
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
host(#{host := Host}) ->
|
|
|
|
Host.
|
2011-03-07 22:59:22 +01:00
|
|
|
|
2016-08-10 11:52:41 +02:00
|
|
|
%% @todo The host_info is undefined if cowboy_router isn't used. Do we want to crash?
|
2014-09-23 16:43:29 +03:00
|
|
|
-spec host_info(req()) -> cowboy_router:tokens() | undefined.
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
host_info(#{host_info := HostInfo}) ->
|
|
|
|
HostInfo.
|
2011-05-09 14:31:06 +02:00
|
|
|
|
2014-09-23 16:43:29 +03:00
|
|
|
-spec port(req()) -> inet:port_number().
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
port(#{port := Port}) ->
|
|
|
|
Port.
|
2011-05-04 12:05:57 +02:00
|
|
|
|
2014-09-23 16:43:29 +03:00
|
|
|
-spec path(req()) -> binary().
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
path(#{path := Path}) ->
|
|
|
|
Path.
|
2011-03-07 22:59:22 +01:00
|
|
|
|
2016-08-10 11:52:41 +02:00
|
|
|
%% @todo The path_info is undefined if cowboy_router isn't used. Do we want to crash?
|
2014-09-23 16:43:29 +03:00
|
|
|
-spec path_info(req()) -> cowboy_router:tokens() | undefined.
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
path_info(#{path_info := PathInfo}) ->
|
|
|
|
PathInfo.
|
2011-05-09 14:31:06 +02:00
|
|
|
|
2014-09-23 16:43:29 +03:00
|
|
|
-spec qs(req()) -> binary().
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
qs(#{qs := Qs}) ->
|
|
|
|
Qs.
|
2014-09-23 16:43:29 +03:00
|
|
|
|
2016-08-10 11:52:41 +02:00
|
|
|
%% @todo Might be useful to limit the number of keys.
|
2014-09-23 16:43:29 +03:00
|
|
|
-spec parse_qs(req()) -> [{binary(), binary() | true}].
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
parse_qs(#{qs := Qs}) ->
|
2017-09-14 13:42:17 +02:00
|
|
|
try
|
|
|
|
cow_qs:parse_qs(Qs)
|
|
|
|
catch _:_ ->
|
|
|
|
erlang:raise(exit, {request_error, qs,
|
|
|
|
'Malformed query string; application/x-www-form-urlencoded expected.'
|
|
|
|
}, erlang:get_stacktrace())
|
|
|
|
end.
|
2011-03-07 22:59:22 +01:00
|
|
|
|
2014-10-04 13:21:16 +03:00
|
|
|
-spec match_qs(cowboy:fields(), req()) -> map().
|
|
|
|
match_qs(Fields, Req) ->
|
2017-09-27 16:20:38 +02:00
|
|
|
case filter(Fields, kvlist_to_map(Fields, parse_qs(Req))) of
|
|
|
|
{ok, Map} ->
|
|
|
|
Map;
|
|
|
|
{error, Errors} ->
|
|
|
|
exit({request_error, {match_qs, Errors},
|
|
|
|
'Query string validation constraints failed for the reasons provided.'})
|
|
|
|
end.
|
2011-03-07 22:59:22 +01:00
|
|
|
|
2016-06-21 19:04:52 +02:00
|
|
|
-spec uri(req()) -> iodata().
|
|
|
|
uri(Req) ->
|
|
|
|
uri(Req, #{}).
|
|
|
|
|
|
|
|
-spec uri(req(), map()) -> iodata().
|
|
|
|
uri(#{scheme := Scheme0, host := Host0, port := Port0,
|
|
|
|
path := Path0, qs := Qs0}, Opts) ->
|
|
|
|
Scheme = case maps:get(scheme, Opts, Scheme0) of
|
|
|
|
S = undefined -> S;
|
|
|
|
S -> iolist_to_binary(S)
|
2012-09-15 22:03:00 +02:00
|
|
|
end,
|
2016-06-21 19:04:52 +02:00
|
|
|
Host = maps:get(host, Opts, Host0),
|
|
|
|
Port = maps:get(port, Opts, Port0),
|
2017-12-06 14:05:30 +01:00
|
|
|
{Path, Qs} = case maps:get(path, Opts, Path0) of
|
|
|
|
<<"*">> -> {<<>>, <<>>};
|
|
|
|
P -> {P, maps:get(qs, Opts, Qs0)}
|
|
|
|
end,
|
2016-06-21 19:04:52 +02:00
|
|
|
Fragment = maps:get(fragment, Opts, undefined),
|
|
|
|
[uri_host(Scheme, Scheme0, Port, Host), uri_path(Path), uri_qs(Qs), uri_fragment(Fragment)].
|
|
|
|
|
|
|
|
uri_host(_, _, _, undefined) -> <<>>;
|
|
|
|
uri_host(Scheme, Scheme0, Port, Host) ->
|
|
|
|
case iolist_size(Host) of
|
|
|
|
0 -> <<>>;
|
|
|
|
_ -> [uri_scheme(Scheme), <<"//">>, Host, uri_port(Scheme, Scheme0, Port)]
|
|
|
|
end.
|
|
|
|
|
|
|
|
uri_scheme(undefined) -> <<>>;
|
|
|
|
uri_scheme(Scheme) ->
|
|
|
|
case iolist_size(Scheme) of
|
|
|
|
0 -> Scheme;
|
|
|
|
_ -> [Scheme, $:]
|
|
|
|
end.
|
|
|
|
|
|
|
|
uri_port(_, _, undefined) -> <<>>;
|
|
|
|
uri_port(undefined, <<"http">>, 80) -> <<>>;
|
|
|
|
uri_port(undefined, <<"https">>, 443) -> <<>>;
|
|
|
|
uri_port(<<"http">>, _, 80) -> <<>>;
|
|
|
|
uri_port(<<"https">>, _, 443) -> <<>>;
|
|
|
|
uri_port(_, _, Port) ->
|
|
|
|
[$:, integer_to_binary(Port)].
|
|
|
|
|
|
|
|
uri_path(undefined) -> <<>>;
|
|
|
|
uri_path(Path) -> Path.
|
|
|
|
|
|
|
|
uri_qs(undefined) -> <<>>;
|
|
|
|
uri_qs(Qs) ->
|
|
|
|
case iolist_size(Qs) of
|
|
|
|
0 -> Qs;
|
|
|
|
_ -> [$?, Qs]
|
|
|
|
end.
|
|
|
|
|
|
|
|
uri_fragment(undefined) -> <<>>;
|
|
|
|
uri_fragment(Fragment) ->
|
|
|
|
case iolist_size(Fragment) of
|
|
|
|
0 -> Fragment;
|
|
|
|
_ -> [$#, Fragment]
|
|
|
|
end.
|
|
|
|
|
|
|
|
-ifdef(TEST).
|
|
|
|
uri1_test() ->
|
|
|
|
<<"http://localhost/path">> = iolist_to_binary(uri(#{
|
|
|
|
scheme => <<"http">>, host => <<"localhost">>, port => 80,
|
|
|
|
path => <<"/path">>, qs => <<>>})),
|
|
|
|
<<"http://localhost:443/path">> = iolist_to_binary(uri(#{
|
|
|
|
scheme => <<"http">>, host => <<"localhost">>, port => 443,
|
|
|
|
path => <<"/path">>, qs => <<>>})),
|
|
|
|
<<"http://localhost:8080/path">> = iolist_to_binary(uri(#{
|
|
|
|
scheme => <<"http">>, host => <<"localhost">>, port => 8080,
|
|
|
|
path => <<"/path">>, qs => <<>>})),
|
|
|
|
<<"http://localhost:8080/path?dummy=2785">> = iolist_to_binary(uri(#{
|
|
|
|
scheme => <<"http">>, host => <<"localhost">>, port => 8080,
|
|
|
|
path => <<"/path">>, qs => <<"dummy=2785">>})),
|
|
|
|
<<"https://localhost/path">> = iolist_to_binary(uri(#{
|
|
|
|
scheme => <<"https">>, host => <<"localhost">>, port => 443,
|
|
|
|
path => <<"/path">>, qs => <<>>})),
|
|
|
|
<<"https://localhost:8443/path">> = iolist_to_binary(uri(#{
|
|
|
|
scheme => <<"https">>, host => <<"localhost">>, port => 8443,
|
|
|
|
path => <<"/path">>, qs => <<>>})),
|
|
|
|
<<"https://localhost:8443/path?dummy=2785">> = iolist_to_binary(uri(#{
|
|
|
|
scheme => <<"https">>, host => <<"localhost">>, port => 8443,
|
|
|
|
path => <<"/path">>, qs => <<"dummy=2785">>})),
|
|
|
|
ok.
|
|
|
|
|
|
|
|
uri2_test() ->
|
|
|
|
Req = #{
|
|
|
|
scheme => <<"http">>, host => <<"localhost">>, port => 8080,
|
|
|
|
path => <<"/path">>, qs => <<"dummy=2785">>
|
|
|
|
},
|
|
|
|
<<"http://localhost:8080/path?dummy=2785">> = iolist_to_binary(uri(Req, #{})),
|
|
|
|
%% Disable individual components.
|
|
|
|
<<"//localhost:8080/path?dummy=2785">> = iolist_to_binary(uri(Req, #{scheme => undefined})),
|
|
|
|
<<"/path?dummy=2785">> = iolist_to_binary(uri(Req, #{host => undefined})),
|
|
|
|
<<"http://localhost/path?dummy=2785">> = iolist_to_binary(uri(Req, #{port => undefined})),
|
|
|
|
<<"http://localhost:8080?dummy=2785">> = iolist_to_binary(uri(Req, #{path => undefined})),
|
|
|
|
<<"http://localhost:8080/path">> = iolist_to_binary(uri(Req, #{qs => undefined})),
|
|
|
|
<<"http://localhost:8080/path?dummy=2785">> = iolist_to_binary(uri(Req, #{fragment => undefined})),
|
|
|
|
<<"http://localhost:8080">> = iolist_to_binary(uri(Req, #{path => undefined, qs => undefined})),
|
|
|
|
<<>> = iolist_to_binary(uri(Req, #{host => undefined, path => undefined, qs => undefined})),
|
|
|
|
%% Empty values.
|
|
|
|
<<"//localhost:8080/path?dummy=2785">> = iolist_to_binary(uri(Req, #{scheme => <<>>})),
|
|
|
|
<<"//localhost:8080/path?dummy=2785">> = iolist_to_binary(uri(Req, #{scheme => ""})),
|
|
|
|
<<"//localhost:8080/path?dummy=2785">> = iolist_to_binary(uri(Req, #{scheme => [<<>>]})),
|
|
|
|
<<"/path?dummy=2785">> = iolist_to_binary(uri(Req, #{host => <<>>})),
|
|
|
|
<<"/path?dummy=2785">> = iolist_to_binary(uri(Req, #{host => ""})),
|
|
|
|
<<"/path?dummy=2785">> = iolist_to_binary(uri(Req, #{host => [<<>>]})),
|
|
|
|
<<"http://localhost:8080?dummy=2785">> = iolist_to_binary(uri(Req, #{path => <<>>})),
|
|
|
|
<<"http://localhost:8080?dummy=2785">> = iolist_to_binary(uri(Req, #{path => ""})),
|
|
|
|
<<"http://localhost:8080?dummy=2785">> = iolist_to_binary(uri(Req, #{path => [<<>>]})),
|
|
|
|
<<"http://localhost:8080/path">> = iolist_to_binary(uri(Req, #{qs => <<>>})),
|
|
|
|
<<"http://localhost:8080/path">> = iolist_to_binary(uri(Req, #{qs => ""})),
|
|
|
|
<<"http://localhost:8080/path">> = iolist_to_binary(uri(Req, #{qs => [<<>>]})),
|
|
|
|
<<"http://localhost:8080/path?dummy=2785">> = iolist_to_binary(uri(Req, #{fragment => <<>>})),
|
|
|
|
<<"http://localhost:8080/path?dummy=2785">> = iolist_to_binary(uri(Req, #{fragment => ""})),
|
|
|
|
<<"http://localhost:8080/path?dummy=2785">> = iolist_to_binary(uri(Req, #{fragment => [<<>>]})),
|
|
|
|
%% Port is integer() | undefined.
|
|
|
|
{'EXIT', _} = (catch iolist_to_binary(uri(Req, #{port => <<>>}))),
|
|
|
|
{'EXIT', _} = (catch iolist_to_binary(uri(Req, #{port => ""}))),
|
|
|
|
{'EXIT', _} = (catch iolist_to_binary(uri(Req, #{port => [<<>>]}))),
|
|
|
|
%% Update components.
|
|
|
|
<<"https://localhost:8080/path?dummy=2785">> = iolist_to_binary(uri(Req, #{scheme => "https"})),
|
|
|
|
<<"http://example.org:8080/path?dummy=2785">> = iolist_to_binary(uri(Req, #{host => "example.org"})),
|
|
|
|
<<"http://localhost:123/path?dummy=2785">> = iolist_to_binary(uri(Req, #{port => 123})),
|
|
|
|
<<"http://localhost:8080/custom?dummy=2785">> = iolist_to_binary(uri(Req, #{path => "/custom"})),
|
|
|
|
<<"http://localhost:8080/path?smart=42">> = iolist_to_binary(uri(Req, #{qs => "smart=42"})),
|
|
|
|
<<"http://localhost:8080/path?dummy=2785#intro">> = iolist_to_binary(uri(Req, #{fragment => "intro"})),
|
|
|
|
%% Interesting combinations.
|
|
|
|
<<"http://localhost/path?dummy=2785">> = iolist_to_binary(uri(Req, #{port => 80})),
|
|
|
|
<<"https://localhost/path?dummy=2785">> = iolist_to_binary(uri(Req, #{scheme => "https", port => 443})),
|
|
|
|
ok.
|
|
|
|
-endif.
|
2012-09-15 22:03:00 +02:00
|
|
|
|
2014-09-23 16:43:29 +03:00
|
|
|
-spec binding(atom(), req()) -> any() | undefined.
|
|
|
|
binding(Name, Req) ->
|
2011-03-29 13:57:21 +02:00
|
|
|
binding(Name, Req, undefined).
|
2011-03-29 13:49:48 +02:00
|
|
|
|
2014-09-23 16:43:29 +03:00
|
|
|
-spec binding(atom(), req(), Default) -> any() | Default when Default::any().
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
binding(Name, #{bindings := Bindings}, Default) when is_atom(Name) ->
|
2017-02-19 16:51:16 +01:00
|
|
|
case Bindings of
|
|
|
|
#{Name := Value} -> Value;
|
|
|
|
_ -> Default
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
end;
|
|
|
|
binding(Name, _, Default) when is_atom(Name) ->
|
|
|
|
Default.
|
2011-03-07 22:59:22 +01:00
|
|
|
|
2017-02-19 16:51:16 +01:00
|
|
|
-spec bindings(req()) -> cowboy_router:bindings().
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
bindings(#{bindings := Bindings}) ->
|
|
|
|
Bindings;
|
|
|
|
bindings(_) ->
|
2017-02-19 16:51:16 +01:00
|
|
|
#{}.
|
2011-03-07 22:59:22 +01:00
|
|
|
|
2014-09-23 16:43:29 +03:00
|
|
|
-spec header(binary(), req()) -> binary() | undefined.
|
2012-09-21 09:18:56 +02:00
|
|
|
header(Name, Req) ->
|
2011-03-29 13:57:21 +02:00
|
|
|
header(Name, Req, undefined).
|
2011-03-29 13:49:48 +02:00
|
|
|
|
2014-09-23 16:43:29 +03:00
|
|
|
-spec header(binary(), req(), Default) -> binary() | Default when Default::any().
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
header(Name, #{headers := Headers}, Default) ->
|
|
|
|
maps:get(Name, Headers, Default).
|
2011-03-07 22:59:22 +01:00
|
|
|
|
2014-09-23 16:43:29 +03:00
|
|
|
-spec headers(req()) -> cowboy:http_headers().
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
headers(#{headers := Headers}) ->
|
|
|
|
Headers.
|
2014-09-23 16:43:29 +03:00
|
|
|
|
|
|
|
-spec parse_header(binary(), Req) -> any() when Req::req().
|
|
|
|
parse_header(Name = <<"content-length">>, Req) ->
|
2017-09-14 13:42:17 +02:00
|
|
|
parse_header(Name, Req, 0);
|
2014-09-23 16:43:29 +03:00
|
|
|
parse_header(Name = <<"cookie">>, Req) ->
|
2017-09-14 13:42:17 +02:00
|
|
|
parse_header(Name, Req, []);
|
2014-09-23 16:43:29 +03:00
|
|
|
parse_header(Name, Req) ->
|
|
|
|
parse_header(Name, Req, undefined).
|
|
|
|
|
|
|
|
-spec parse_header(binary(), Req, any()) -> any() when Req::req().
|
2015-02-04 16:18:28 +01:00
|
|
|
parse_header(Name, Req, Default) ->
|
2017-09-14 13:42:17 +02:00
|
|
|
try
|
|
|
|
parse_header(Name, Req, Default, parse_header_fun(Name))
|
|
|
|
catch _:_ ->
|
|
|
|
erlang:raise(exit, {request_error, {header, Name},
|
|
|
|
'Malformed header. Please consult the relevant specification.'
|
|
|
|
}, erlang:get_stacktrace())
|
|
|
|
end.
|
2015-02-04 16:18:28 +01:00
|
|
|
|
|
|
|
parse_header_fun(<<"accept">>) -> fun cow_http_hd:parse_accept/1;
|
|
|
|
parse_header_fun(<<"accept-charset">>) -> fun cow_http_hd:parse_accept_charset/1;
|
|
|
|
parse_header_fun(<<"accept-encoding">>) -> fun cow_http_hd:parse_accept_encoding/1;
|
|
|
|
parse_header_fun(<<"accept-language">>) -> fun cow_http_hd:parse_accept_language/1;
|
|
|
|
parse_header_fun(<<"authorization">>) -> fun cow_http_hd:parse_authorization/1;
|
|
|
|
parse_header_fun(<<"connection">>) -> fun cow_http_hd:parse_connection/1;
|
|
|
|
parse_header_fun(<<"content-length">>) -> fun cow_http_hd:parse_content_length/1;
|
|
|
|
parse_header_fun(<<"content-type">>) -> fun cow_http_hd:parse_content_type/1;
|
|
|
|
parse_header_fun(<<"cookie">>) -> fun cow_cookie:parse_cookie/1;
|
|
|
|
parse_header_fun(<<"expect">>) -> fun cow_http_hd:parse_expect/1;
|
|
|
|
parse_header_fun(<<"if-match">>) -> fun cow_http_hd:parse_if_match/1;
|
|
|
|
parse_header_fun(<<"if-modified-since">>) -> fun cow_http_hd:parse_if_modified_since/1;
|
|
|
|
parse_header_fun(<<"if-none-match">>) -> fun cow_http_hd:parse_if_none_match/1;
|
2018-11-07 18:55:06 +01:00
|
|
|
parse_header_fun(<<"if-range">>) -> fun cow_http_hd:parse_if_range/1;
|
2015-02-04 16:18:28 +01:00
|
|
|
parse_header_fun(<<"if-unmodified-since">>) -> fun cow_http_hd:parse_if_unmodified_since/1;
|
|
|
|
parse_header_fun(<<"range">>) -> fun cow_http_hd:parse_range/1;
|
|
|
|
parse_header_fun(<<"sec-websocket-extensions">>) -> fun cow_http_hd:parse_sec_websocket_extensions/1;
|
|
|
|
parse_header_fun(<<"sec-websocket-protocol">>) -> fun cow_http_hd:parse_sec_websocket_protocol_req/1;
|
2018-04-04 17:23:37 +02:00
|
|
|
parse_header_fun(<<"sec-websocket-version">>) -> fun cow_http_hd:parse_sec_websocket_version_req/1;
|
2015-02-04 16:18:28 +01:00
|
|
|
parse_header_fun(<<"upgrade">>) -> fun cow_http_hd:parse_upgrade/1;
|
|
|
|
parse_header_fun(<<"x-forwarded-for">>) -> fun cow_http_hd:parse_x_forwarded_for/1.
|
|
|
|
|
2014-09-23 16:43:29 +03:00
|
|
|
parse_header(Name, Req, Default, ParseFun) ->
|
2011-10-05 03:17:13 +02:00
|
|
|
case header(Name, Req) of
|
2015-02-04 16:18:28 +01:00
|
|
|
undefined -> Default;
|
|
|
|
Value -> ParseFun(Value)
|
2011-10-26 04:07:08 +02:00
|
|
|
end.
|
2011-10-05 03:17:13 +02:00
|
|
|
|
2014-09-23 16:43:29 +03:00
|
|
|
-spec parse_cookies(req()) -> [{binary(), binary()}].
|
|
|
|
parse_cookies(Req) ->
|
|
|
|
parse_header(<<"cookie">>, Req).
|
2011-07-08 13:41:30 -05:00
|
|
|
|
2014-10-04 13:21:16 +03:00
|
|
|
-spec match_cookies(cowboy:fields(), req()) -> map().
|
|
|
|
match_cookies(Fields, Req) ->
|
2017-09-27 16:20:38 +02:00
|
|
|
case filter(Fields, kvlist_to_map(Fields, parse_cookies(Req))) of
|
|
|
|
{ok, Map} ->
|
|
|
|
Map;
|
|
|
|
{error, Errors} ->
|
|
|
|
exit({request_error, {match_cookies, Errors},
|
|
|
|
'Cookie validation constraints failed for the reasons provided.'})
|
|
|
|
end.
|
2011-07-08 13:41:30 -05:00
|
|
|
|
2016-08-10 11:49:31 +02:00
|
|
|
%% Request body.
|
2011-03-21 17:26:00 +01:00
|
|
|
|
2013-04-11 14:22:16 +02:00
|
|
|
-spec has_body(req()) -> boolean().
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
has_body(#{has_body := HasBody}) ->
|
|
|
|
HasBody.
|
2012-03-29 01:14:44 +02:00
|
|
|
|
2016-08-10 11:49:31 +02:00
|
|
|
%% The length may not be known if HTTP/1.1 with a transfer-encoding;
|
|
|
|
%% or HTTP/2 with no content-length header. The length is always
|
|
|
|
%% known once the body has been completely read.
|
2014-09-23 16:43:29 +03:00
|
|
|
-spec body_length(req()) -> undefined | non_neg_integer().
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
body_length(#{body_length := Length}) ->
|
|
|
|
Length.
|
2012-03-29 01:14:44 +02:00
|
|
|
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
-spec read_body(Req) -> {ok, binary(), Req} | {more, binary(), Req} when Req::req().
|
|
|
|
read_body(Req) ->
|
2016-08-10 11:49:31 +02:00
|
|
|
read_body(Req, #{}).
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
|
2017-01-02 16:47:16 +01:00
|
|
|
-spec read_body(Req, read_body_opts()) -> {ok, binary(), Req} | {more, binary(), Req} when Req::req().
|
2016-08-10 11:49:31 +02:00
|
|
|
read_body(Req=#{has_body := false}, _) ->
|
|
|
|
{ok, <<>>, Req};
|
|
|
|
read_body(Req=#{has_read_body := true}, _) ->
|
|
|
|
{ok, <<>>, Req};
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
read_body(Req=#{pid := Pid, streamid := StreamID}, Opts) ->
|
2016-08-10 11:49:31 +02:00
|
|
|
Length = maps:get(length, Opts, 8000000),
|
|
|
|
Period = maps:get(period, Opts, 15000),
|
|
|
|
Timeout = maps:get(timeout, Opts, Period + 1000),
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
Ref = make_ref(),
|
2016-08-10 11:49:31 +02:00
|
|
|
Pid ! {{Pid, StreamID}, {read_body, Ref, Length, Period}},
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
receive
|
|
|
|
{request_body, Ref, nofin, Body} ->
|
|
|
|
{more, Body, Req};
|
2017-09-25 12:34:44 +02:00
|
|
|
{request_body, Ref, fin, BodyLength, Body} ->
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
{ok, Body, set_body_length(Req, BodyLength)}
|
2016-08-10 11:49:31 +02:00
|
|
|
after Timeout ->
|
|
|
|
exit(timeout)
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
end.
|
|
|
|
|
|
|
|
set_body_length(Req=#{headers := Headers}, BodyLength) ->
|
|
|
|
Req#{
|
|
|
|
headers => Headers#{<<"content-length">> => integer_to_binary(BodyLength)},
|
2016-08-10 11:49:31 +02:00
|
|
|
body_length => BodyLength,
|
|
|
|
has_read_body => true
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
}.
|
|
|
|
|
2016-08-10 11:49:31 +02:00
|
|
|
-spec read_urlencoded_body(Req) -> {ok, [{binary(), binary() | true}], Req} when Req::req().
|
|
|
|
read_urlencoded_body(Req) ->
|
|
|
|
read_urlencoded_body(Req, #{length => 64000, period => 5000}).
|
2015-02-04 16:18:28 +01:00
|
|
|
|
2017-01-02 16:47:16 +01:00
|
|
|
-spec read_urlencoded_body(Req, read_body_opts()) -> {ok, [{binary(), binary() | true}], Req} when Req::req().
|
2016-08-10 11:49:31 +02:00
|
|
|
read_urlencoded_body(Req0, Opts) ->
|
2017-09-14 13:42:17 +02:00
|
|
|
case read_body(Req0, Opts) of
|
|
|
|
{ok, Body, Req} ->
|
|
|
|
try
|
|
|
|
{ok, cow_qs:parse_qs(Body), Req}
|
|
|
|
catch _:_ ->
|
|
|
|
erlang:raise(exit, {request_error, urlencoded_body,
|
|
|
|
'Malformed body; application/x-www-form-urlencoded expected.'
|
|
|
|
}, erlang:get_stacktrace())
|
|
|
|
end;
|
|
|
|
{more, Body, _} ->
|
|
|
|
Length = maps:get(length, Opts, 64000),
|
|
|
|
if
|
|
|
|
byte_size(Body) < Length ->
|
|
|
|
exit({request_error, timeout,
|
|
|
|
'The request body was not received within the configured time.'});
|
|
|
|
true ->
|
|
|
|
exit({request_error, payload_too_large,
|
|
|
|
'The request body is larger than allowed by configuration.'})
|
|
|
|
end
|
|
|
|
end.
|
Add request body reading options
The options were added to allow developers to fix timeout
issues when reading large bodies. It is also a cleaner and
easier to extend interface.
This commit deprecates the functions init_stream, stream_body
and skip_body which are no longer needed. They will be removed
in 1.0.
The body function can now take an additional argument that is a
list of options. The body_qs, part and part_body functions can
too and simply pass this argument down to the body call.
There are options for disabling the automatic continue reply,
setting a maximum length to be returned (soft limit), setting
the read length and read timeout, and setting the transfer and
content decode functions.
The return value of the body and body_qs have changed slightly.
The body function now works similarly to the part_body function,
in that it returns either an ok or a more tuple depending on
whether there is additional data to be read. The body_qs function
can return a badlength tuple if the body is too big. The default
size has been increased from 16KB to 64KB.
The default read length and timeout have been tweaked and vary
depending on the function called.
The body function will now adequately process chunked bodies,
which means that the body_qs function will too. But this means
that the behavior has changed slightly and your code should be
tested properly when updating your code.
The body and body_qs still accept a length as first argument
for compatibility purpose with older code. Note that this form
is deprecated and will be removed in 1.0. The part and part_body
function, being new and never having been in a release yet, have
this form completely removed in this commit.
Again, while most code should work as-is, you should make sure
that it actually does before pushing this to production.
2014-06-02 23:09:43 +02:00
|
|
|
|
2018-09-07 13:56:12 +02:00
|
|
|
-spec read_and_match_urlencoded_body(cowboy:fields(), Req)
|
|
|
|
-> {ok, map(), Req} when Req::req().
|
|
|
|
read_and_match_urlencoded_body(Fields, Req) ->
|
|
|
|
read_and_match_urlencoded_body(Fields, Req, #{length => 64000, period => 5000}).
|
|
|
|
|
|
|
|
-spec read_and_match_urlencoded_body(cowboy:fields(), Req, read_body_opts())
|
|
|
|
-> {ok, map(), Req} when Req::req().
|
|
|
|
read_and_match_urlencoded_body(Fields, Req0, Opts) ->
|
|
|
|
{ok, Qs, Req} = read_urlencoded_body(Req0, Opts),
|
|
|
|
case filter(Fields, kvlist_to_map(Fields, Qs)) of
|
|
|
|
{ok, Map} ->
|
|
|
|
{ok, Map, Req};
|
|
|
|
{error, Errors} ->
|
|
|
|
exit({request_error, {read_and_match_urlencoded_body, Errors},
|
|
|
|
'Urlencoded request body validation constraints failed for the reasons provided.'})
|
|
|
|
end.
|
|
|
|
|
2016-08-10 11:49:31 +02:00
|
|
|
%% Multipart.
|
2011-11-08 00:51:49 +01:00
|
|
|
|
2016-08-10 15:09:04 +02:00
|
|
|
-spec read_part(Req)
|
2018-10-31 10:50:57 +01:00
|
|
|
-> {ok, cowboy:http_headers(), Req} | {done, Req}
|
2014-02-06 19:36:25 +01:00
|
|
|
when Req::req().
|
2016-08-10 15:09:04 +02:00
|
|
|
read_part(Req) ->
|
|
|
|
read_part(Req, #{length => 64000, period => 5000}).
|
2014-02-06 19:36:25 +01:00
|
|
|
|
2017-01-02 16:47:16 +01:00
|
|
|
-spec read_part(Req, read_body_opts())
|
2018-10-31 10:50:57 +01:00
|
|
|
-> {ok, cowboy:http_headers(), Req} | {done, Req}
|
Add request body reading options
The options were added to allow developers to fix timeout
issues when reading large bodies. It is also a cleaner and
easier to extend interface.
This commit deprecates the functions init_stream, stream_body
and skip_body which are no longer needed. They will be removed
in 1.0.
The body function can now take an additional argument that is a
list of options. The body_qs, part and part_body functions can
too and simply pass this argument down to the body call.
There are options for disabling the automatic continue reply,
setting a maximum length to be returned (soft limit), setting
the read length and read timeout, and setting the transfer and
content decode functions.
The return value of the body and body_qs have changed slightly.
The body function now works similarly to the part_body function,
in that it returns either an ok or a more tuple depending on
whether there is additional data to be read. The body_qs function
can return a badlength tuple if the body is too big. The default
size has been increased from 16KB to 64KB.
The default read length and timeout have been tweaked and vary
depending on the function called.
The body function will now adequately process chunked bodies,
which means that the body_qs function will too. But this means
that the behavior has changed slightly and your code should be
tested properly when updating your code.
The body and body_qs still accept a length as first argument
for compatibility purpose with older code. Note that this form
is deprecated and will be removed in 1.0. The part and part_body
function, being new and never having been in a release yet, have
this form completely removed in this commit.
Again, while most code should work as-is, you should make sure
that it actually does before pushing this to production.
2014-06-02 23:09:43 +02:00
|
|
|
when Req::req().
|
2016-08-10 15:09:04 +02:00
|
|
|
read_part(Req, Opts) ->
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
case maps:is_key(multipart, Req) of
|
|
|
|
true ->
|
2017-05-16 14:50:01 -07:00
|
|
|
{Data, Req2} = stream_multipart(Req, Opts, headers),
|
2016-08-10 15:09:04 +02:00
|
|
|
read_part(Data, Opts, Req2);
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
false ->
|
2016-08-10 15:09:04 +02:00
|
|
|
read_part(init_multipart(Req), Opts)
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
end.
|
Add request body reading options
The options were added to allow developers to fix timeout
issues when reading large bodies. It is also a cleaner and
easier to extend interface.
This commit deprecates the functions init_stream, stream_body
and skip_body which are no longer needed. They will be removed
in 1.0.
The body function can now take an additional argument that is a
list of options. The body_qs, part and part_body functions can
too and simply pass this argument down to the body call.
There are options for disabling the automatic continue reply,
setting a maximum length to be returned (soft limit), setting
the read length and read timeout, and setting the transfer and
content decode functions.
The return value of the body and body_qs have changed slightly.
The body function now works similarly to the part_body function,
in that it returns either an ok or a more tuple depending on
whether there is additional data to be read. The body_qs function
can return a badlength tuple if the body is too big. The default
size has been increased from 16KB to 64KB.
The default read length and timeout have been tweaked and vary
depending on the function called.
The body function will now adequately process chunked bodies,
which means that the body_qs function will too. But this means
that the behavior has changed slightly and your code should be
tested properly when updating your code.
The body and body_qs still accept a length as first argument
for compatibility purpose with older code. Note that this form
is deprecated and will be removed in 1.0. The part and part_body
function, being new and never having been in a release yet, have
this form completely removed in this commit.
Again, while most code should work as-is, you should make sure
that it actually does before pushing this to production.
2014-06-02 23:09:43 +02:00
|
|
|
|
2016-08-10 15:09:04 +02:00
|
|
|
read_part(Buffer, Opts, Req=#{multipart := {Boundary, _}}) ->
|
2017-09-14 13:42:17 +02:00
|
|
|
try cow_multipart:parse_headers(Buffer, Boundary) of
|
2014-02-06 19:36:25 +01:00
|
|
|
more ->
|
2017-05-16 14:50:01 -07:00
|
|
|
{Data, Req2} = stream_multipart(Req, Opts, headers),
|
2016-08-10 15:09:04 +02:00
|
|
|
read_part(<< Buffer/binary, Data/binary >>, Opts, Req2);
|
2014-02-06 19:36:25 +01:00
|
|
|
{more, Buffer2} ->
|
2017-05-16 14:50:01 -07:00
|
|
|
{Data, Req2} = stream_multipart(Req, Opts, headers),
|
2016-08-10 15:09:04 +02:00
|
|
|
read_part(<< Buffer2/binary, Data/binary >>, Opts, Req2);
|
2017-06-09 16:57:11 +02:00
|
|
|
{ok, Headers0, Rest} ->
|
|
|
|
Headers = maps:from_list(Headers0),
|
|
|
|
%% Reject multipart content containing duplicate headers.
|
|
|
|
true = map_size(Headers) =:= length(Headers0),
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
{ok, Headers, Req#{multipart => {Boundary, Rest}}};
|
2014-02-06 19:36:25 +01:00
|
|
|
%% Ignore epilogue.
|
|
|
|
{done, _} ->
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
{done, Req#{multipart => done}}
|
2017-09-14 13:42:17 +02:00
|
|
|
catch _:_ ->
|
|
|
|
erlang:raise(exit, {request_error, {multipart, headers},
|
|
|
|
'Malformed body; multipart expected.'
|
|
|
|
}, erlang:get_stacktrace())
|
2011-11-08 00:51:49 +01:00
|
|
|
end.
|
|
|
|
|
2016-08-10 15:09:04 +02:00
|
|
|
-spec read_part_body(Req)
|
2014-02-06 19:36:25 +01:00
|
|
|
-> {ok, binary(), Req} | {more, binary(), Req}
|
|
|
|
when Req::req().
|
2016-08-10 15:09:04 +02:00
|
|
|
read_part_body(Req) ->
|
|
|
|
read_part_body(Req, #{}).
|
2014-02-06 19:36:25 +01:00
|
|
|
|
2017-01-02 16:47:16 +01:00
|
|
|
-spec read_part_body(Req, read_body_opts())
|
2014-02-06 19:36:25 +01:00
|
|
|
-> {ok, binary(), Req} | {more, binary(), Req}
|
|
|
|
when Req::req().
|
2016-08-10 15:09:04 +02:00
|
|
|
read_part_body(Req, Opts) ->
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
case maps:is_key(multipart, Req) of
|
|
|
|
true ->
|
2016-08-10 15:09:04 +02:00
|
|
|
read_part_body(<<>>, Opts, Req, <<>>);
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
false ->
|
2016-08-10 15:09:04 +02:00
|
|
|
read_part_body(init_multipart(Req), Opts)
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
end.
|
Add request body reading options
The options were added to allow developers to fix timeout
issues when reading large bodies. It is also a cleaner and
easier to extend interface.
This commit deprecates the functions init_stream, stream_body
and skip_body which are no longer needed. They will be removed
in 1.0.
The body function can now take an additional argument that is a
list of options. The body_qs, part and part_body functions can
too and simply pass this argument down to the body call.
There are options for disabling the automatic continue reply,
setting a maximum length to be returned (soft limit), setting
the read length and read timeout, and setting the transfer and
content decode functions.
The return value of the body and body_qs have changed slightly.
The body function now works similarly to the part_body function,
in that it returns either an ok or a more tuple depending on
whether there is additional data to be read. The body_qs function
can return a badlength tuple if the body is too big. The default
size has been increased from 16KB to 64KB.
The default read length and timeout have been tweaked and vary
depending on the function called.
The body function will now adequately process chunked bodies,
which means that the body_qs function will too. But this means
that the behavior has changed slightly and your code should be
tested properly when updating your code.
The body and body_qs still accept a length as first argument
for compatibility purpose with older code. Note that this form
is deprecated and will be removed in 1.0. The part and part_body
function, being new and never having been in a release yet, have
this form completely removed in this commit.
Again, while most code should work as-is, you should make sure
that it actually does before pushing this to production.
2014-06-02 23:09:43 +02:00
|
|
|
|
2016-08-10 15:09:04 +02:00
|
|
|
read_part_body(Buffer, Opts, Req=#{multipart := {Boundary, _}}, Acc) ->
|
2016-08-10 11:49:31 +02:00
|
|
|
Length = maps:get(length, Opts, 8000000),
|
|
|
|
case byte_size(Acc) > Length of
|
Add request body reading options
The options were added to allow developers to fix timeout
issues when reading large bodies. It is also a cleaner and
easier to extend interface.
This commit deprecates the functions init_stream, stream_body
and skip_body which are no longer needed. They will be removed
in 1.0.
The body function can now take an additional argument that is a
list of options. The body_qs, part and part_body functions can
too and simply pass this argument down to the body call.
There are options for disabling the automatic continue reply,
setting a maximum length to be returned (soft limit), setting
the read length and read timeout, and setting the transfer and
content decode functions.
The return value of the body and body_qs have changed slightly.
The body function now works similarly to the part_body function,
in that it returns either an ok or a more tuple depending on
whether there is additional data to be read. The body_qs function
can return a badlength tuple if the body is too big. The default
size has been increased from 16KB to 64KB.
The default read length and timeout have been tweaked and vary
depending on the function called.
The body function will now adequately process chunked bodies,
which means that the body_qs function will too. But this means
that the behavior has changed slightly and your code should be
tested properly when updating your code.
The body and body_qs still accept a length as first argument
for compatibility purpose with older code. Note that this form
is deprecated and will be removed in 1.0. The part and part_body
function, being new and never having been in a release yet, have
this form completely removed in this commit.
Again, while most code should work as-is, you should make sure
that it actually does before pushing this to production.
2014-06-02 23:09:43 +02:00
|
|
|
true ->
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
{more, Acc, Req#{multipart => {Boundary, Buffer}}};
|
Add request body reading options
The options were added to allow developers to fix timeout
issues when reading large bodies. It is also a cleaner and
easier to extend interface.
This commit deprecates the functions init_stream, stream_body
and skip_body which are no longer needed. They will be removed
in 1.0.
The body function can now take an additional argument that is a
list of options. The body_qs, part and part_body functions can
too and simply pass this argument down to the body call.
There are options for disabling the automatic continue reply,
setting a maximum length to be returned (soft limit), setting
the read length and read timeout, and setting the transfer and
content decode functions.
The return value of the body and body_qs have changed slightly.
The body function now works similarly to the part_body function,
in that it returns either an ok or a more tuple depending on
whether there is additional data to be read. The body_qs function
can return a badlength tuple if the body is too big. The default
size has been increased from 16KB to 64KB.
The default read length and timeout have been tweaked and vary
depending on the function called.
The body function will now adequately process chunked bodies,
which means that the body_qs function will too. But this means
that the behavior has changed slightly and your code should be
tested properly when updating your code.
The body and body_qs still accept a length as first argument
for compatibility purpose with older code. Note that this form
is deprecated and will be removed in 1.0. The part and part_body
function, being new and never having been in a release yet, have
this form completely removed in this commit.
Again, while most code should work as-is, you should make sure
that it actually does before pushing this to production.
2014-06-02 23:09:43 +02:00
|
|
|
false ->
|
2017-05-16 14:50:01 -07:00
|
|
|
{Data, Req2} = stream_multipart(Req, Opts, body),
|
Add request body reading options
The options were added to allow developers to fix timeout
issues when reading large bodies. It is also a cleaner and
easier to extend interface.
This commit deprecates the functions init_stream, stream_body
and skip_body which are no longer needed. They will be removed
in 1.0.
The body function can now take an additional argument that is a
list of options. The body_qs, part and part_body functions can
too and simply pass this argument down to the body call.
There are options for disabling the automatic continue reply,
setting a maximum length to be returned (soft limit), setting
the read length and read timeout, and setting the transfer and
content decode functions.
The return value of the body and body_qs have changed slightly.
The body function now works similarly to the part_body function,
in that it returns either an ok or a more tuple depending on
whether there is additional data to be read. The body_qs function
can return a badlength tuple if the body is too big. The default
size has been increased from 16KB to 64KB.
The default read length and timeout have been tweaked and vary
depending on the function called.
The body function will now adequately process chunked bodies,
which means that the body_qs function will too. But this means
that the behavior has changed slightly and your code should be
tested properly when updating your code.
The body and body_qs still accept a length as first argument
for compatibility purpose with older code. Note that this form
is deprecated and will be removed in 1.0. The part and part_body
function, being new and never having been in a release yet, have
this form completely removed in this commit.
Again, while most code should work as-is, you should make sure
that it actually does before pushing this to production.
2014-06-02 23:09:43 +02:00
|
|
|
case cow_multipart:parse_body(<< Buffer/binary, Data/binary >>, Boundary) of
|
|
|
|
{ok, Body} ->
|
2016-08-10 15:09:04 +02:00
|
|
|
read_part_body(<<>>, Opts, Req2, << Acc/binary, Body/binary >>);
|
Add request body reading options
The options were added to allow developers to fix timeout
issues when reading large bodies. It is also a cleaner and
easier to extend interface.
This commit deprecates the functions init_stream, stream_body
and skip_body which are no longer needed. They will be removed
in 1.0.
The body function can now take an additional argument that is a
list of options. The body_qs, part and part_body functions can
too and simply pass this argument down to the body call.
There are options for disabling the automatic continue reply,
setting a maximum length to be returned (soft limit), setting
the read length and read timeout, and setting the transfer and
content decode functions.
The return value of the body and body_qs have changed slightly.
The body function now works similarly to the part_body function,
in that it returns either an ok or a more tuple depending on
whether there is additional data to be read. The body_qs function
can return a badlength tuple if the body is too big. The default
size has been increased from 16KB to 64KB.
The default read length and timeout have been tweaked and vary
depending on the function called.
The body function will now adequately process chunked bodies,
which means that the body_qs function will too. But this means
that the behavior has changed slightly and your code should be
tested properly when updating your code.
The body and body_qs still accept a length as first argument
for compatibility purpose with older code. Note that this form
is deprecated and will be removed in 1.0. The part and part_body
function, being new and never having been in a release yet, have
this form completely removed in this commit.
Again, while most code should work as-is, you should make sure
that it actually does before pushing this to production.
2014-06-02 23:09:43 +02:00
|
|
|
{ok, Body, Rest} ->
|
2016-08-10 15:09:04 +02:00
|
|
|
read_part_body(Rest, Opts, Req2, << Acc/binary, Body/binary >>);
|
Add request body reading options
The options were added to allow developers to fix timeout
issues when reading large bodies. It is also a cleaner and
easier to extend interface.
This commit deprecates the functions init_stream, stream_body
and skip_body which are no longer needed. They will be removed
in 1.0.
The body function can now take an additional argument that is a
list of options. The body_qs, part and part_body functions can
too and simply pass this argument down to the body call.
There are options for disabling the automatic continue reply,
setting a maximum length to be returned (soft limit), setting
the read length and read timeout, and setting the transfer and
content decode functions.
The return value of the body and body_qs have changed slightly.
The body function now works similarly to the part_body function,
in that it returns either an ok or a more tuple depending on
whether there is additional data to be read. The body_qs function
can return a badlength tuple if the body is too big. The default
size has been increased from 16KB to 64KB.
The default read length and timeout have been tweaked and vary
depending on the function called.
The body function will now adequately process chunked bodies,
which means that the body_qs function will too. But this means
that the behavior has changed slightly and your code should be
tested properly when updating your code.
The body and body_qs still accept a length as first argument
for compatibility purpose with older code. Note that this form
is deprecated and will be removed in 1.0. The part and part_body
function, being new and never having been in a release yet, have
this form completely removed in this commit.
Again, while most code should work as-is, you should make sure
that it actually does before pushing this to production.
2014-06-02 23:09:43 +02:00
|
|
|
done ->
|
|
|
|
{ok, Acc, Req2};
|
|
|
|
{done, Body} ->
|
|
|
|
{ok, << Acc/binary, Body/binary >>, Req2};
|
|
|
|
{done, Body, Rest} ->
|
|
|
|
{ok, << Acc/binary, Body/binary >>,
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
Req2#{multipart => {Boundary, Rest}}}
|
Add request body reading options
The options were added to allow developers to fix timeout
issues when reading large bodies. It is also a cleaner and
easier to extend interface.
This commit deprecates the functions init_stream, stream_body
and skip_body which are no longer needed. They will be removed
in 1.0.
The body function can now take an additional argument that is a
list of options. The body_qs, part and part_body functions can
too and simply pass this argument down to the body call.
There are options for disabling the automatic continue reply,
setting a maximum length to be returned (soft limit), setting
the read length and read timeout, and setting the transfer and
content decode functions.
The return value of the body and body_qs have changed slightly.
The body function now works similarly to the part_body function,
in that it returns either an ok or a more tuple depending on
whether there is additional data to be read. The body_qs function
can return a badlength tuple if the body is too big. The default
size has been increased from 16KB to 64KB.
The default read length and timeout have been tweaked and vary
depending on the function called.
The body function will now adequately process chunked bodies,
which means that the body_qs function will too. But this means
that the behavior has changed slightly and your code should be
tested properly when updating your code.
The body and body_qs still accept a length as first argument
for compatibility purpose with older code. Note that this form
is deprecated and will be removed in 1.0. The part and part_body
function, being new and never having been in a release yet, have
this form completely removed in this commit.
Again, while most code should work as-is, you should make sure
that it actually does before pushing this to production.
2014-06-02 23:09:43 +02:00
|
|
|
end
|
2011-11-08 00:51:49 +01:00
|
|
|
end.
|
|
|
|
|
2014-02-06 19:36:25 +01:00
|
|
|
init_multipart(Req) ->
|
2014-09-23 16:43:29 +03:00
|
|
|
{<<"multipart">>, _, Params} = parse_header(<<"content-type">>, Req),
|
2017-09-14 13:42:17 +02:00
|
|
|
case lists:keyfind(<<"boundary">>, 1, Params) of
|
|
|
|
{_, Boundary} ->
|
|
|
|
Req#{multipart => {Boundary, <<>>}};
|
|
|
|
false ->
|
|
|
|
exit({request_error, {multipart, boundary},
|
|
|
|
'Missing boundary parameter for multipart media type.'})
|
|
|
|
end.
|
2014-02-06 19:36:25 +01:00
|
|
|
|
2017-05-16 14:50:01 -07:00
|
|
|
stream_multipart(Req=#{multipart := done}, _, _) ->
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
{<<>>, Req};
|
2017-05-16 14:50:01 -07:00
|
|
|
stream_multipart(Req=#{multipart := {_, <<>>}}, Opts, Type) ->
|
|
|
|
case read_body(Req, Opts) of
|
|
|
|
{more, Data, Req2} ->
|
|
|
|
{Data, Req2};
|
|
|
|
%% We crash when the data ends unexpectedly.
|
|
|
|
{ok, <<>>, _} ->
|
|
|
|
exit({request_error, {multipart, Type},
|
|
|
|
'Malformed body; multipart expected.'});
|
|
|
|
{ok, Data, Req2} ->
|
|
|
|
{Data, Req2}
|
|
|
|
end;
|
|
|
|
stream_multipart(Req=#{multipart := {Boundary, Buffer}}, _, _) ->
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
{Buffer, Req#{multipart => {Boundary, <<>>}}}.
|
2014-02-06 19:36:25 +01:00
|
|
|
|
2016-08-10 11:49:31 +02:00
|
|
|
%% Response.
|
|
|
|
|
|
|
|
-spec set_resp_cookie(iodata(), iodata(), Req)
|
|
|
|
-> Req when Req::req().
|
|
|
|
set_resp_cookie(Name, Value, Req) ->
|
2017-02-19 09:46:11 +01:00
|
|
|
set_resp_cookie(Name, Value, Req, #{}).
|
2011-03-18 22:38:26 +01:00
|
|
|
|
2012-12-17 12:32:17 +01:00
|
|
|
%% The cookie name cannot contain any of the following characters:
|
|
|
|
%% =,;\s\t\r\n\013\014
|
|
|
|
%%
|
|
|
|
%% The cookie value cannot contain any of the following characters:
|
|
|
|
%% ,; \t\r\n\013\014
|
2016-08-10 11:52:41 +02:00
|
|
|
%% @todo Fix the cookie_opts() type.
|
2017-02-19 09:46:11 +01:00
|
|
|
-spec set_resp_cookie(binary(), iodata(), Req, cookie_opts())
|
2012-12-07 14:54:45 +01:00
|
|
|
-> Req when Req::req().
|
2017-02-19 09:46:11 +01:00
|
|
|
set_resp_cookie(Name, Value, Req, Opts) ->
|
2016-08-10 11:49:31 +02:00
|
|
|
Cookie = cow_cookie:setcookie(Name, Value, maps:to_list(Opts)),
|
|
|
|
RespCookies = maps:get(resp_cookies, Req, #{}),
|
|
|
|
Req#{resp_cookies => RespCookies#{Name => Cookie}}.
|
|
|
|
|
|
|
|
%% @todo We could add has_resp_cookie and delete_resp_cookie now.
|
2011-12-07 11:54:57 +01:00
|
|
|
|
2012-09-21 09:18:56 +02:00
|
|
|
-spec set_resp_header(binary(), iodata(), Req)
|
2012-09-16 03:51:07 +02:00
|
|
|
-> Req when Req::req().
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
set_resp_header(Name, Value, Req=#{resp_headers := RespHeaders}) ->
|
|
|
|
Req#{resp_headers => RespHeaders#{Name => Value}};
|
|
|
|
set_resp_header(Name,Value, Req) ->
|
|
|
|
Req#{resp_headers => #{Name => Value}}.
|
2011-11-28 09:09:41 +01:00
|
|
|
|
2016-11-13 15:39:40 +01:00
|
|
|
-spec set_resp_headers(cowboy:http_headers(), Req)
|
|
|
|
-> Req when Req::req().
|
|
|
|
set_resp_headers(Headers, Req=#{resp_headers := RespHeaders}) ->
|
|
|
|
Req#{resp_headers => maps:merge(RespHeaders, Headers)};
|
|
|
|
set_resp_headers(Headers, Req) ->
|
|
|
|
Req#{resp_headers => Headers}.
|
|
|
|
|
|
|
|
-spec resp_header(binary(), req()) -> binary() | undefined.
|
|
|
|
resp_header(Name, Req) ->
|
|
|
|
resp_header(Name, Req, undefined).
|
|
|
|
|
|
|
|
-spec resp_header(binary(), req(), Default)
|
|
|
|
-> binary() | Default when Default::any().
|
|
|
|
resp_header(Name, #{resp_headers := Headers}, Default) ->
|
|
|
|
maps:get(Name, Headers, Default);
|
|
|
|
resp_header(_, #{}, Default) ->
|
|
|
|
Default.
|
|
|
|
|
|
|
|
-spec resp_headers(req()) -> cowboy:http_headers().
|
|
|
|
resp_headers(#{resp_headers := RespHeaders}) ->
|
|
|
|
RespHeaders;
|
|
|
|
resp_headers(#{}) ->
|
|
|
|
#{}.
|
|
|
|
|
2016-08-10 11:49:31 +02:00
|
|
|
-spec set_resp_body(resp_body(), Req) -> Req when Req::req().
|
2011-11-28 09:09:41 +01:00
|
|
|
set_resp_body(Body, Req) ->
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
Req#{resp_body => Body}.
|
2011-12-28 18:00:27 +01:00
|
|
|
|
2012-09-21 09:18:56 +02:00
|
|
|
-spec has_resp_header(binary(), req()) -> boolean().
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
has_resp_header(Name, #{resp_headers := RespHeaders}) ->
|
|
|
|
maps:is_key(Name, RespHeaders);
|
|
|
|
has_resp_header(_, _) ->
|
|
|
|
false.
|
2011-11-28 09:09:41 +01:00
|
|
|
|
2012-08-27 14:27:41 +02:00
|
|
|
-spec has_resp_body(req()) -> boolean().
|
2016-08-10 11:49:31 +02:00
|
|
|
has_resp_body(#{resp_body := {sendfile, _, _, _}}) ->
|
|
|
|
true;
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
has_resp_body(#{resp_body := RespBody}) ->
|
|
|
|
iolist_size(RespBody) > 0;
|
|
|
|
has_resp_body(_) ->
|
|
|
|
false.
|
|
|
|
|
2012-09-21 09:18:56 +02:00
|
|
|
-spec delete_resp_header(binary(), Req)
|
2012-09-16 01:55:40 +02:00
|
|
|
-> Req when Req::req().
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
delete_resp_header(Name, Req=#{resp_headers := RespHeaders}) ->
|
2018-01-22 14:00:05 +01:00
|
|
|
Req#{resp_headers => maps:remove(Name, RespHeaders)};
|
|
|
|
%% There are no resp headers so we have nothing to delete.
|
2018-01-23 16:29:25 +01:00
|
|
|
delete_resp_header(_, Req) ->
|
2018-01-22 14:00:05 +01:00
|
|
|
Req.
|
2012-09-16 01:55:40 +02:00
|
|
|
|
2017-10-29 19:52:27 +00:00
|
|
|
-spec inform(cowboy:http_status(), req()) -> ok.
|
|
|
|
inform(Status, Req) ->
|
|
|
|
inform(Status, #{}, Req).
|
|
|
|
|
|
|
|
-spec inform(cowboy:http_status(), cowboy:http_headers(), req()) -> ok.
|
|
|
|
inform(_, _, #{has_sent_resp := _}) ->
|
|
|
|
error(function_clause); %% @todo Better error message.
|
|
|
|
inform(Status, Headers, #{pid := Pid, streamid := StreamID})
|
|
|
|
when is_integer(Status); is_binary(Status) ->
|
|
|
|
Pid ! {{Pid, StreamID}, {inform, Status, Headers}},
|
|
|
|
ok.
|
|
|
|
|
2014-09-23 16:43:29 +03:00
|
|
|
-spec reply(cowboy:http_status(), Req) -> Req when Req::req().
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
reply(Status, Req) ->
|
|
|
|
reply(Status, #{}, Req).
|
2011-10-13 16:16:53 +02:00
|
|
|
|
2013-05-16 16:29:24 +02:00
|
|
|
-spec reply(cowboy:http_status(), cowboy:http_headers(), Req)
|
2014-09-23 16:43:29 +03:00
|
|
|
-> Req when Req::req().
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
reply(Status, Headers, Req=#{resp_body := Body}) ->
|
|
|
|
reply(Status, Headers, Body, Req);
|
|
|
|
reply(Status, Headers, Req) ->
|
|
|
|
reply(Status, Headers, <<>>, Req).
|
2011-10-13 16:16:53 +02:00
|
|
|
|
2016-08-10 11:49:31 +02:00
|
|
|
-spec reply(cowboy:http_status(), cowboy:http_headers(), resp_body(), Req)
|
2014-09-23 16:43:29 +03:00
|
|
|
-> Req when Req::req().
|
2016-08-10 17:15:02 +02:00
|
|
|
reply(_, _, _, #{has_sent_resp := _}) ->
|
2017-10-29 19:52:27 +00:00
|
|
|
error(function_clause); %% @todo Better error message.
|
2017-09-05 13:24:46 +02:00
|
|
|
reply(Status, Headers, {sendfile, _, 0, _}, Req)
|
2017-09-04 20:48:07 +02:00
|
|
|
when is_integer(Status); is_binary(Status) ->
|
|
|
|
do_reply(Status, Headers#{
|
|
|
|
<<"content-length">> => <<"0">>
|
|
|
|
}, <<>>, Req);
|
2016-08-10 11:49:31 +02:00
|
|
|
reply(Status, Headers, SendFile = {sendfile, _, Len, _}, Req)
|
|
|
|
when is_integer(Status); is_binary(Status) ->
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
do_reply(Status, Headers#{
|
|
|
|
<<"content-length">> => integer_to_binary(Len)
|
|
|
|
}, SendFile, Req);
|
2017-11-29 21:38:10 +01:00
|
|
|
%% 204 responses must not include content-length. (RFC7230 3.3.1, RFC7230 3.3.2)
|
|
|
|
reply(Status=204, Headers, Body, Req) ->
|
|
|
|
do_reply(Status, Headers, Body, Req);
|
|
|
|
reply(Status= <<"204",_/bits>>, Headers, Body, Req) ->
|
|
|
|
do_reply(Status, Headers, Body, Req);
|
2016-08-10 11:49:31 +02:00
|
|
|
reply(Status, Headers, Body, Req)
|
|
|
|
when is_integer(Status); is_binary(Status) ->
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
do_reply(Status, Headers#{
|
|
|
|
<<"content-length">> => integer_to_binary(iolist_size(Body))
|
|
|
|
}, Body, Req).
|
|
|
|
|
2016-08-10 11:49:31 +02:00
|
|
|
%% Don't send any body for HEAD responses. While the protocol code is
|
|
|
|
%% supposed to enforce this rule, we prefer to avoid copying too much
|
|
|
|
%% data around if we can avoid it.
|
|
|
|
do_reply(Status, Headers, _, Req=#{pid := Pid, streamid := StreamID, method := <<"HEAD">>}) ->
|
|
|
|
Pid ! {{Pid, StreamID}, {response, Status, response_headers(Headers, Req), <<>>}},
|
2016-08-10 17:15:02 +02:00
|
|
|
done_replying(Req, true);
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
do_reply(Status, Headers, Body, Req=#{pid := Pid, streamid := StreamID}) ->
|
|
|
|
Pid ! {{Pid, StreamID}, {response, Status, response_headers(Headers, Req), Body}},
|
2016-08-10 17:15:02 +02:00
|
|
|
done_replying(Req, true).
|
|
|
|
|
|
|
|
done_replying(Req, HasSentResp) ->
|
|
|
|
maps:without([resp_cookies, resp_headers, resp_body], Req#{has_sent_resp => HasSentResp}).
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
|
2016-08-10 11:49:31 +02:00
|
|
|
-spec stream_reply(cowboy:http_status(), Req) -> Req when Req::req().
|
|
|
|
stream_reply(Status, Req) ->
|
|
|
|
stream_reply(Status, #{}, Req).
|
2013-01-07 22:42:16 +01:00
|
|
|
|
2016-08-10 11:49:31 +02:00
|
|
|
-spec stream_reply(cowboy:http_status(), cowboy:http_headers(), Req)
|
2014-09-23 16:43:29 +03:00
|
|
|
-> Req when Req::req().
|
2016-08-10 17:15:02 +02:00
|
|
|
stream_reply(_, _, #{has_sent_resp := _}) ->
|
|
|
|
error(function_clause);
|
2016-08-10 11:49:31 +02:00
|
|
|
stream_reply(Status, Headers=#{}, Req=#{pid := Pid, streamid := StreamID})
|
|
|
|
when is_integer(Status); is_binary(Status) ->
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
Pid ! {{Pid, StreamID}, {headers, Status, response_headers(Headers, Req)}},
|
2016-08-10 17:15:02 +02:00
|
|
|
done_replying(Req, headers).
|
2011-05-08 17:26:21 +02:00
|
|
|
|
2018-11-09 17:42:37 +01:00
|
|
|
-spec stream_body(resp_body(), fin | nofin, req()) -> ok.
|
2016-08-10 17:15:02 +02:00
|
|
|
%% Error out if headers were not sent.
|
2016-08-10 11:49:31 +02:00
|
|
|
%% Don't send any body for HEAD responses.
|
2016-08-10 17:15:02 +02:00
|
|
|
stream_body(_, _, #{method := <<"HEAD">>, has_sent_resp := headers}) ->
|
2011-09-06 12:11:44 +02:00
|
|
|
ok;
|
2016-08-10 11:49:31 +02:00
|
|
|
%% Don't send a message if the data is empty, except for the
|
2018-11-09 17:42:37 +01:00
|
|
|
%% very last message with IsFin=fin. When using sendfile this
|
|
|
|
%% is converted to a data tuple, however.
|
|
|
|
stream_body({sendfile, _, 0, _}, nofin, _) ->
|
|
|
|
ok;
|
|
|
|
stream_body({sendfile, _, 0, _}, IsFin=fin,
|
|
|
|
#{pid := Pid, streamid := StreamID, has_sent_resp := headers}) ->
|
|
|
|
Pid ! {{Pid, StreamID}, {data, IsFin, <<>>}},
|
|
|
|
ok;
|
|
|
|
stream_body({sendfile, O, B, P}, IsFin,
|
|
|
|
#{pid := Pid, streamid := StreamID, has_sent_resp := headers})
|
|
|
|
when is_integer(O), O >= 0, is_integer(B), B > 0 ->
|
|
|
|
Pid ! {{Pid, StreamID}, {data, IsFin, {sendfile, O, B, P}}},
|
|
|
|
ok;
|
|
|
|
stream_body(Data, IsFin=nofin, #{pid := Pid, streamid := StreamID, has_sent_resp := headers})
|
|
|
|
when not is_tuple(Data) ->
|
2015-02-16 19:49:01 +01:00
|
|
|
case iolist_size(Data) of
|
|
|
|
0 -> ok;
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
_ ->
|
2016-08-10 11:49:31 +02:00
|
|
|
Pid ! {{Pid, StreamID}, {data, IsFin, Data}},
|
Initial commit with connection/streams
Breaking changes with previous commit. This is a very large change,
and I am giving up on making a single commit that fixes everything.
More commits will follow slowly adding back features, introducing
new tests and fixing the documentation.
This change contains most of the work toward unifying the interface
for handling both HTTP/1.1 and HTTP/2. HTTP/1.1 connections are now
no longer 1 process per connection; instead by default 1 process per
request is also created. This has a number of pros and cons.
Because it has cons, we also allow users to use a lower-level API
that acts on "streams" (requests/responses) directly at the connection
process-level. If performance is a concern, one can always write a
stream handler. The performance in this case will be even greater
than with Cowboy 1, although all the special handlers are unavailable.
When switching to Websocket, after the handler returns from init/2,
Cowboy stops the stream and the Websocket protocol takes over the
connection process. Websocket then calls websocket_init/2 for any
additional initialization such as timers, because the process is
different in init/2 and websocket_*/* functions. This however would
allow us to use websocket_init/2 for sending messages on connect,
instead of sending ourselves a message and be subject to races.
Note that websocket_init/2 is optional.
This is all a big change and while most of the tests pass, some
functionality currently doesn't. SPDY is broken and will be removed
soon in favor of HTTP/2. Automatic compression is currently disabled.
The cowboy_req interface probably still have a few functions that
need to be updated. The docs and examples do not refer the current
functionality anymore.
Everything will be fixed over time. Feedback is more than welcome.
Open a ticket!
2016-02-10 17:28:32 +01:00
|
|
|
ok
|
2016-08-10 11:49:31 +02:00
|
|
|
end;
|
2018-11-09 17:42:37 +01:00
|
|
|
stream_body(Data, IsFin, #{pid := Pid, streamid := StreamID, has_sent_resp := headers})
|
|
|
|
when not is_tuple(Data) ->
|
2016-08-10 11:49:31 +02:00
|
|
|
Pid ! {{Pid, StreamID}, {data, IsFin, Data}},
|
|
|
|
ok.
|
2013-08-24 11:20:14 +02:00
|
|
|
|
2018-06-25 15:56:29 +02:00
|
|
|
-spec stream_events(cow_sse:event() | [cow_sse:event()], fin | nofin, req()) -> ok.
|
|
|
|
stream_events(Event, IsFin, Req) when is_map(Event) ->
|
|
|
|
stream_events([Event], IsFin, Req);
|
|
|
|
stream_events(Events, IsFin, #{pid := Pid, streamid := StreamID, has_sent_resp := headers}) ->
|
|
|
|
Pid ! {{Pid, StreamID}, {data, IsFin, cow_sse:events(Events)}},
|
|
|
|
ok.
|
|
|
|
|
2017-11-15 14:58:49 +01:00
|
|
|
-spec stream_trailers(cowboy:http_headers(), req()) -> ok.
|
|
|
|
stream_trailers(Trailers, #{pid := Pid, streamid := StreamID, has_sent_resp := headers}) ->
|
|
|
|
Pid ! {{Pid, StreamID}, {trailers, Trailers}},
|
|
|
|
ok.
|
|
|
|
|
2018-10-31 10:50:57 +01:00
|
|
|
-spec push(iodata(), cowboy:http_headers(), req()) -> ok.
|
2016-08-10 11:49:31 +02:00
|
|
|
push(Path, Headers, Req) ->
|
|
|
|
push(Path, Headers, Req, #{}).
|
2014-07-12 12:09:43 +02:00
|
|
|
|
2016-08-10 11:49:31 +02:00
|
|
|
%% @todo Optimization: don't send anything at all for HTTP/1.0 and HTTP/1.1.
|
|
|
|
%% @todo Path, Headers, Opts, everything should be in proper binary,
|
|
|
|
%% or normalized when creating the Req object.
|
2017-01-02 16:47:16 +01:00
|
|
|
-spec push(iodata(), cowboy:http_headers(), req(), push_opts()) -> ok.
|
2016-08-10 11:49:31 +02:00
|
|
|
push(Path, Headers, #{pid := Pid, streamid := StreamID,
|
|
|
|
scheme := Scheme0, host := Host0, port := Port0}, Opts) ->
|
|
|
|
Method = maps:get(method, Opts, <<"GET">>),
|
|
|
|
Scheme = maps:get(scheme, Opts, Scheme0),
|
|
|
|
Host = maps:get(host, Opts, Host0),
|
|
|
|
Port = maps:get(port, Opts, Port0),
|
|
|
|
Qs = maps:get(qs, Opts, <<>>),
|
|
|
|
Pid ! {{Pid, StreamID}, {push, Method, Scheme, Host, Port, Path, Qs, Headers}},
|
2012-09-15 22:19:39 +02:00
|
|
|
ok.
|
|
|
|
|
2011-03-07 22:59:22 +01:00
|
|
|
%% Internal.
|
|
|
|
|
2016-08-10 11:49:31 +02:00
|
|
|
%% @todo What about set-cookie headers set through set_resp_header or reply?
|
2016-08-12 18:06:45 +02:00
|
|
|
-spec response_headers(Headers, req()) -> Headers when Headers::cowboy:http_headers().
|
2016-08-10 11:49:31 +02:00
|
|
|
response_headers(Headers0, Req) ->
|
|
|
|
RespHeaders = maps:get(resp_headers, Req, #{}),
|
|
|
|
Headers = maps:merge(#{
|
|
|
|
<<"date">> => cowboy_clock:rfc1123(),
|
|
|
|
<<"server">> => <<"Cowboy">>
|
|
|
|
}, maps:merge(RespHeaders, Headers0)),
|
|
|
|
%% The set-cookie header is special; we can only send one cookie per header.
|
|
|
|
%% We send the list of values for many cookies in one key of the map,
|
|
|
|
%% and let the protocols deal with it directly.
|
|
|
|
case maps:get(resp_cookies, Req, undefined) of
|
|
|
|
undefined -> Headers;
|
|
|
|
RespCookies -> Headers#{<<"set-cookie">> => maps:values(RespCookies)}
|
|
|
|
end.
|
2011-03-18 22:38:26 +01:00
|
|
|
|
2014-09-23 16:43:29 +03:00
|
|
|
%% Create map, convert keys to atoms and group duplicate keys into lists.
|
|
|
|
%% Keys that are not found in the user provided list are entirely skipped.
|
|
|
|
%% @todo Can probably be done directly while parsing.
|
2014-10-04 13:21:16 +03:00
|
|
|
kvlist_to_map(Fields, KvList) ->
|
2014-09-23 16:43:29 +03:00
|
|
|
Keys = [case K of
|
|
|
|
{Key, _} -> Key;
|
|
|
|
{Key, _, _} -> Key;
|
|
|
|
Key -> Key
|
|
|
|
end || K <- Fields],
|
2014-10-04 13:21:16 +03:00
|
|
|
kvlist_to_map(Keys, KvList, #{}).
|
2014-09-23 16:43:29 +03:00
|
|
|
|
2014-10-04 13:21:16 +03:00
|
|
|
kvlist_to_map(_, [], Map) ->
|
2014-09-23 16:43:29 +03:00
|
|
|
Map;
|
2014-10-04 13:21:16 +03:00
|
|
|
kvlist_to_map(Keys, [{Key, Value}|Tail], Map) ->
|
2014-09-23 16:43:29 +03:00
|
|
|
try binary_to_existing_atom(Key, utf8) of
|
|
|
|
Atom ->
|
|
|
|
case lists:member(Atom, Keys) of
|
|
|
|
true ->
|
|
|
|
case maps:find(Atom, Map) of
|
|
|
|
{ok, MapValue} when is_list(MapValue) ->
|
2014-10-04 13:21:16 +03:00
|
|
|
kvlist_to_map(Keys, Tail,
|
2015-07-27 17:32:05 +02:00
|
|
|
Map#{Atom => [Value|MapValue]});
|
2014-09-23 16:43:29 +03:00
|
|
|
{ok, MapValue} ->
|
2014-10-04 13:21:16 +03:00
|
|
|
kvlist_to_map(Keys, Tail,
|
2015-07-27 17:32:05 +02:00
|
|
|
Map#{Atom => [Value, MapValue]});
|
2014-09-23 16:43:29 +03:00
|
|
|
error ->
|
2014-10-04 13:21:16 +03:00
|
|
|
kvlist_to_map(Keys, Tail,
|
2015-07-27 17:32:05 +02:00
|
|
|
Map#{Atom => Value})
|
2014-09-23 16:43:29 +03:00
|
|
|
end;
|
|
|
|
false ->
|
2014-10-04 13:21:16 +03:00
|
|
|
kvlist_to_map(Keys, Tail, Map)
|
2014-09-23 16:43:29 +03:00
|
|
|
end
|
|
|
|
catch error:badarg ->
|
2014-10-04 13:21:16 +03:00
|
|
|
kvlist_to_map(Keys, Tail, Map)
|
2014-09-23 16:43:29 +03:00
|
|
|
end.
|
|
|
|
|
2017-07-01 16:10:27 +02:00
|
|
|
filter(Fields, Map0) ->
|
2017-09-27 16:20:38 +02:00
|
|
|
filter(Fields, Map0, #{}).
|
2017-07-01 16:10:27 +02:00
|
|
|
|
|
|
|
%% Loop through fields, if value is missing and no default,
|
|
|
|
%% record the error; else if value is missing and has a
|
|
|
|
%% default, set default; otherwise apply constraints. If
|
|
|
|
%% constraint fails, record the error.
|
|
|
|
%%
|
|
|
|
%% When there is an error at the end, crash.
|
|
|
|
filter([], Map, Errors) ->
|
|
|
|
case maps:size(Errors) of
|
|
|
|
0 -> {ok, Map};
|
|
|
|
_ -> {error, Errors}
|
|
|
|
end;
|
|
|
|
filter([{Key, Constraints}|Tail], Map, Errors) ->
|
|
|
|
filter_constraints(Tail, Map, Errors, Key, maps:get(Key, Map), Constraints);
|
|
|
|
filter([{Key, Constraints, Default}|Tail], Map, Errors) ->
|
2014-09-23 16:43:29 +03:00
|
|
|
case maps:find(Key, Map) of
|
|
|
|
{ok, Value} ->
|
2017-07-01 16:10:27 +02:00
|
|
|
filter_constraints(Tail, Map, Errors, Key, Value, Constraints);
|
2014-09-23 16:43:29 +03:00
|
|
|
error ->
|
2017-07-01 16:10:27 +02:00
|
|
|
filter(Tail, Map#{Key => Default}, Errors)
|
2014-09-23 16:43:29 +03:00
|
|
|
end;
|
2017-07-01 16:10:27 +02:00
|
|
|
filter([Key|Tail], Map, Errors) ->
|
|
|
|
case maps:is_key(Key, Map) of
|
|
|
|
true ->
|
|
|
|
filter(Tail, Map, Errors);
|
|
|
|
false ->
|
|
|
|
filter(Tail, Map, Errors#{Key => required})
|
|
|
|
end.
|
2014-09-23 16:43:29 +03:00
|
|
|
|
2017-07-01 16:10:27 +02:00
|
|
|
filter_constraints(Tail, Map, Errors, Key, Value0, Constraints) ->
|
2017-06-28 17:38:17 +02:00
|
|
|
case cowboy_constraints:validate(Value0, Constraints) of
|
|
|
|
{ok, Value} ->
|
2017-07-01 16:10:27 +02:00
|
|
|
filter(Tail, Map#{Key => Value}, Errors);
|
2017-06-28 17:38:17 +02:00
|
|
|
{error, Reason} ->
|
2017-07-01 16:10:27 +02:00
|
|
|
filter(Tail, Map, Errors#{Key => Reason})
|
2014-09-23 16:43:29 +03:00
|
|
|
end.
|