diff --git a/CHANGELOG.md b/CHANGELOG.md index e2e21590..63c260b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ Version 71: * Fix extra ; warning +* Documentation revision -------------------------------------------------------------------------------- diff --git a/README.md b/README.md index eac10c81..9cb3ec34 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,7 @@ cmake -G Xcode .. # for Apple Xcode builds cd .. mkdir bin64 -cd ../bin64 +cd bin64 cmake -G"Visual Studio 14 2015 Win64" .. # for 64-bit Windows builds (VS2015) cmake -G"Visual Studio 15 2017 Win64" .. # for 64-bit Windows builds (VS2017) diff --git a/doc/3_3_buffers.qbk b/doc/3_3_buffers.qbk index 52972591..21d9df3e 100644 --- a/doc/3_3_buffers.qbk +++ b/doc/3_3_buffers.qbk @@ -97,7 +97,7 @@ lightweight iterators over the existing, unmodified memory buffers. Control of buffers is retained by the caller; ownership is not transferred. -[table Buffer Algorithms +[table Buffer Algorithms and Types [[Name][Description]] [[ [link beast.ref.beast__buffer_cat `buffer_cat`] @@ -126,7 +126,7 @@ transferred. ][ This class represents the buffer sequence formed from a prefix of an existing buffer sequence. This is the type of buffer returned by - [link beast.ref.beast__buffer_prefix `buffer_prefix`]. + [link beast.ref.beast__buffer_prefix.overload3 `buffer_prefix`]. ]] [[ [link beast.ref.beast__consuming_buffers `consuming_buffers`] diff --git a/doc/5_05_parser_streams.qbk b/doc/5_05_parser_streams.qbk index 2f481eb0..d9c9937a 100644 --- a/doc/5_05_parser_streams.qbk +++ b/doc/5_05_parser_streams.qbk @@ -22,7 +22,7 @@ at once, such as: These types of operations require callers to manage the lifetime of associated state, by constructing a class derived from __basic_parser__. Beast comes with the derived instance __parser__ which creates complete -__message__ objects; user-defined parsers are also possible: +__message__ objects using the __basic_fields__ Fields container. [table Parser [[Name][Description]] @@ -32,9 +32,9 @@ __message__ objects; user-defined parsers are also possible: ``` /// An HTTP/1 parser for producing a message. template< - bool isRequest, // `true` to parse an HTTP request - class Body, // The Body type for the resulting message - class Fields = fields> // The type of container representing the fields + bool isRequest, // `true` to parse an HTTP request + class Body, // The Body type for the resulting message + class Allocator = std::allocator> // The type of allocator for the header class parser : public basic_parser<...>; ``` @@ -44,8 +44,8 @@ __message__ objects; user-defined parsers are also possible: ][ ``` /// An HTTP/1 parser for producing a request message. - template - using request_parser = parser; + template> + using request_parser = parser; ``` ]] [[ @@ -53,8 +53,8 @@ __message__ objects; user-defined parsers are also possible: ][ ``` /// An HTTP/1 parser for producing a response message. - template - using response_parser = parser; + template> + using response_parser = parser; ``` ]] ] diff --git a/doc/5_09_custom_parsers.qbk b/doc/5_09_custom_parsers.qbk index fbecba3e..610dc167 100644 --- a/doc/5_09_custom_parsers.qbk +++ b/doc/5_09_custom_parsers.qbk @@ -9,11 +9,11 @@ While the parsers included in the library will handle a broad number of use-cases, the __basic_parser__ interface can be subclassed to implement -custom parsing strategies: the parser processes the incoming octets into -elements according to the HTTP/1 protocol specification, while the derived -class decides what to do with those elements. In particular, users who -create exotic containers for [*Fields] may need to also create their own -parser. Custom parsers will work with all of the stream read operations +custom parsing strategies: the basic parser processes the incoming octets +into elements according to the HTTP/1 protocol specification, while the +derived class decides what to do with those elements. In particular, users +who create exotic containers for [*Fields] may need to also create their +own parser. Custom parsers will work with all of the stream read operations that work on parsers, as those algorithms use only the basic parser interface. Some use cases for implementing custom parsers are: diff --git a/doc/7_6_control.qbk b/doc/7_6_control.qbk index d39f4f08..fb1de84d 100644 --- a/doc/7_6_control.qbk +++ b/doc/7_6_control.qbk @@ -22,10 +22,10 @@ The connection is considered gracefully closed when each side has sent and received a close frame. During read operations, Beast automatically reads and processes control -frames. Pings are replied to as soon as possible with a pong, received -ping and pongs are delivered to the ping callback. The receipt of a close -frame initiates the WebSocket close procedure, eventually resulting in the -error code +frames. If a control callback is registered, the callback is notified of +the incoming control frame. The implementation will respond to pings +automatically. The receipt of a close frame initiates the WebSocket +close procedure, eventually resulting in the error code [link beast.ref.beast__websocket__error `error::closed`] being delivered to the caller in a subsequent read operation, assuming no other error takes place. @@ -35,36 +35,39 @@ operations can cause socket writes. However, these writes will not compete with caller-initiated write operations. For the purposes of correctness with respect to the stream invariants, caller-initiated read operations still only count as a read. This means that callers can -have a simultaneously active read, write, and ping operation in progress, -while the implementation also automatically handles control frames. +have a simultaneously active read, write, and ping/pong operation in +progress, while the implementation also automatically handles control +frames. [heading Control Callback] -Ping and pong messages are control frames which may be sent at any time -by either peer on an established WebSocket connection. They are sent -using the functions -[link beast.ref.beast__websocket__stream.ping `ping`] and +Ping, pong, and close messages are control frames which may be sent at +any time by either peer on an established WebSocket connection. They +are sent using the functions +[link beast.ref.beast__websocket__stream.ping `ping`], [link beast.ref.beast__websocket__stream.pong `pong`]. -To be notified of control frames, including pings, pongs, and close frames, -callers may register a ['control callback] using +and +[link beast.ref.beast__websocket__stream.close `close`]. +To be notified of control frames, callers may register a +['control callback] using [link beast.ref.beast__websocket__stream.control_callback `control_callback`]. The object provided with this option should be callable with the following signature: [ws_snippet_17] -When a ping callback is registered, all pings and pongs received through -either synchronous read functions or asynchronous read functions will -invoke the ping callback, with the value of `is_pong` set to `true` if a -pong was received or `false` otherwise. The payload of the ping or pong -control frame is passed in the payload argument. +When a control callback is registered, it will be invoked for all pings, +pongs, and close frames received through either synchronous read functions +or asynchronous read functions. The type of frame and payload text are +passed as parameters to the control callback. If the frame is a close +frame, the close reason may be obtained by calling +[link beast.ref.beast__websocket__stream.reason `reason`]. Unlike regular completion handlers used in calls to asynchronous initiation -functions, the ping callback only needs to be set once. The callback is not -reset when a ping or pong is received. The same callback is used for both -synchronous and asynchronous reads. The ping callback is passive; in order -to receive pings and pongs, a synchronous or asynchronous stream read -function must be active. +functions, the control callback only needs to be set once. The callback is +not reset after being called. The same callback is used for both synchronous +and asynchronous reads. The callback is passive; in order to be called, +a stream read operation must be active. [note When an asynchronous read function receives a control frame, the diff --git a/doc/9_1_http_message.qbk b/doc/9_1_http_message.qbk index 8910493c..53a57934 100644 --- a/doc/9_1_http_message.qbk +++ b/doc/9_1_http_message.qbk @@ -124,8 +124,22 @@ void f(message& msg); ``` This function can manipulate the fields common to requests and responses. -If it needs to access the other fields, it can do so using tag dispatch -with an object of type `std::integral_constant`. +If it needs to access the other fields, it can use overloads with +partial specialization, or in C++17 a `constexpr` expression: +``` +template +void f(message& msg) +{ + if constexpr(isRequest) + { + // call msg.method(), msg.target() + } + else + { + // call msg.result(), msg.reason() + } +} +``` Often, in non-trivial HTTP applications, we want to read the HTTP header and examine its contents before choosing a type for [*Body]. To accomplish diff --git a/doc/9_4_faq.qbk b/doc/9_4_faq.qbk index dec58392..9d2f4dfd 100644 --- a/doc/9_4_faq.qbk +++ b/doc/9_4_faq.qbk @@ -24,36 +24,33 @@ about Beast and other HTTP libraries that have gone through formal review. [[ "Beast does not offer an HTTP server?" ][ - The scope of the library is to provide a message container, - and serialization and deserialization algorithms, with an - interface permitting users to achieve all the behaviors - necessary to implement high performance, conforming servers. - However, management of listening sockets, io_service threads, - individual connections, and HTTP semantics such as pipelining, - redirection, Expect: 100-continue, cookies, and request routing - are not handled by Beast. - It is the author's position that keeping the library low-level - will establish it as a building block which the greater C++ - community at large can leverage to produce higher level - libraries competing with each other to figure out the best - way to solve these problems. + Beast has a functional HTTP server in the example directory. The + server supports both HTTP and WebSocket using synchronous and + asynchronous shared or dedicated ports. In addition, the server + supports encrypted TLS connections if OpenSSL is available, on + dedicated ports. And the server comes with a "multi-port", a + flexible single port which supports both encrypted and unencrypted + connections, both HTTP and WebSocket, all on the same port. The + server is not part of Beast's public interfaces, as that + functionality is outside the scope of the library. The author + feels that attempting to broaden the scope of the library will + reduce its appeal for standardization. ]] [[ "Beast does not offer an HTTP client?" ][ "I just want to download a resource using HTTP" is a common cry from users and reviewers. Such functionality is beyond - the scope of Beast and will likely never be added. Building - a robust HTTP client is a difficult task. The source code for - such a client would probably be several times larger than - the entirety of Beast! There are many things to deal with - such as the various message body encodings, complex parsing - of headers, difficult header semantics such as Range and - Cache-Control, redirection, Expect:100-continue, connection - retrying, domain name resolution, TLS, and much, much more. - It is the author's position that Boost first needs a common - set of nouns and verbs for manipulating HTTP at the protocol - level; Beast provides that language. + the scope of Beast. Building a full featured HTTP client is + a difficult task and large enough to deserve its own library. + There are many things to deal with such as the various message + body encodings, complex parsing of headers, difficult header + semantics such as Range and Cache-Control, redirection, + Expect:100-continue, connection retrying, domain name + resolution, TLS, and much, much more. It is the author's + position that Boost first needs a common set of nouns and + verbs for manipulating HTTP at the protocol level; Beast + provides that language. ]] [[ "There's no HTTP/2 support yet!" @@ -86,17 +83,15 @@ about Beast and other HTTP libraries that have gone through formal review. [[ "This should work with standalone-Asio!" ][ - Beast uses more than Boost.Asio, it depends on a smattering - of various parts of Boost. The standalone Asio is currently - farther ahead than the Boost version. Keeping Beast maintained - against both versions of Asio is beyond the resources of the - author at the present time. Compatibility with non-Boost - libraries should not be an acceptance criteria. Beast is - currently designed to be a part of Boost: nothing more, - nothing less. - Looking at the bigger picture, it is the author's goal to - propose this library for standardization. A logical track for - achieving this is as follows: + Beast uses more than Boost.Asio, it depends on various other parts + of Boost. The standalone Asio is currently farther ahead than the + Boost version. Keeping Beast maintained against both versions of + Asio is beyond the resources of the author at the present time. + Compatibility with non-Boost libraries should not be an acceptance + criteria. Beast is currently designed to be a part of Boost: + nothing more, nothing less. Looking at the bigger picture, it + is the author's goal to propose this library for standardization. + A logical track for achieving this is as follows: [ordered_list [ @@ -130,7 +125,9 @@ about Beast and other HTTP libraries that have gone through formal review. As the library matures it will undergo optimization passes; benchmarks will logically accompany this process. There is a small benchmarking program included in the tests which compares the performance of - Beast's parser to the NodeJS reference parser. + Beast's parser to the NodeJS reference parser, as well as some + benchmarks which compare the performance of various Beast dynamic + buffer implementations against Asio's. ]] [[ "Beast is a terrible name!" @@ -164,12 +161,13 @@ about Beast and other HTTP libraries that have gone through formal review. "Some more advanced examples, e.g. including TLS with client/server certificates would help." ][ - The HTTP interface doesn't try to reinvent the wheel, it just uses - the `boost::asio::ip::tcp::socket` or `boost::asio::ssl::stream` that - you set up beforehand. Callers use the interfaces already existing - on those objects to make outgoing connections, accept incoming connections, - or establish TLS sessions with certificates. We find the available Asio - examples for performing these tasks sufficient. + The server-framework example demonstrates how to implement a server + that supports TLS using certificates. There are also websocket and + HTTP client examples which use TLS. Furthermore, management of + certificates is beyond the scope of the public interfaces of the + library. Asio already provides documentation, interfaces, and + examples for performing these tasks - Beast does not intend to + reinvent them or to redundantly provide this information. ]] [[ @@ -178,14 +176,17 @@ about Beast and other HTTP libraries that have gone through formal review. We presume this means a facility to match expressions against the URI in HTTP requests, and dispatch them to calling code. The authors feel that this is a responsibility of higher level code. Beast does - not try to offer a web server. + not try to offer a web server. That said, the server-framework + example has a concept of request routing called a Service. Two + services are provided, one for serving files and the other for + handling WebSocket upgrade requests. ]] [[ "HTTP Cookies? Forms/File Uploads?" ][ Cookies, or managing these types of HTTP headers in general, is the - responsibility of higher levels. Beast.HTTP just tries to get complete + responsibility of higher levels. Beast just tries to get complete messages to and from the calling code. It deals in the HTTP headers just enough to process the message body and leaves the rest to callers. However, for forms and file uploads the symmetric interface of the message class @@ -197,11 +198,8 @@ about Beast and other HTTP libraries that have gone through formal review. "...supporting TLS (is this a feature? If not this would be a show-stopper), etc." ][ - Beast does not provide direct facilities for implementing TLS connections; - however, the interfaces already existing on the `boost::asio::ssl::stream` - are available and can be used to establish secure connections. Then, - functions like `http::read` or `http::async_write` can work with those - encrypted connections with no problem. + Beast works with the Stream concept, so it automatically works with the + `boost::asio::ssl::stream` that you have already set up through Asio. ]] [[ @@ -215,18 +213,18 @@ about Beast and other HTTP libraries that have gone through formal review. which higher abstractions such as the aforementioned HTTP service or cgi-gateway can be built. - One of the example programs implements a simple HTTP server that - delivers files from the filesystem. + There are several HTTP servers in the example directory which deliver + files, as well as some tested and compiled code snippets which can be + used as a starting point for interfacing with other processes. ]] [[ "You should send a 100-continue to ask for the rest of the body if required." ][ - The Beast interface supports this functionality (by allowing this - special case of "split" message parsing and serialization). Specifically, - it lets callers read the request up to just before the body, - and let callers write the request up to just before the body. However, - making use of this behavior is up to callers (since Beast is low level). + Deciding on whether to send the "Expect: 100-continue" header or + how to handle it on the server side is the caller's responsibility; + Beast provides the functionality to send or inspect the header before + sending or reading the body. ]] @@ -236,13 +234,18 @@ about Beast and other HTTP libraries that have gone through formal review. in production. That would give some evidence that the design works in practice." ][ - Beast.HTTP and Beast.WebSocket are production ready and currently - running on public servers receiving traffic and handling millions of - dollars' worth of financial transactions daily. The servers run [*rippled], - open source software ([@https://github.com/ripple/rippled repository]) + Beast has already been on public servers receiving traffic and handling + hundreds of millions of dollars' worth of financial transactions daily. + The servers run [*rippled], open source software + ([@https://github.com/ripple/rippled repository]) implementing the [@https://ripple.com/files/ripple_consensus_whitepaper.pdf [*Ripple Consensus Protocol]], technology provided by [@http://ripple.com Ripple]. + + Furthermore, the repository has grown significantly in popularity in + 2017. There are many users, and some of them participate directly in + the repository by reporting issues, performing testing, and in some + cases submitting pull requests with code contributions. ]] @@ -263,8 +266,8 @@ about Beast and other HTTP libraries that have gone through formal review. `boost::asio::ssl::stream`). You establish your TLS connection using the interface on `ssl::stream` like shown in all of the Asio examples, then construct your `websocket::stream` around it. It works perfectly fine; - Beast.WebSocket doesn't try to reinvent the wheel or put a fresh coat of - interface paint on the `ssl::stream`. + Beast comes with an `ssl_stream` wrapper in the example directory which + allows the SSL stream to be moved, overcoming an Asio limitation. The WebSocket implementation [*does] provide support for shutting down the TLS connection through the use of the ADL compile-time virtual functions diff --git a/example/websocket-client/websocket_client.cpp b/example/websocket-client/websocket_client.cpp index d1ee985a..642bfe6f 100644 --- a/example/websocket-client/websocket_client.cpp +++ b/example/websocket-client/websocket_client.cpp @@ -49,7 +49,7 @@ int main() // Wrap the now-connected socket in a websocket stream websocket::stream ws{sock}; - // Perform the websocket handhskae + // Perform the websocket handshake ws.handshake(host, "/", ec); if(ec) return fail("handshake", ec); diff --git a/include/beast/http/parser.hpp b/include/beast/http/parser.hpp index d7801171..590a89d9 100644 --- a/include/beast/http/parser.hpp +++ b/include/beast/http/parser.hpp @@ -101,7 +101,7 @@ public: #if BEAST_DOXYGEN template explicit - msesage_parser(Args&&... args); + parser(Args&&... args); #else template cb) { - cb_ = cb; + cb_ = std::move(cb); } private: diff --git a/test/http/doc_snippets.cpp b/test/http/doc_snippets.cpp index 304fbf03..78e07ca0 100644 --- a/test/http/doc_snippets.cpp +++ b/test/http/doc_snippets.cpp @@ -123,7 +123,8 @@ void fxx() { //[http_snippet_10 response res; - response_serializer sr{res}; + + response_serializer sr{res}; //] }