From 58e9e76814a8291894ba01ac8a4551e4f8d480b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Mon, 4 Sep 2017 14:33:44 +0200 Subject: Fix more documentation todos I have decided not to include a manual page for cowboy_stream_h at this point because it clashes with the cowboy_stream manual page. This decision will be revisited in the future. --- doc/src/guide/book.asciidoc | 2 - doc/src/guide/loop_handlers.asciidoc | 2 - doc/src/guide/modern_web.asciidoc | 25 ++++----- doc/src/guide/ws_handlers.asciidoc | 6 +-- doc/src/manual/cowboy.start_clear.asciidoc | 10 ++-- doc/src/manual/cowboy.start_tls.asciidoc | 10 ++-- doc/src/manual/cowboy_app.asciidoc | 6 +-- doc/src/manual/cowboy_constraints.asciidoc | 60 +++++++++++++++++++++ doc/src/manual/cowboy_constraints.int.asciidoc | 63 ++++++++++++++++++++++ .../manual/cowboy_constraints.nonempty.asciidoc | 62 +++++++++++++++++++++ doc/src/manual/cowboy_handler.terminate.asciidoc | 18 +++---- doc/src/manual/cowboy_websocket.asciidoc | 8 +-- src/cowboy_constraints.erl | 6 +-- src/cowboy_handler.erl | 2 +- 14 files changed, 225 insertions(+), 55 deletions(-) create mode 100644 doc/src/manual/cowboy_constraints.asciidoc create mode 100644 doc/src/manual/cowboy_constraints.int.asciidoc create mode 100644 doc/src/manual/cowboy_constraints.nonempty.asciidoc diff --git a/doc/src/guide/book.asciidoc b/doc/src/guide/book.asciidoc index 98e2d83..39e70d2 100644 --- a/doc/src/guide/book.asciidoc +++ b/doc/src/guide/book.asciidoc @@ -75,6 +75,4 @@ include::middlewares.asciidoc[Middlewares] include::migrating_from_1.0.asciidoc[Migrating from Cowboy 1.0 to 2.0] -// @todo Maybe history? Could take info from architecture also. - include::specs.asciidoc[HTTP and other specifications] diff --git a/doc/src/guide/loop_handlers.asciidoc b/doc/src/guide/loop_handlers.asciidoc index 80bc484..21bf842 100644 --- a/doc/src/guide/loop_handlers.asciidoc +++ b/doc/src/guide/loop_handlers.asciidoc @@ -1,8 +1,6 @@ [[loop_handlers]] == Loop handlers -// @todo This description needs to be updated. - Loop handlers are a special kind of HTTP handlers used when the response can not be sent right away. The handler enters instead a receive loop waiting for the right message before it can send diff --git a/doc/src/guide/modern_web.asciidoc b/doc/src/guide/modern_web.asciidoc index 6c43adb..4852573 100644 --- a/doc/src/guide/modern_web.asciidoc +++ b/doc/src/guide/modern_web.asciidoc @@ -1,8 +1,6 @@ [[modern_web]] == The modern Web -// @todo Link to related xrefs. - Cowboy is a server for the modern Web. This chapter explains what it means and details all the standards involved. @@ -56,9 +54,9 @@ methods, status codes, headers or semantics. === Websocket -Websocket is a protocol built on top of HTTP/1.1 that provides -a two-ways communication channel between the client and the -server. Communication is asynchronous and can occur concurrently. +xref:ws_protocol[Websocket] is a protocol built on top of HTTP/1.1 +that provides a two-ways communication channel between the client and +the server. Communication is asynchronous and can occur concurrently. It consists of a Javascript object allowing setting up a Websocket connection to the server, and a binary based @@ -79,6 +77,9 @@ is closer to TCP in that aspect, and requires you to design and implement your own protocol on top of it; or adapt an existing protocol to Websocket. +Cowboy provides an interface known as xref:ws_handlers[Websocket handlers] +that gives complete control over a Websocket connection. + The Websocket protocol is defined by RFC 6455. === Long-lived requests @@ -101,21 +102,21 @@ type, `text/event-stream`, along with a new HTTP header, `Last-Event-ID`. It is defined in the EventSource W3C specification. -Cowboy provides an interface known as loop handlers that -facilitates the implementation of long-polling or stream +Cowboy provides an interface known as xref:loop_handlers[loop handlers] +that facilitates the implementation of long-polling or stream mechanisms. It works regardless of the underlying protocol. === REST -REST, or REpresentational State Transfer, is a style of -architecture for loosely connected distributed systems. -It can easily be implemented on top of HTTP. +xref:rest_principles[REST, or REpresentational State Transfer], +is a style of architecture for loosely connected distributed +systems. It can easily be implemented on top of HTTP. REST is essentially a set of constraints to be followed. Many of these constraints are purely architectural and solved by simply using HTTP. Some constraints must be explicitly followed by the developer. -Cowboy provides an interface known as REST handlers that -simplifies the implementation of a REST API on top of +Cowboy provides an interface known as xref:rest_handlers[REST handlers] +that simplifies the implementation of a REST API on top of the HTTP protocol. diff --git a/doc/src/guide/ws_handlers.asciidoc b/doc/src/guide/ws_handlers.asciidoc index 61a523b..84dfb9b 100644 --- a/doc/src/guide/ws_handlers.asciidoc +++ b/doc/src/guide/ws_handlers.asciidoc @@ -151,7 +151,9 @@ websocket_info(_Info, State) -> === Sending frames -// @todo So yeah, reply makes no sense. Maybe change it to send. Sigh. +// @todo This will be deprecated and eventually replaced with a +// {Commands, State} interface that allows providing more +// functionality easily. All `websocket_` callbacks share return values. They may send zero, one or many frames to the client. @@ -222,8 +224,6 @@ init(Req, State) -> This value cannot be changed once it is set. It defaults to `60000`. -// @todo Perhaps the default should be changed. - === Saving memory The Websocket connection process can be set to hibernate diff --git a/doc/src/manual/cowboy.start_clear.asciidoc b/doc/src/manual/cowboy.start_clear.asciidoc index 7a12a58..3d09935 100644 --- a/doc/src/manual/cowboy.start_clear.asciidoc +++ b/doc/src/manual/cowboy.start_clear.asciidoc @@ -47,16 +47,12 @@ ProtocolOpts:: The protocol options are in a map containing all the options for the different protocols that may be involved when connecting -to the listener, including HTTP/1.1 and HTTP/2 but also -subprotocols like Websocket. -// @todo For Websocket this might change in the future. +to the listener, including HTTP/1.1 and HTTP/2. + The HTTP/1.1 options are documented in the link:man:cowboy_http(3)[cowboy_http(3)] manual; -the HTTP/2 options in -link:man:cowboy_http2(3)[cowboy_http2(3)]; -and the Websocket options in -link:man:cowboy_websocket(3)[cowboy_websocket(3)]. +and the HTTP/2 options in +link:man:cowboy_http2(3)[cowboy_http2(3)]. == Return value diff --git a/doc/src/manual/cowboy.start_tls.asciidoc b/doc/src/manual/cowboy.start_tls.asciidoc index 1cf87c9..8d2131a 100644 --- a/doc/src/manual/cowboy.start_tls.asciidoc +++ b/doc/src/manual/cowboy.start_tls.asciidoc @@ -47,16 +47,12 @@ ProtocolOpts:: The protocol options are in a map containing all the options for the different protocols that may be involved when connecting -to the listener, including HTTP/1.1 and HTTP/2 but also -subprotocols like Websocket. -// @todo For Websocket this might change in the future. +to the listener, including HTTP/1.1 and HTTP/2. + The HTTP/1.1 options are documented in the link:man:cowboy_http(3)[cowboy_http(3)] manual; -the HTTP/2 options in -link:man:cowboy_http2(3)[cowboy_http2(3)]; -and the Websocket options in -link:man:cowboy_websocket(3)[cowboy_websocket(3)]. +and the HTTP/2 options in +link:man:cowboy_http2(3)[cowboy_http2(3)]. == Return value diff --git a/doc/src/manual/cowboy_app.asciidoc b/doc/src/manual/cowboy_app.asciidoc index bc67959..5825cf9 100644 --- a/doc/src/manual/cowboy_app.asciidoc +++ b/doc/src/manual/cowboy_app.asciidoc @@ -20,8 +20,7 @@ Functions: * link:man:cowboy(3)[cowboy(3)] - Listener management * link:man:cowboy_req(3)[cowboy_req(3)] - Request and response * link:man:cowboy_router(3)[cowboy_router(3)] - Router - -// @todo What about cowboy_constraints? +* link:man:cowboy_constraints(3)[cowboy_constraints(3)] - Constraints Protocols: @@ -33,9 +32,6 @@ Handlers: * link:man:cowboy_static(3)[cowboy_static(3)] - Static file handler -// @todo What about cowboy_stream_h? -// @todo cowboy_compress_h - Behaviors: * link:man:cowboy_handler(3)[cowboy_handler(3)] - Plain HTTP handlers diff --git a/doc/src/manual/cowboy_constraints.asciidoc b/doc/src/manual/cowboy_constraints.asciidoc new file mode 100644 index 0000000..52ee664 --- /dev/null +++ b/doc/src/manual/cowboy_constraints.asciidoc @@ -0,0 +1,60 @@ += cowboy_constraints(3) + +== Name + +cowboy_constraints - Constraints + +== Description + +The module `cowboy_constraints` defines the built-in +constraints in Cowboy and provides an interface for +manipulating these constraints. + +Constraints are functions that define what type of +input is allowed. They are used throughout Cowboy, +from the router to query strings to cookies. + +== Exports + +Built-in constraints: + +* link:man:cowboy_constraints:int(3)[cowboy_constraints:int(3)] - Integer constraint +* link:man:cowboy_constraints:nonempty(3)[cowboy_constraints:nonempty(3)] - Non-empty constraint + +== Types + +=== constraint() + +[source,erlang] +---- +constraint() :: int | nonempty | fun() +---- + +A constraint function. + +The atom constraints are built-in, see the corresponding +function in the exports list above. + +=== reason() + +[source,erlang] +---- +reason() :: {constraint(), Reason, Value} + +Reason :: any() +Value :: any() +---- + +Reason for the constraint failure. + +It includes the constraint function in question, +a machine-readable error reason and the value that +made the constraint fail. + +== See also + +link:man:cowboy(7)[cowboy(7)], +link:man:cowboy(3)[cowboy(3)], +link:man:cowboy_router(3)[cowboy_router(3)], +link:man:cowboy_req:match_cookies(3)[cowboy_req:match_cookies(3)], +link:man:cowboy_req:match_qs(3)[cowboy_req:match_qs(3)] diff --git a/doc/src/manual/cowboy_constraints.int.asciidoc b/doc/src/manual/cowboy_constraints.int.asciidoc new file mode 100644 index 0000000..28855a4 --- /dev/null +++ b/doc/src/manual/cowboy_constraints.int.asciidoc @@ -0,0 +1,63 @@ += cowboy_constraints:int(3) + +== Name + +cowboy_constraints:int - Integer constraint + +== Description + +Constraint functions implement a number of different operations. + +[source,erlang] +---- +int(forward, Bin) -> {ok, Int} | {error, not_an_integer} + +Bin :: binary() +Int :: integer() +---- + +Validate and convert the text representation of an integer. + +[source,erlang] +---- +int(reverse, Int) -> {ok, Bin} | {error, not_an_integer} +---- + +Convert an integer back to its text representation. + +[source,erlang] +---- +int(format_error, Error) -> HumanReadable + +Error :: {not_an_integer, Bin | Int} +HumanReadable :: iolist() +---- + +Generate a human-readable error message. + +== Arguments + +Arguments vary depending on the operation. Constraint +functions always take the operation type as first argument, +and the value as second argument. + +== Return value + +The return value varies depending on the operation. + +== Changelog + +* *2.0*: Interface modified to allow for a variety of operations. +* *1.0*: Constraint introduced. + +== Examples + +This function is not meant to be called directly. + +== See also + +link:man:cowboy_constraints(3)[cowboy_constraints(3)], +link:man:cowboy_constraints:nonempty(3)[cowboy_constraints:nonempty(3)], +link:man:cowboy_router(3)[cowboy_router(3)], +link:man:cowboy_req:match_cookies(3)[cowboy_req:match_cookies(3)], +link:man:cowboy_req:match_qs(3)[cowboy_req:match_qs(3)] diff --git a/doc/src/manual/cowboy_constraints.nonempty.asciidoc b/doc/src/manual/cowboy_constraints.nonempty.asciidoc new file mode 100644 index 0000000..0c25b4b --- /dev/null +++ b/doc/src/manual/cowboy_constraints.nonempty.asciidoc @@ -0,0 +1,62 @@ += cowboy_constraints:nonempty(3) + +== Name + +cowboy_constraints:nonempty - Non-empty constraint + +== Description + +Constraint functions implement a number of different operations. + +[source,erlang] +---- +nonempty(forward | reverse, <<>>) -> {error, empty} +---- + +Reject empty values. + +[source,erlang] +---- +nonempty(forward | reverse, Bin) -> {ok, Bin} + +Bin :: binary() +---- + +Accept any other binary values. + +[source,erlang] +---- +nonempty(format_error, Error) -> HumanReadable + +Error :: {empty, Bin} +HumanReadable :: iolist() +---- + +Generate a human-readable error message. + +== Arguments + +Arguments vary depending on the operation. Constraint +functions always take the operation type as first argument, +and the value as second argument. + +== Return value + +The return value varies depending on the operation. + +== Changelog + +* *2.0*: Interface modified to allow for a variety of operations. +* *1.0*: Constraint introduced. + +== Examples + +This function is not meant to be called directly. + +== See also + +link:man:cowboy_constraints(3)[cowboy_constraints(3)], +link:man:cowboy_constraints:int(3)[cowboy_constraints:int(3)], +link:man:cowboy_router(3)[cowboy_router(3)], +link:man:cowboy_req:match_cookies(3)[cowboy_req:match_cookies(3)], +link:man:cowboy_req:match_qs(3)[cowboy_req:match_qs(3)] diff --git a/doc/src/manual/cowboy_handler.terminate.asciidoc b/doc/src/manual/cowboy_handler.terminate.asciidoc index f10d945..c995ba3 100644 --- a/doc/src/manual/cowboy_handler.terminate.asciidoc +++ b/doc/src/manual/cowboy_handler.terminate.asciidoc @@ -8,12 +8,12 @@ cowboy_handler:terminate - Terminate the handler [source,erlang] ---- -terminate(Reason, Req | undefined, State, Handler) -> ok +terminate(Reason, PartialReq, State, Handler) -> ok -Reason :: any() -Req :: cowboy_req:req() -State :: any() -Handler :: module() +Reason :: any() +PartialReq :: map() +State :: any() +Handler :: module() ---- Call the optional terminate callback if it is defined. @@ -27,13 +27,13 @@ Reason:: Reason for termination. -Req:: +PartialReq:: The Req object. + -It is possible to pass `undefined` if the handler has no concept -of requests/responses and discarded the Req object before calling -this function. +It is possible to remove fields from the Req object to save memory +when the handler has no concept of requests/responses. The only +requirement is that a map is provided. State:: diff --git a/doc/src/manual/cowboy_websocket.asciidoc b/doc/src/manual/cowboy_websocket.asciidoc index 7979b97..2421ae8 100644 --- a/doc/src/manual/cowboy_websocket.asciidoc +++ b/doc/src/manual/cowboy_websocket.asciidoc @@ -25,9 +25,10 @@ websocket_init(State) -> CallResult %% optional websocket_handle(InFrame, State) -> CallResult websocket_info(Info, State) -> CallResult -terminate(Reason, undefined, State) -> ok %% optional +terminate(Reason, PartialReq, State) -> ok %% optional Req :: cowboy_req:req() +PartialReq :: map() State :: any() Opts :: cowboy_websocket:opts() InFrame :: {text | binary | ping | pong, binary()} @@ -74,9 +75,8 @@ tuple). The optional `terminate/3` callback will ultimately be called with the reason for the termination of the connection. This -callback is common to all handlers. Note that Websocket has -no concept of requests so it sets the second argument to -undefined. +callback is common to all handlers. Note that Websocket will +not provide the full Req object by default, to save memory. Cowboy will terminate the process right after closing the Websocket connection. This means that there is no need to diff --git a/src/cowboy_constraints.erl b/src/cowboy_constraints.erl index 6b468fe..6509c4b 100644 --- a/src/cowboy_constraints.erl +++ b/src/cowboy_constraints.erl @@ -78,11 +78,11 @@ int(format_error, {not_an_integer, Value}) -> io_lib:format("The value ~p is not an integer.", [Value]). nonempty(Type, <<>>) when Type =/= format_error -> - {error, not_empty}; + {error, empty}; nonempty(Type, Value) when Type =/= format_error, is_binary(Value) -> {ok, Value}; -nonempty(format_error, {not_empty, Value}) -> - io_lib:format("The value ~p is not empty.", [Value]). +nonempty(format_error, {empty, Value}) -> + io_lib:format("The value ~p is empty.", [Value]). -ifdef(TEST). diff --git a/src/cowboy_handler.erl b/src/cowboy_handler.erl index 3249f76..3d509b6 100644 --- a/src/cowboy_handler.erl +++ b/src/cowboy_handler.erl @@ -28,7 +28,7 @@ | {module(), Req, any(), any()} when Req::cowboy_req:req(). --callback terminate(any(), cowboy_req:req(), any()) -> ok. +-callback terminate(any(), map(), any()) -> ok. -optional_callbacks([terminate/3]). -spec execute(Req, Env) -> {ok, Req, Env} -- cgit v1.2.3