diff --git a/doc/qbk/01_intro/1_quick_look_zh_Hans.qbk b/doc/qbk/01_intro/1_quick_look_zh_Hans.qbk new file mode 100644 index 0000000..d77d7ba --- /dev/null +++ b/doc/qbk/01_intro/1_quick_look_zh_Hans.qbk @@ -0,0 +1,43 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section:quick_start 快速查看] +[/block''''''] + +这些完整示例程序旨在让读者快速了解该库的特点。它们的源码和编译脚本位于 [path_link example example] 目录中。 + + + +[section:http_client 简单HTTP客户端 __示例__] + +使用 HTTP 向网站发送 GET 请求,然后打印返回结果: + +文件:[path_link example/http/client/sync/http_client_sync.cpp http_sync_client.cpp] + +[example_http_client] + +[endsect] + + + +[section:websocket_client 简单 WebSocket 客户端 __示例__] + +建立 WebSocket 连接,发送消息并接收回复: + +文件:[path_link example/websocket/client/sync/websocket_client_sync.cpp websocket_sync_client.cpp] + +[example_websocket_client] + +[endsect] + +[include 1a_bishop_fox.qbk] + +[include 1b_autobahn.qbk] + +[endsect] diff --git a/doc/qbk/01_intro/1a_bishop_fox_zh_Hans.qbk b/doc/qbk/01_intro/1a_bishop_fox_zh_Hans.qbk new file mode 100644 index 0000000..b2d3e72 --- /dev/null +++ b/doc/qbk/01_intro/1a_bishop_fox_zh_Hans.qbk @@ -0,0 +1,36 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section:security_review_bishop_fox 安全审查(Bishop Fox)__视频__] + +2020年,为了兑现打造应用开发者可以信赖的顶级 C++ 库这一承诺,C++ 联盟再次委托 Bishop Fox 对 Beast 库进行复测。 + +报告链接如下: + +[@https://github.com/CPPAlliance/beast-assets/raw/master/bishop-fox/C%20Plus%20Plus%20Alliance%20-%20Hybrid%20Application%20Assessment%202020%20-%20Assessment%20Report%20-%2020200924.pdf + [*Beast - Hybrid Application Assessment 2020]] + +自 2005 年起,[@https://www.bishopfox.com/ Bishop Fox] 一直为全球财富 1000 强、高科技初创公司及金融机构提供安全咨询服务。Beast 委托 Bishop Fox 对 Boost C++ Beast HTTP/S 网络库进行安全评估。本次评估自 2017 年 9 月 11 日开始,以下报告详细说明了评估过程中的各项发现。 + +评估团队对 Beast 库进行了混合式应用安全评估。Bishop Fox 的这套评估方法结合了渗透测试中的实际攻击手段和针对性的源码审查,可以全面发现应用安全漏洞。这类在充分了解系统内部情况的前提下进行的评估,先从已部署的应用和源码入手,做自动化扫描。接着,把扫描结果和人工审查结合起来,深入排查潜在的安全漏洞。另外,团队还对应用架构和业务逻辑进行审查,找出设计层面的问题。最后,团队对这些问题进行人工利用和验证,确认发现结果是否准确。 + +[@https://github.com/CPPAlliance/beast-assets/raw/master/bishop-fox/Beast%20-%20Hybrid%20Application%20Assessment%202017%20-%20Assessment%20Report%20-%2020171114.pdf + [*Beast - Hybrid Application Assessment 2017]] + +[/ "Securing Boost.Beast: A Non-Traditional Source Code Review"] +''' + + + + + +''' + +[endsect] diff --git a/doc/qbk/01_intro/1b_autobahn_zh_Hans.qbk b/doc/qbk/01_intro/1b_autobahn_zh_Hans.qbk new file mode 100644 index 0000000..420cc86 --- /dev/null +++ b/doc/qbk/01_intro/1b_autobahn_zh_Hans.qbk @@ -0,0 +1,16 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section:websocket_autobahn_testsuite WebSocket(Autobahn| 测试套件)] + +[@https://github.com/crossbario/autobahn-testsuite Autobahn WebSockets 测试套件] 提供了一套全自动化的测试方案,用于验证 WebSocket 协议的客户端和服务端实现是否符合规范、是否健壮。该测试套件通过基本的 WebSocket 通信、全面的协议合规性验证以及性能和极限测试来检查具体实现。Autobahn 测试套件在行业中得到广泛应用,包含 500 多个测试用例。 + +[@https://vinniefalco.github.io/BeastAssets/reports/autobahn/index.html [*Autobahn|Testsuite WebSocket Results]] + +[endsect] diff --git a/doc/qbk/01_intro/_intro_zh_Hans.qbk b/doc/qbk/01_intro/_intro_zh_Hans.qbk new file mode 100644 index 0000000..16b90cc --- /dev/null +++ b/doc/qbk/01_intro/_intro_zh_Hans.qbk @@ -0,0 +1,93 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section 引言] +[block''''''] + +Beast 是一个 C++ 仅头文件库,通过使用 __Asio__ 的统一异步模型提供 [*低级 HTTP/1、WebSocket 和网络协议*] 的词汇类型与算法,为编写可互操作的网络库奠定基础。 + +该库专为以下场景设计: + +* **【对称性:】** 算法不区分角色;既可用来构建客户端,也可用来构建服务器,或者两者兼备。 + +* **【易用性:】** __Asio__ 用户能够立即理解 Beast。 + +* **【灵活性:】** 用户做出重要决策,例如缓冲区或 + thread management. + +* **【性能:】** 构建能够处理成千上万甚至更多连接的应用程序。 + +* **【作为进一步抽象的基础:】** 组件非常适合在其基础上进行构建。 + +该库本身并非客户端或服务器,但可用于构建这些组件。库中提供了大量示例,包括客户端和服务器的实现,可作为用户编写自己程序的起点。 + +[heading 动机] + +Beast 授权用户基于 HTTP/1 和 WebSocket 构建自己的库、客户端及服务器。由于 Beast 处理了底层协议细节,代码的实现、理解与维护将变得更为简单和高效。HTTP 与 WebSocket 协议是万维网的核心协议。每个 Web 浏览器都实现这些协议以加载网页,并支持客户端程序(通常以 JavaScript 编写)进行交互通信。C++ 能够拥有这些协议的标准化实现,是一大助益。 + + + +[section 要求] + +[important + 该库面向熟悉 Asio 的程序员。用户 + wish to use asynchronous interfaces should already know how to + create concurrent network programs using callbacks or coroutines. +] + +Beast 依赖一下环境: + +* **【C++11:】** 对大部分语言特性提供稳定支持。 +* **【Boost:】** Beast 仅可与 Boost 一同使用,不支持独立版 Asio。 +* **【OpenSSL:】**要求版本不低于 1.0.2。构建测试、示例以及使用 TLS/安全套接字时均需此依赖。 + +已在以下编译器上完成测试:msvc-14+、gcc 5.0+、clang 3.6+。 + +源码采用 [*仅头文件] 形式。通常情况下,在程序的链接阶段无需额外添加库即可使用 Beast,但以下情况除外: + +* 当使用通过调用 [@boost:/doc/html/boost_asio/reference/spawn.html `boost::asio::spawn`] 创建的协程时,需要在程序中添加 [@boost:/libs/coroutine/index.html Boost.Coroutine] 库。 + +当使用 [@boost:/doc/html/boost_asio/reference/ssl__stream.html boost::asio::ssl::stream] 时,需要在程序中添加 [@https://www.openssl.org/ OpenSSL] 库。 + +请查阅 [@boost:/more/getting_started.html Boost 文档],以获取针对您特定环境系统构建和链接 Boost 库的说明。 + +[endsect] + + + +[section 反馈缺陷] + +如需报告缺陷或获取 Beast 的使用帮助,建议优先使用 GitHub Issues。请访问 [@https://github.com/boostorg/beast/issues https://github.com/boostorg/beast/issues] 提出问题、报告缺陷或请求新功能。如需对问题或咨询内容保密,请通过邮件联系作者:[@mailto:vinnie.falco%40gmail.com vinnie.falco@gmail.com]。 + +[endsect] + + + +[section 致谢] + +Boost.Asio 是所有接口与实现策略构建的基础。文档中的部分内容在措辞与呈现方式上参照了 Boost.Asio 文档的风格。感谢 [@https://github.com/chriskohlhoff Christopher Kohlhoff] 贡献了出色的 Asio 库,以及 [@http://cplusplus.github.io/networking-ts/draft.pdf [*C++ 网络扩展]] 中的设计思想,为 Beast 提供了核心动力。 + +Beast 的诞生离不开 [@https://www.ripple.com Ripple] 在其早期开发阶段提供的支持,也得益于 [@https://github.com/JoelKatz David Schwartz]、[@https://github.com/ximinez Edward Hennis]、[@https://github.com/howardhinnant Howard Hinnant]、[@https://github.com/miguelportilla Miguel Portilla]、[@https://github.com/nbougalis Nik Bougalis]、[@https://github.com/seelabs Scott Determan] 和 [@https://github.com/scottschurr Scott Schurr] 贡献的思路、时间与耐心。同时感谢 [@https://github.com/K-ballo Agustín Bergé]、[@http://www.boost.org/users/people/glen_fernandes.html Glen Fernandes] 及 [@https://github.com/pdimov Peter Dimov] 在 [@https://slack.cpp.al/ C++ Language Slack Workspace] 上不厌其烦地解答疑问。 + +感谢 [@https://github.com/djarek Damian Jarek] 的积极参与和源码贡献。 + +感谢 [@https://github.com/madmongo1 Richard Hodges] (hodges.r@gmail.com) 代表 [@https://cppalliance.org C++ 联盟] 维护 Beast 库。 + +非常感谢 [@https://www.jetbrains.com Jetbrains s.r.o.] 为 Beast 开发团队提供全套产品开发授权。 +[endsect] + + + +[endsect] + +[h1 文档] + +请访问 [@https://boost.org/libs/beast https://boost.org/libs/beast] 查看完整文档。 + +[include 1_quick_look.qbk] diff --git a/doc/qbk/02_examples/_examples_zh_Hans.qbk b/doc/qbk/02_examples/_examples_zh_Hans.qbk new file mode 100644 index 0000000..6421b0b --- /dev/null +++ b/doc/qbk/02_examples/_examples_zh_Hans.qbk @@ -0,0 +1,282 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section 示例] +[block''''''] + +这些程序的源码和编译脚本存放在 [path_link example example] 目录里。 + +[/-----------------------------------------------------------------------------] + +[section 客户端] + +这些 HTTP 客户端会向命令行指定的服务器发送 GET 请求,并输出返回结果。爬取客户端会异步抓取排名前 10000 的站点的文档根目录,可用于评估程序的健壮性。所有异步客户端都支持超时设置。 + +[table +[[Description] [Source File] [Source File (using SSL)]] +[ + [HTTP 同步] + [[path_link example/http/client/sync/http_client_sync.cpp http_client_sync.cpp]] + [[path_link example/http/client/sync-ssl/http_client_sync_ssl.cpp http_client_sync_ssl.cpp]] +][ + [HTTP 异步] + [[path_link example/http/client/async/http_client_async.cpp http_client_async.cpp]] + [[path_link example/http/client/async-ssl/http_client_async_ssl.cpp http_client_async_ssl.cpp]] +][ + [HTTP 异步 Unix 域套接字] + [[path_link example/http/client/async-local/http_client_async_local.cpp http_client_async_local.cpp]] + [] +][ + [使用 __system_executor__ 的 HTTP 异步模式] + [] + [[path_link example/http/client/async-ssl-system-executor/http_client_async_ssl_system_executor.cpp http_client_async_ssl_system_executor.cpp]] +][ + [HTTP 协程] + [[path_link example/http/client/coro/http_client_coro.cpp http_client_coro.cpp]] + [[path_link example/http/client/coro-ssl/http_client_coro_ssl.cpp http_client_coro_ssl.cpp]] +][ + [HTTP C++20 协程] + [[path_link example/http/client/awaitable/http_client_awaitable.cpp http_client_awaitable.cpp]] + [[path_link example/http/client/awaitable-ssl/http_client_awaitable_ssl.cpp http_client_awaitable_ssl.cpp]] +][ + [HTTP 爬取(异步)] + [[path_link example/http/client/crawl/http_crawl.cpp http_crawl.cpp]] + [] +][ + [HTTP json_body(同步)] + [ + [path_link example/http/client/body/json_body.hpp json_body.hpp] + [path_link example/http/client/body/json_client.cpp json_client.cpp] + ] + [] +][ + [HTTP client for all methods (synchronous)] + [[path_link example/http/client/methods/http_client_methods.cpp http_client_methods.cpp]] + [] +]] + +这些 WebSocket 客户端会先连接服务器,发一条消息,收到回复后打印结果,最后断开连接。所有异步客户端都支持设置超时时间。 + +[table +[[Description] [Source File] [Source File (using SSL)]] +[ + [WebSocket 同步] + [[path_link example/websocket/client/sync/websocket_client_sync.cpp websocket_client_sync.cpp]] + [[path_link example/websocket/client/sync-ssl/websocket_client_sync_ssl.cpp websocket_client_sync_ssl.cpp]] +][ + [WebSocket 异步] + [[path_link example/websocket/client/async/websocket_client_async.cpp websocket_client_async.cpp]] + [[path_link example/websocket/client/async-ssl/websocket_client_async_ssl.cpp websocket_client_async_ssl.cpp]] +][ + [WebSocket 异步 Unix 域套接字] + [[path_link example/websocket/client/async-local/websocket_client_async_local.cpp websocket_client_async_local.cpp]] + [] +][ + [使用 __system_executor__ 的 WebSocket 异步模式] + [] + [[path_link example/websocket/client/async-ssl-system-executor/websocket_client_async_ssl_system_executor.cpp websocket_client_async_ssl_system_executor.cpp]] +][ + [WebSocket 协程] + [[path_link example/websocket/client/coro/websocket_client_coro.cpp websocket_client_coro.cpp]] + [[path_link example/websocket/client/coro-ssl/websocket_client_coro_ssl.cpp websocket_client_coro_ssl.cpp]] +][ + [WebSocket C++20 协程] + [[path_link example/websocket/client/awaitable/websocket_client_awaitable.cpp websocket_client_awaitable.cpp]] + [] +]] + +[endsect] + +[/-----------------------------------------------------------------------------] + +[section 服务器端] + +这些 HTTP 服务器会从命令行指定的根目录中读取文件并提供给客户端。所有异步服务器都支持设置超时时间。 + +[table +[[Description] [Source File] [Source File (using SSL)]] +[ + [HTTP 同步] + [[path_link example/http/server/sync/http_server_sync.cpp http_server_sync.cpp]] + [[path_link example/http/server/sync-ssl/http_server_sync_ssl.cpp http_server_sync_ssl.cpp]] +][ + [HTTP 异步] + [[path_link example/http/server/async/http_server_async.cpp http_server_async.cpp]] + [[path_link example/http/server/async-ssl/http_server_async_ssl.cpp http_server_async_ssl.cpp]] +][ + [HTTP 异步 Unix 域套接字] + [[path_link example/http/server/async-local/http_server_async_local.cpp http_server_async_local.cpp]] + [] +][ + [HTTP 协程] + [[path_link example/http/server/coro/http_server_coro.cpp http_server_coro.cpp]] + [[path_link example/http/server/coro-ssl/http_server_coro_ssl.cpp http_server_coro_ssl.cpp]] +][ + [HTTP 无栈协程] + [[path_link example/http/server/stackless/http_server_stackless.cpp http_server_stackless.cpp]] + [[path_link example/http/server/stackless-ssl/http_server_stackless_ssl.cpp http_server_stackless_ssl.cpp]] +][ + [HTTP C++20 协程] + [[path_link example/http/server/awaitable/http_server_awaitable.cpp http_server_awaitable.cpp]] +][ + [HTTP 快速模式(速度优先)] + [[path_link example/http/server/fast/http_server_fast.cpp http_server_fast.cpp]] + [] +][ + [HTTP 精简模式(空间优先)] + [[path_link example/http/server/small/http_server_small.cpp http_server_small.cpp]] + [] +][ + [HTTP 灵活模式(普通 + SSL)] + [] + [[path_link example/http/server/flex/http_server_flex.cpp http_server_flex.cpp]] +]] + +这些 WebSocket 服务器会把收到的任何消息原样返回,并且保持会话不断开,直到客户端主动断开为止。所有异步服务器都支持设置超时时间。 + +[table +[[Description] [Source File] [Source File (using SSL)]] +[ + [WebSocket 同步] + [[path_link example/websocket/server/sync/websocket_server_sync.cpp websocket_server_sync.cpp]] + [[path_link example/websocket/server/sync-ssl/websocket_server_sync_ssl.cpp websocket_server_sync_ssl.cpp]] +][ + [WebSocket 异步] + [[path_link example/websocket/server/async/websocket_server_async.cpp websocket_server_async.cpp]] + [[path_link example/websocket/server/async-ssl/websocket_server_async_ssl.cpp websocket_server_async_ssl.cpp]] +][ + [WebSocket 异步 Unix 域套接字] + [[path_link example/websocket/server/async-local/websocket_server_async_local.cpp websocket_server_async_local.cpp]] + [] +][ + [WebSocket 协程] + [[path_link example/websocket/server/coro/websocket_server_coro.cpp websocket_server_coro.cpp]] + [[path_link example/websocket/server/coro-ssl/websocket_server_coro_ssl.cpp websocket_server_coro_ssl.cpp]] +][ + [WebSocket 无栈协程] + [[path_link example/websocket/server/stackless/websocket_server_stackless.cpp websocket_server_stackless.cpp]] + [[path_link example/websocket/server/stackless-ssl/websocket_server_stackless_ssl.cpp websocket_server_stackless_ssl.cpp]] +][ + [WebSocket C++20 协程] + [[path_link example/websocket/server/awaitable/websocket_server_awaitable.cpp websocket_server_awaitable.cpp]] + [] +][ + [WebSocket 快速模式(适用于基准测试)] + [[path_link example/websocket/server/fast/websocket_server_fast.cpp websocket_server_fast.cpp]] + [] +]] + +[endsect] + +[/-----------------------------------------------------------------------------] + +[section 服务器端(进阶篇)] + +这些服务器在同一端口上同时提供 HTTP 和 WebSocket 服务,并展示了高级功能的实现方式。 + +[table +[[Description] [Features] [Sources]] +[ + [进阶篇] + [[itemized_list + [Timeouts] + [Multi-threaded] + [HTTP pipelining] + [Parser-oriented HTTP reading] + [Dual protocols: HTTP and WebSocket] + [Clean exit via SIGINT (CTRL+C) or SIGTERM (kill)] + ]] + [[path_link example/advanced/server/advanced_server.cpp advanced_server.cpp]] +][ + [进阶篇,灵活模式(普通 + SSL)] + [[itemized_list + [Timeouts] + [Multi-threaded] + [HTTP pipelining] + [Parser-oriented HTTP reading] + [Dual protocols: HTTP and WebSocket] + [Flexible ports: plain and SSL on the same port] + [Clean exit via SIGINT (CTRL+C) or SIGTERM (kill)] + ]] + [[path_link example/advanced/server-flex/advanced_server_flex.cpp advanced_server_flex.cpp]] +][ + [进阶篇,灵活模式(普通 + SSL)支持可等待操作] + [[itemized_list + [Timeouts] + [Multi-threaded] + [HTTP pipelining] + [Parser-oriented HTTP reading] + [Dual protocols: HTTP and WebSocket] + [Flexible ports: plain and SSL on the same port] + [Clean exit via SIGINT (CTRL+C) or SIGTERM (kill)] + [Usage of cancellation_signals] + ]] + [[path_link example/advanced/server-flex-awaitable/advanced_server_flex_awaitable.cpp advanced_server_flex_awaitable.cpp]] + ][ + [聊天服务器,多线程版] + [[itemized_list + [Multi-threaded] + [Broadcasting Messages] + [Multi-user Chat Server] + [JavaScript Browser Client] + [Parser-oriented HTTP reading] + [Dual protocols: HTTP and WebSocket] + [Clean exit via SIGINT (CTRL+C) or SIGTERM (kill)] + ]] + [[path_link example/websocket/server/chat-multi chat-multi]] +]] + +[endsect] + +[/-----------------------------------------------------------------------------] + +[section:chat_server 聊天服务器 __视频__] + +这个示例展示了一个 WebSocket 聊天服务器,支持多个用户同时连接并参与实时群聊。它附带了一个用 JavaScript 和 HTML5 实现的小型前端界面,可以在任意浏览器中运行。该示例还配有一小时的演讲视频,内容包括网络概念讲解,以及客户端和服务器实现细节的深度剖析。该演讲于 [@https://cppcon.org CppCon 2018] 上发布。Beast 示例中的源码相比原始程序有所改进。 + +[table WebSocket 聊天服务器与 JavaScript 客户端 +[[组件] [特性] [源码]] +[ + [服务器] + [[itemized_list + [C++] + [Timeouts] + [Multi-threaded] + [Broadcast to multiple peers] + [Dual protocols: HTTP and WebSocket] + [Clean exit via SIGINT (CTRL+C) or SIGTERM (kill)] + ]] + [[path_link example/websocket/server/chat-multi chat-multi]] +][ + [客户端] + [[itemized_list + [JavaScript / HTML5] + [Runs in the browser] + [Delivered by the server] + [Only 60 lines total including UI] + [Completely portable graphics] + ]] + [[path_link example/websocket/server/chat-multi/chat_client.html chat_client.html]] +]] + +[/ "Get rich quick! Using Boost.Beast WebSockets and Networking TS"] +''' + + + + + +''' + +[endsect] + +[/-----------------------------------------------------------------------------] + +[endsect] diff --git a/doc/qbk/03_core/10_ssl_tls_shutdown_zh_Hans.qbk b/doc/qbk/03_core/10_ssl_tls_shutdown_zh_Hans.qbk new file mode 100644 index 0000000..a47fe62 --- /dev/null +++ b/doc/qbk/03_core/10_ssl_tls_shutdown_zh_Hans.qbk @@ -0,0 +1,69 @@ +[/ + Copyright (c) 2024 Mohammad Nejati + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section SSL/TLS Shutdown] +[block''''''] + +A secure SSL/TLS connection requires a proper shutdown process to securely +indicate the [@https://en.wikipedia.org/wiki/End-of-file ['EOF]] condition. +This process prevents a type of attack known as a +[@https://en.wikipedia.org/wiki/Transport_Layer_Security#Truncation_attack ['truncation attack]] +in which an attacker can close the underlying transport layer and control +the length of the last message in the SSL/TLS connection. A shutdown process +consists of exchanging `close_notify` message between two parties. In __Asio__ +these steps happen by calling `shutdown()` or `async_shutdown()` on +`ssl::stream` object. + +[/-----------------------------------------------------------------------------] + +[section error::stream_truncated] + +There are SSL/TLS implementations that don't perform a proper shutdown process +and simply close the underlying transport layer instead. As a result, the EOF +condition in these applications is not cryptographically secure and should not +be relied upon. However, there are scenarios where an HTTPS client or server +doesn't need EOF for determining the end of the last message: + +* The HTTP message has a `Content-Length` header, and the body is fully + received (a known body length). + +* The HTTP message uses chunked transfer encoding, and the final chunk is + received. + +* The HTTP message doesn't contain a body, such as any response with a 1xx + (Informational), 204 (No Content), or 304 (Not Modified) status code. + +In such scenarios, `http::read` or `http::async_read` operations succeed as +they don't need EOF to complete. However, the next operation on the stream +would fail with an +[@boost:/doc/html/boost_asio/reference/ssl__error__stream_errors.html `net::ssl::error::stream_truncated`] +error. + +For example, let's assume we are using Beast for communicating with an HTTPS +server that doesn't perform a proper SSL/TLS shutdown: + +[snippet_core_4] + +[/-----------------------------------------------------------------------------] + +[heading Non-Compliant Peers and Unknown Body Length] + +This is a rare case and indeed a security issue when HTTPS servers don't +perform a proper SSL/TLS shutdown procedure and send an HTTP response message +that relies on EOF to determine the end of the body. This is a security concern +because without an SSL/TLS shutdown procedure, the EOF is not cryptographically +secure, leaving the message body vulnerable to truncation attacks. + +The following is an example that can read an HTTP response from such a server: + +[snippet_core_5] + +[endsect] + +[endsect] diff --git a/doc/qbk/03_core/1_refresher_zh_Hans.qbk b/doc/qbk/03_core/1_refresher_zh_Hans.qbk new file mode 100644 index 0000000..a8242e1 --- /dev/null +++ b/doc/qbk/03_core/1_refresher_zh_Hans.qbk @@ -0,0 +1,238 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section:asio_refresher 回顾] + +为有效使用 Beast,需要预先理解网络库相关知识。本节对这些概念进行回顾,以作为提醒及进一步学习的指引。 + +[@https://en.wikipedia.org/wiki/Computer_network [网络]] 允许位于任意地点的程序在建立 [@https://en.wikipedia.org/wiki/Data_link [连接]] 并选择通信后进行信息交换。数据可通过连接在双向([@https://en.wikipedia.org/wiki/Duplex_(telecommunications) [全双工]])上可靠传输,且字节按发送顺序到达。这些连接以及用于表示连接的对象和类型统称为 [link beast.concepts.streams [流]]。连接到网络的计算机或设备称为 [@https://en.wikipedia.org/wiki/Host_(network) [主机]],已建立连接另一端的程序称为 [@https://en.wikipedia.org/wiki/Peer-to-peer [对等端]]。 + +[@https://en.wikipedia.org/wiki/Internet [互联网]] 是一个由全球互联计算机组成的网络,这些计算机使用多种标准化的通信协议进行信息交换。其中最为流行的协议是 [@https://en.wikipedia.org/wiki/Transmission_Control_Protocol [TCP/IP]],这也是本库唯一依赖的协议。该协议处理了底层细节,使得应用程序看到的是一个可靠的、全双工的流式连接,用于承载上述有序字节序列。[@https://en.wikipedia.org/wiki/Server_(computing) [服务器]] 是一台强大的、始终在线的主机,位于知名的网络名称或地址上,用于提供数据服务。而 [@https://en.wikipedia.org/wiki/Client_(computing) [客户端]] 则是一个临时的对等端,它连接到服务器进行数据交换,完成后便离线。 + +[@https://en.wikipedia.org/wiki/Internet [互联网]] 是一个由全球互联计算机组成的网络,这些计算机使用多种标准化的通信协议进行信息交换。其中最为流行的协议是 [@https://en.wikipedia.org/wiki/Transmission_Control_Protocol [TCP/IP]],这也是本库唯一依赖的协议。该协议处理了底层细节,使得应用程序看到的是一个可靠的、全双工的流式连接,用于承载上述有序字节序列。[@https://en.wikipedia.org/wiki/Server_(computing) [服务器]] 是一台强大的、始终在线的主机,位于知名的网络名称或地址上,用于提供数据服务。而 [@https://en.wikipedia.org/wiki/Client_(computing) [客户端]] 则是一个临时的对等端,它连接到服务器进行数据交换,完成后便离线。 + +C++ 中的网络编程以 __Asio__、[@https://think-async.com/Asio/ Asio] 以及 __NetTS__ 为代表,提供了一个抽象层,用于可移植地与操作系统设施交互。这些设施不仅涵盖网络,还涉及通用的 [@https://en.wikipedia.org/wiki/Input/output [输入/输出]](简称 I/O)。 + +[/-----------------------------------------------------------------------------] + +[heading 缓冲区] + +[@https://en.wikipedia.org/wiki/Data_buffer [缓冲区]] 是用于存放 I/O 操作中字节数据的一段连续内存区域。[@boost:/doc/html/boost_asio/reference/const_buffer.html `net::const_buffer`] 与 [@boost:/doc/html/boost_asio/reference/mutable_buffer.html `net::mutable_buffer`] 类型以类型安全的指针/大小对来表示这些内存区域。 + +[code_core_1_refresher_1s] + +[tip + `const_buffer` 与 `mutable_buffer` 比 `std::span` 更适用。 + and `span` because + [@https://en.cppreference.com/w/cpp/container/span `std::span`] + does too much. It not only + type-erases the original pointer but also recasts it to a pointer-to-byte. + The operating system doesn't care about this, but if a user wants to send + and receive an array of some other type, presenting it as an array of bytes + which supports bitwise operations is unnecessary. Custom buffer types also + enable implementations to provide targeted features such as + [@boost:/doc/html/boost_asio/overview/core/buffers.html#boost_asio.overview.core.buffers.buffer_debugging ['buffer debugging]] + without changing the more general vocabulary types. +] + +__ConstBufferSequence__ 与 __MutableBufferSequence__ 概念用于描述双向范围,其值类型分别可转换为 `const_buffer` 与 `mutable_buffer`。这些序列允许在单个函数调用中处理多个缓冲区,这种技术称为 [@https://en.wikipedia.org/wiki/Vectored_I/O [分散/聚集 I/O]]。缓冲区及缓冲区序列不具有所有权;拷贝操作产生的是浅层引用,而非底层内存的副本。以下每条语句都用于声明一个缓冲区序列: + +[code_core_1_refresher_2s] + +[@boost:/doc/html/boost_asio/reference/buffer_size.html `net::buffer_size`] 函数用于确定缓冲区序列中的总字节数,而 [@boost:/doc/html/boost_asio/reference/buffer_copy.html `net::buffer_copy`] 函数则用于将部分或全部字节从一个缓冲区序列转移到另一个序列。`buffer_size` 是一个定制点:允许用户在外层命名空间中定义重载版本,调用时不应使用命名空间限定符。[@boost:/doc/html/boost_asio/reference/buffer_sequence_begin.html `net::buffer_sequence_begin`] 与 [@boost:/doc/html/boost_asio/reference/buffer_sequence_end.html `net::buffer_sequence_end`] 函数用于获取遍历序列的一对迭代器。Beast 提供了一系列缓冲区序列类型和算法,包括 [link beast.ref.boost__beast__buffers_cat `buffers_cat`]、[link beast.ref.boost__beast__buffers_front `buffers_front`]、[link beast.ref.boost__beast__buffers_prefix `buffers_prefix`]、[link beast.ref.boost__beast__buffers_range `buffers_range`] 以及 [link beast.ref.boost__beast__buffers_suffix `buffers_suffix`]。以下示例将缓冲区序列中的字节转换为字符串: + +[code_core_1_refresher_1] + +__DynamicBuffer__ 概念用于定义一个可调整大小的缓冲区序列接口。当内存需求无法预先确定时(例如从流中读取 HTTP 消息时),算法可以使用动态缓冲区来表达。Beast 提供一系列完善的动态缓冲区类型,包括 [link beast.ref.boost__beast__buffers_adaptor `buffers_adaptor`]、[link beast.ref.boost__beast__flat_buffer `flat_buffer`]、[link beast.ref.boost__beast__multi_buffer `multi_buffer`] 以及 [link beast.ref.boost__beast__static_buffer `static_buffer`]。以下函数从 [link beast.ref.boost__beast__tcp_stream `tcp_stream`] 中读取数据到动态缓冲区,直到遇到换行符为止,该函数使用 [@boost:/doc/html/boost_asio/reference/buffers_iterator.html `net::buffers_iterator`] 将缓冲区内容视为字符范围进行处理: + +[code_core_1_refresher_2] + + + +[/-----------------------------------------------------------------------------] + +[heading 同步 I/O] + +同步输入与输出通过阻塞函数调用实现,这些调用在操作完成后将返回结果。此类操作通常无法取消,也没有设置超时的方法。__SyncReadStream__ 与 __SyncWriteStream__ 概念用于定义 [同步流] 的要求:这是一种可移植的 I/O 抽象,使用缓冲区序列来传输字节数据,并通过 `error_code` 或异常来报告错误。[@boost:/doc/html/boost_asio/reference/basic_stream_socket.html `net::basic_stream_socket`] 是一种常用的同步流,用于建立 TCP/IP 连接。用户也可以定义满足这些要求的自定义类型。 + +[code_core_1_refresher_3] + +同步流算法用于编写为函数模板,接受满足同步读写(或两者兼具)命名要求的流对象。以下示例用于展示一个写入文本并使用异常指示错误的算法: + +[code_core_1_refresher_4] + +同一算法也可采用错误码而非异常的方式来表述: + +[code_core_1_refresher_5] + +[/-----------------------------------------------------------------------------] + +[heading 异步 I/O] + +异步操作从调用 [@boost:/doc/html/boost_asio/reference/asynchronous_operations.html [发起函数]] 开始。该函数负责启动操作并立即返回,不会等待操作完成。随后,这个 [未完成] 的异步操作会在后台并发执行,不会阻塞调用者。当操作的外部可见效果全部产生后,发起函数中提供的一个可移动对象(称为 [@boost:/doc/html/boost_asio/reference/CompletionHandler.html [完成处理器]])会连同操作结果(例如错误码及其他信息)一起被放入队列,等待执行。完成处理器被放入队列的那一刻,就意味着该异步操作 [已完成]。下面的代码演示了如何异步地向套接字写入一段文本,并在操作完成时调用一个 lambda 函数: + +[code_core_1_refresher_3s] + +每个完成处理器(也称为 [@https://en.wikipedia.org/wiki/Continuation [延续]])都包含三个关联组件:通过 [@boost:/doc/html/boost_asio/reference/get_associated_allocator.html `net::get_associated_allocator`] 获取的 [@boost:/doc/html/boost_asio/overview/core/allocation.html [关联分配器]]、通过 [@boost:/doc/html/boost_asio/reference/associated_cancellation_slot.html `net::get_associated_cancellation_slot`] 获取的 [@boost:/doc/html/boost_asio/reference/associated_cancellation_slot.html [关联取消槽]],以及通过 [@boost:/doc/html/boost_asio/reference/get_associated_executor.html `net::get_associated_executor`] 获取的 [@boost:/doc/html/boost_asio/reference/associated_executor.html [关联执行器]]。这些关联可以通过内嵌方式指定: + +[code_core_1_refresher_6] + +或者,这些关联也可以通过非侵入方式指定,即特化类模板 [@boost:/doc/html/boost_asio/reference/associated_allocator.html `net::associated_allocator`]、[@boost:/doc/html/boost_asio/reference/associated_cancellation_slot.html `net::associated_cancellation_slot`] 以及 [@boost:/doc/html/boost_asio/reference/associated_executor.html `net::associated_executor`]: + +[code_core_1_refresher_7] + +当调用方希望更改完成处理器的执行器时,可以使用 [@boost:/doc/html/boost_asio/reference/bind_executor.html `net::bind_executor`] 函数。 + +实现使用该分配器来获取执行操作所需的任何临时存储空间。所有临时分配的内存在完成处理器被调用之前都会被释放。执行器是一种轻量可复制的对象,提供用于调用完成处理器的算法。除非调用方进行了自定义,否则完成处理器默认使用 `std::allocator` 以及对应 I/O 对象的执行器。 + +当调用方希望为操作指定自定义分配器时,可以使用 [@boost:/doc/html/boost_asio/reference/bind_allocator.html `net::bind_allocator`] 函数。 + + +完成处理器令牌所关联的取消槽可用于取消单个操作。该取消槽通常由完成处理器令牌(例如 [@boost:/doc/html/boost_asio/reference/use_awaitable.html `net::use_awaitable`] 或 [@boost:/doc/html/boost_asio/reference/yield_context.html `net::yield_context`])进行传递。 + +可用的 [@boost:/doc/html/boost_asio/reference/cancellation_type.html 取消类型] 如下所列。 + +# `terminal` —— 终止型 + Requests cancellation where, following a successful cancellation, + the only safe operations on the I/O object are closure or destruction. + +# `partial` —— 部分型 + Requests cancellation where a successful cancellation may result in partial + side effects or no side effects. Following cancellation, + the I/O object is in a well-known state, and may be used for further operations. + +# `total` —— 完全型 + Requests cancellation where a successful cancellation results in no apparent side effects. + Following cancellation, the I/O object is in the same observable state as it was prior to the operation. + + + + +网络库规定用于确定处理器运行上下文的设施。每个 I/O 对象都关联一个 __ExecutionContext__,用于获取调用完成处理器所需的 __Executor__ 实例。执行器决定完成处理器的调用位置与方式。从 __io_context__ 实例获取的执行器提供一项基本保证:处理器仅会在当前正在调用 [@boost:/doc/html/boost_asio/reference/io_context/run/overload1.html `net::io_context::run`] 的线程中被执行。 + +__AsyncReadStream__ 与 __AsyncWriteStream__ 概念用于定义 [异步流] 的要求:这是一种可移植的 I/O 抽象,能够异步交换数据,使用缓冲区序列表示字节数据,并通过 `error_code` 报告错误。[异步流算法] 以模板化的发起函数形式编写,接受满足异步读、异步写或两者兼具命名要求的流对象。以下示例用于展示一个向异步流写入文本的算法: + +[code_core_1_refresher_8] + +[/-----------------------------------------------------------------------------] + +[heading 并发] + +套接字和流等 I/O 对象 [*不是线程安全的]。尽管可以同时有多个操作未完成(例如,同时进行异步读和异步写),但流对象本身在同一时刻只能从一个线程进行访问。这意味着移动构造函数、析构函数或发起函数等成员函数不能并发调用。通常,这可以通过互斥锁等同步原语来实现,但并发网络程序需要更好的方式来访问共享资源,因为获取互斥锁的所有权可能会阻塞线程,使其无法执行无竞争的工作。为了提高效率,网络库采用了一种无需显式加锁的线程使用模型,要求所有对 I/O 对象的访问都必须在一个 [@boost:/doc/html/boost_asio/overview/core/strands.html [串行器]] 内执行。 + +[/-----------------------------------------------------------------------------] + +[heading 通用模型] + +Because completion handlers cause an inversion of the flow of control, +sometimes other methods of attaching a continuation are desired. Networking +provides the +[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3747.pdf ['Universal Model for Asynchronous Operations]], +providing a customizable means for transforming the signature of the initiating +function to use other types of objects and methods in place of a completion +handler callback. For example to call to write a string to a socket +asynchronously, using a `std::future` to receive the number of bytes transferred +thus looks like this: + +[code_core_1_refresher_4s] + +This functionality is enabled by passing the variable +[@boost:/doc/html/boost_asio/reference/use_future.html `net::use_future`] +(of type +[@boost:/doc/html/boost_asio/reference/use_future_t.html `net::use_future_t<>`]) +in place of the completion handler. The same `async_write` function overload +can work with a +[@https://en.wikipedia.org/wiki/Fiber_(computer_science) ['fiber]] +launched with +[@boost:/doc/html/boost_asio/reference/spawn/overload1.html `asio::spawn`]: + +[code_core_1_refresher_5s] + +In both of these cases, an object with a specific type is used in place of +the completion handler, and the return value of the initiating function +is transformed from `void` to `std::future` or `std::size_t`. +The handler is sometimes called a +__CompletionToken__ +when used in this context. The return type transformation is supported by +customization points in the initiating function signature. Here is the +signature for +[@boost:/doc/html/boost_asio/reference/async_write/overload1.html `net::async_write`]: + +Note that a `spawn` function itself has a completion signature, +but we're ignoring it's result in the example by using `asio::detached`. + +[code_core_1_refresher_9] + +The type of the function's return value is determined by the +[@boost:/doc/html/boost_asio/reference/async_result.html `net::async_result`] +customization point, which comes with specializations for common library +types such as `std::future` and may also be specialized for user-defined +types. The body of the initiating function calls the +[@boost:/doc/html/boost_asio/reference/async_initiate.html `net::async_initiate`] +helper to capture the arguments and forward them to the specialization of +`async_result`. An additional "initiation function" object is provided which +`async_result` may use to immediately launch the operation, or defer the launch +of the operation until some point in the future (this is called "lazy +execution"). The initiation function object receives the internal completion +handler which matches the signature expected by the initiating function: + +[code_core_1_refresher_10] + +This transformed, internal handler is responsible for the finalizing step that +delivers the result of the operation to the caller. For example, when using +`net::use_future` the internal handler will deliver the result by calling +[@https://en.cppreference.com/w/cpp/thread/promise/set_value `std::promise::set_value`] +on the promise object returned by the initiating function. + +[/-----------------------------------------------------------------------------] + +[heading Using Networking] + +Most library stream algorithms require a __socket__, __ssl_stream__, or +other __Stream__ object that has already established communication with +a remote peer. This example is provided as a reminder of how to work with +sockets: + +[snippet_core_2] + +Throughout this documentation identifiers with the following names have +special meaning: + +[table Global Variables +[[Name][Description]] +[[ + [@boost:/doc/html/boost_asio/reference/io_context.html [*`ioc`]] +][ + A variable of type __io_context__ which is running on one separate thread, + and upon which an __executor_work_guard__ object has been constructed. +]] +[[ + [@boost:/doc/html/boost_asio/reference/ip__tcp/socket.html [*`sock`]] +][ + A variable of type + [@boost:/doc/html/boost_asio/reference/ip__tcp/socket.html `tcp::socket`] + which has already been connected to a remote host. +]] +[[ + [@boost:/doc/html/boost_asio/reference/ssl__stream.html [*`ssl_sock`]] +][ + A variable of type + [@boost:/doc/html/boost_asio/reference/ssl__stream.html `net::ssl::stream`] + which is already connected and has handshaked with a remote host. +]] +[[ + [link beast.ref.boost__beast__websocket__stream [*`ws`]] +][ + A variable of type + [link beast.ref.boost__beast__websocket__stream `websocket::stream`] + which is already connected with a remote host. +]] +] + +[endsect] diff --git a/doc/qbk/03_core/2_streams_zh_Hans.qbk b/doc/qbk/03_core/2_streams_zh_Hans.qbk new file mode 100644 index 0000000..f3129a3 --- /dev/null +++ b/doc/qbk/03_core/2_streams_zh_Hans.qbk @@ -0,0 +1,116 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + + + +[section:stream_types Streams] + +A __Stream__ is a communication channel where data is reliably transferred as +an ordered sequence of bytes. Streams are either synchronous or asynchronous, +and may allow reading, writing, or both. Note that a particular type may model +more than one concept. For example, the networking types __socket__ and +__ssl_stream__ support both __SyncStream__ and __AsyncStream__. All stream +algorithms in Beast are declared as template functions using these concepts: + +[table Stream Concepts +[[Concept][Description]] +[ + [__SyncReadStream__] + [ + Supports buffer-oriented blocking reads. + ] +][ + [__SyncWriteStream__] + [ + Supports buffer-oriented blocking writes. + ] +][ + [__SyncStream__] + [ + A stream supporting buffer-oriented blocking reads and writes. + ] +][ + [__AsyncReadStream__] + [ + Supports buffer-oriented asynchronous reads. + ] +][ + [__AsyncWriteStream__] + [ + Supports buffer-oriented asynchronous writes. + ] +][ + [__AsyncStream__] + [ + A stream supporting buffer-oriented asynchronous reads and writes. + ] +] +] + +These template metafunctions check whether a given type meets the +requirements for the various stream concepts, and some additional +useful utilities. The library uses these type checks internally +and also provides them as public interfaces so users may use the +same techniques to augment their own code. The use of these type +checks helps provide more concise errors during compilation: + +[table Type Traits and Metafunctions +[[Name][Description]] +[[ + [link beast.ref.boost__beast__executor_type `executor_type`] +][ + An alias for the type of object returned by `get_executor`. +]] +[[ + [link beast.ref.boost__beast__has_get_executor `has_get_executor`] +][ + Determine if the `get_executor` member function is present. +]] +[[ + [link beast.ref.boost__beast__is_async_read_stream `is_async_read_stream`] +][ + Determine if a type meets the requirements of __AsyncReadStream__. +]] +[[ + [link beast.ref.boost__beast__is_async_stream `is_async_stream`] +][ + Determine if a type meets the requirements of both __AsyncReadStream__ + and __AsyncWriteStream__. +]] +[[ + [link beast.ref.boost__beast__is_async_write_stream `is_async_write_stream`] +][ + Determine if a type meets the requirements of __AsyncWriteStream__. +]] +[[ + [link beast.ref.boost__beast__is_sync_read_stream `is_sync_read_stream`] +][ + Determine if a type meets the requirements of __SyncReadStream__. +]] +[[ + [link beast.ref.boost__beast__is_sync_stream `is_sync_stream`] +][ + Determine if a type meets the requirements of both __SyncReadStream__ + and __SyncWriteStream__. +]] +[[ + [link beast.ref.boost__beast__is_sync_write_stream `is_sync_write_stream`] +][ + Determine if a type meets the requirements of __SyncWriteStream__. +]] +] + +Using the type checks with `static_assert` on function or class template +types will provide users with helpful error messages and prevent undefined +behaviors. This example shows how a template function which writes to a +synchronous stream may check its argument: + +[snippet_core_3] + +[endsect] diff --git a/doc/qbk/03_core/3_timeouts_zh_Hans.qbk b/doc/qbk/03_core/3_timeouts_zh_Hans.qbk new file mode 100644 index 0000000..2f207c4 --- /dev/null +++ b/doc/qbk/03_core/3_timeouts_zh_Hans.qbk @@ -0,0 +1,221 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section:timeouts Timeouts __example__] + +Network programs must handle adverse connection conditions; the most common +is that a connected peer goes offline unexpectedly. Protocols have no way of +identifying this reliably: the peer is offline after all, and unable to send +a message announcing the absence. A peer can go offline for various reasons: + +[itemized_list + [The peer experiences a power loss] + [The peer becomes disconnected from the network] + [The local host becomes disconnected from the network] + [The network itself becomes unavailable] +] + +To determine when a peer is offline or idle, a program will implement a +[@https://en.wikipedia.org/wiki/Timeout_(computing) timeout] +algorithm, which closes the connection after a specified amount of time if +some condition is met. For example, if no data is received for the duration. +A timeout may be used to: + +[itemized_list + [Drop malicious or poorly performing hosts] + [Close idle connections to free up resources] + [Determine if a peer is offline or no longer available] +] + +Traditionally, programs use a +[@boost:/doc/html/boost_asio/reference/steady_timer.html `net::steady_timer`] +to determine when a timeout occurs, and then call +[@boost:/doc/html/boost_asio/reference/basic_socket/close/overload2.html `close`] +on the socket to release the resources. The complexity of managing a separate +timer is often a source of +[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1269r0.html#timers frustration] +for non-experts. + +[note + For portability reasons, networking does not provide timeouts + or cancellation features for synchronous stream operations. +] + +To simplify the handling of timeouts, these provided types wrap a +[@boost:/doc/html/boost_asio/reference/basic_stream_socket.html `net::basic_stream_socket`] +to provide additional features: + +[table +[[Name][Features]] +[ + [[link beast.ref.boost__beast__tcp_stream `tcp_stream`]] + [[itemized_list + [Timeouts for logical operations] + [[@boost:/doc/html/boost_asio/reference/ip__tcp.html `net::ip::tcp`] protocol] + [[@boost:/doc/html/boost_asio/reference/executor.html `net::executor`] executor] + [[link beast.ref.boost__beast__unlimited_rate_policy `unlimited_rate_policy`] rate limits] + ]] +][ + [[link beast.ref.boost__beast__basic_stream `basic_stream`]] + [[itemized_list + [Timeouts for logical operations] + [Configurable __Protocol__ type] + [Configurable __Executor__ type] + [Configurable __RatePolicy__ type] + ]] +]] + +[/-----------------------------------------------------------------------------] + +[heading Construction] + +The `tcp_stream` is designed as a replacement for +[@boost:/doc/html/boost_asio/reference/ip__tcp/socket.html `net::ip::tcp::socket`]. +Any program which currently uses a socket, can switch to a `tcp_stream` and achieve +the features above (although some interfaces are different, see below). +Networking now allows I/O objects to construct with any instance of +__ExecutionContext__ or __Executor__ objects. Here we construct a stream which +uses a particular I/O context to dispatch completion handlers: + +[code_core_3_timeouts_1] + +Alternatively, we can construct the stream from an executor: + +[code_core_3_timeouts_2] + +The function +[@boost:/doc/html/boost_asio/reference/make_strand.html `make_strand`] +returns a strand constructed from an execution context or executor. When a +[@boost:/doc/html/boost_asio/reference/strand.html `net::strand`] +is chosen for the stream's executor, all completion handlers which do not +already have an associated executor will use the strand. This is both a +notational convenience (no need for `strand::wrap` or `bind_executor` at +call sites) and a measure of safety, as it is no longer possible to forget +to use the strand. + +[code_core_3_timeouts_3] + +[/-----------------------------------------------------------------------------] + +[heading Connecting] + +Before data can be exchanged, the stream needs to be connected to a peer. +The following code sets a timeout for an asynchronous connect operation. +In Beast, functions to connect to a range of endpoints (such as the range +returned by +[@boost:/doc/html/boost_asio/reference/ip__basic_resolver/resolve/overload3.html `net::ip::tcp::resolver::resolve`]) +are members of the class rather than free functions such as +[@boost:/doc/html/boost_asio/reference/async_connect.html `net::async_connect`]. + +[code_core_3_timeouts_4] + +A server will use an acceptor bound to a particular IP address and port to +listen to and receive incoming connection requests. The acceptor returns +an ordinary socket. A `tcp_stream` can be move-constructed from the +underlying `basic_stream_socket` thusly: + +[code_core_3_timeouts_5] + +[/-----------------------------------------------------------------------------] + +[heading Reading and Writing] + +Timeouts apply to the logical operation, expressed as a series of asynchronous +calls, rather than just the next call. This code reads a line from the stream +and writes it back. Both the read and the write must complete within 30 seconds +from when the timeout was set; the timer is not reset between operations. + +[code_core_3_timeouts_6] + +Since reads and writes can take place concurrently, it is possible to have +two simultaneous logical operations where each operation either only reads, +or only writes. The beginning of a new read or write operation will use +the most recently set timeout. This will not affect operations that are +already outstanding. + +[code_core_3_timeouts_7] + +When a timeout is set, it cancels any previous read or write timeout for which +no outstanding operation is in progress. Algorithms which loop over logical +operations simply need to set the timeout once before the logical operation, +it is not necessary to call `expires_never` in this case. Here we implement +an algorithm which continuously echoes lines back, with a timeout. This example +is implemented as a complete function. + +[code_core_3_timeouts_1f] + +[/-----------------------------------------------------------------------------] + +[heading https_get] + +It is important to note that all of the examples thus far which perform +reads and writes with a timeout, make use of the existing networking stream +algorithms. As these algorithms are written generically to work with any +object meeting the stream requirements, they transparently support timeouts +when used with `tcp_stream`. This can be used to enable timeouts for stream +wrappers that do not currently support timeouts. + +The following code establishes an encrypted connection, writes an HTTP +request, reads the HTTP response, and closes the connection gracefully. +If these operations take longer than 30 seconds total, a timeout occurs. +This code is intended to show how `tcp_stream` can be used to enable +timeouts across unmodified stream algorithms which were not originally +written to support timing out, and how a blocking algorithm may be written +from asynchronous intermediate operations. + +[code_core_3_timeouts_2f] + +[endsect] + +[/-----------------------------------------------------------------------------] + +[section:rate_limiting Rate Limiting __example__] + +The +[link beast.ref.boost__beast__basic_stream `basic_stream`] +class template supports an additional `RatePolicy` template parameter. Objects +of this type must meet the requirements of __RatePolicy__. They are used to +implement rate limiting or bandwidth management. The default policy for +`basic_stream` and `tcp_stream` is +[link beast.ref.boost__beast__unlimited_rate_policy `unlimited_rate_policy`], +which places no limits on reading and writing. The library comes with the +[link beast.ref.boost__beast__simple_rate_policy `simple_rate_policy`], +allowing for independent control of read and write limits expressed in terms +of bytes per second. The follow code creates an instance of the basic stream +with a simple rate policy, and sets the read and write limits: + +[code_core_3_timeouts_8] + +More sophisticated rate policies can be implemented as user-defined types which +meet the requirements of __RatePolicy__. Here, we develop a rate policy that +measures the instantaneous throughput of reads and writes. First we write a +small utility class that applies an exponential smoothing function to a series +of discrete rate samples, to calculate instantaneous throughput. + +[code_core_3_timeouts_3f] + +Then we define our rate policy object. We friend the type +[link beast.ref.boost__beast__rate_policy_access `rate_policy_access`] to +allow our implementation to be private, but still allow the `basic_stream` +access to call the required functions. This lets us avoid having to write +a cumbersome friend declaration for the `basic_stream` class template. +Public members of rate policy objects become part of the stream object's +interface, through a call to `rate_policy`. + +[code_core_3_timeouts_4f] + +To use our new policy we declare an instance of the stream, and then use it +with stream algorithms as usual. At any time, we can determine the current +read or write rates by calling into the policy. + +[code_core_3_timeouts_9] + +[endsect] + +[/-----------------------------------------------------------------------------] diff --git a/doc/qbk/03_core/4__layers_zh_Hans.qbk b/doc/qbk/03_core/4__layers_zh_Hans.qbk new file mode 100644 index 0000000..cac1cf5 --- /dev/null +++ b/doc/qbk/03_core/4__layers_zh_Hans.qbk @@ -0,0 +1,118 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section:layered_streams Layered Streams] + +Networking's __ssl_stream__ is a class template meeting the requirements +of both synchronous and asynchronous read and write streams, implemented +in terms of a "next layer" object whose type is determined by a class +template parameter. The SSL stream constructs an instance of the next +layer object internally, while allowing external access through the +observer `net::ssl::stream::next_layer()`. This declares an SSL stream +which uses a regular TCP/IP socket as the next layer: + +[code_core_4_layers_1] + +Objects using this design pattern are referred to in networking as "a +stack of stream layers". In Beast we use the term ['layered stream], +although the property of having a next layer is not exclusive to streams. +As with the SSL stream, __websocket_stream__ is a class template +parameterized on a next layer object. This declares a websocket +stream which uses a regular TCP/IP socket as the next layer: + +[code_core_4_layers_2] + +If a Secure WebSockets stream is desired, this is accomplished simply +by changing the type of the next layer and adjusting the constructor +arguments to match: + +[code_core_4_layers_3] + +Higher level abstractions can be developed in this fashion by nesting +stream layers to arbitrary degree. The stack of stream layers effectively +forms a compile-time singly linked list. The object at the end of +this list is called the ['lowest layer], and is special from the +others because it typically represents the underlying socket. + +Beast comes with several layered stream wrappers, as well as +facilities for authoring and working with layered streams: + +[table Layered Stream Algorithms and Types +[[Name][Description]] +[[ + [link beast.ref.boost__beast__basic_stream `basic_stream`] + [link beast.ref.boost__beast__tcp_stream `tcp_stream`] +][ + This stream can be used for synchronous and asynchronous reading + and writing. It allows timeouts to be set on logical operations, + and can have an executor associated with the stream which is + used to invoke completion handlers. This lets you set a strand + on the stream once, which is then used for all asynchronous + operations automatically. +]] +[[ + [link beast.ref.boost__beast__buffered_read_stream `buffered_read_stream`] +][ + A buffered read stream meets the requirements for synchronous and + asynchronous read and write streams, and additionally implements + configurable buffering for reads. +]] +[[ + [link beast.ref.boost__beast__close_socket `close_socket`] +][ + This function closes a socket by performing an unqualified call + to the + [link beast.ref.boost__beast__beast_close_socket `beast_close_socket`] + customization point, allowing sockets to be closed in generic + contexts in an extensible fashion. +]] +[[ + [link beast.ref.boost__beast__get_lowest_layer `get_lowest_layer`] +][ + Returns the lowest layer in a stack of stream layers by recursively + calling the `next_layer` member function on each object until reaching + an object which lacks the member. This example + puts a layered stream into non-blocking mode by retrieving the + TCP/IP socket in the lowest layer and changing the socket option: + + [code_core_4_layers_4] +]] +[[ + [link beast.ref.boost__beast__http__icy_stream `http::icy_stream`] +][ + An ICY stream transparently converts the non-standard "ICY 200 OK" + HTTP response from Shoutcast servers into a conforming 200 level + HTTP response. +]] +[[ + [link beast.ref.boost__beast__lowest_layer_type `lowest_layer_type`] +][ + A metafunction to return the type of the lowest layer used in + a type representing a stack of stream layers. This is the type + of reference returned by + [link beast.ref.boost__beast__get_lowest_layer `get_lowest_layer`] +]] +] + +[/-----------------------------------------------------------------------------] + +[section Counted Stream __example__] + +This example shows the definition of a layered stream which keeps individual +counts of the total number of bytes read from and written to the next layer. +It meets the requirements for synchronous and asynchronous read and write +streams: + +[code_core_4_layers_5] + +[endsect] + +[/-----------------------------------------------------------------------------] + +[endsect] diff --git a/doc/qbk/03_core/5_buffers_zh_Hans.qbk b/doc/qbk/03_core/5_buffers_zh_Hans.qbk new file mode 100644 index 0000000..1cc4de1 --- /dev/null +++ b/doc/qbk/03_core/5_buffers_zh_Hans.qbk @@ -0,0 +1,250 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section Buffer Types] + +To facilitate working with instances of the __ConstBufferSequence__ and +__MutableBufferSequence__ concepts introduced in __Asio__, Beast treats +those sequences as a special type of range. The following algorithms and +wrappers are provided which transform these ranges efficiently using lazy +evaluation. No memory allocations are used in the transformations; instead, +they create lightweight iterators over the existing, unmodified memory +buffers. Control of buffers is retained by the caller; ownership is not +transferred. + +[table Buffer Algorithms and Types +[[Name][Description]] +[[ + [link beast.ref.boost__beast__buffer_bytes `buffer_bytes`] +][ + This is a more reliable version of + [@boost:/doc/html/boost_asio/reference/buffer_size.html `net::buffer_size`] + which is easier to use and also works for types which are convertible + to `net::const_buffer` or `net::mutable_buffer`. +]] +[[ + [link beast.ref.boost__beast__buffers_cat `buffers_cat`] +][ + This functions returns a new buffer sequence which, when iterated, + traverses the sequence which would be formed if all of the input buffer + sequences were concatenated. With this routine, multiple calls to a + stream's `write_some` function may be combined into one, eliminating + expensive system calls. +]] +[[ + [link beast.ref.boost__beast__buffers_cat_view `buffers_cat_view`] +][ + This class represents the buffer sequence formed by concatenating + two or more buffer sequences. This is type of object returned by + [link beast.ref.boost__beast__buffers_cat `buffers_cat`]. +]] +[[ + [link beast.ref.boost__beast__buffers_front `buffers_front`] +][ + This function returns the first buffer in a buffer sequence, + or a buffer of size zero if the buffer sequence has no elements. +]] +[[ + [link beast.ref.boost__beast__buffers_prefix `buffers_prefix`] +][ + This function returns a new buffer or buffer sequence which represents + a prefix of the original buffers. +]] +[[ + [link beast.ref.boost__beast__buffers_prefix_view `buffers_prefix_view`] +][ + 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.boost__beast__buffers_prefix `buffers_prefix`]. +]] +[[ + [link beast.ref.boost__beast__buffers_range `buffers_range`] + [link beast.ref.boost__beast__buffers_range_ref `buffers_range_ref`] +][ + This function returns an iterable range representing the passed + buffer sequence. The values obtained when iterating the range + will always be a constant buffer, unless the underlying buffer + sequence is mutable, in which case the value obtained when iterating + will be a mutable buffer. It is intended as a notational convenience + when writing a ['range-for] statement over a buffer sequence. + + The function + [link beast.ref.boost__beast__buffers_range_ref `buffers_range`] + maintains a copy of the buffer sequence, while + [link beast.ref.boost__beast__buffers_range_ref `buffers_range_ref`] + maintains a reference (in this case, the caller must ensure that + the lifetime of the referenced buffer sequence extends until the + range object is destroyed). +]] +[[ + [link beast.ref.boost__beast__buffers_suffix `buffers_suffix`] +][ + This class wraps the underlying memory of an existing buffer sequence + and presents a suffix of the original sequence. The length of the suffix + may be progressively shortened. This lets callers work with sequential + increments of a buffer sequence. +]] +[[ + [link beast.ref.boost__beast__buffers_to_string `buffers_to_string`] +][ + This function converts a buffer sequence to a `std::string`. It can + be used for diagnostic purposes and tests. +]] +[[ + [link beast.ref.boost__beast__buffer_ref `buffer_ref`] + [link beast.ref.boost__beast__ref `ref`] +][ + This function converts a beast buffer, that is to be passed by reference, + into a buffer reference, that can be passed by value into asio functions. + + It implements the __DynamicBuffer__v2__ concept. +]] +] + +The __DynamicBuffer__ concept introduced in __Asio__ models a buffer +sequence which supports an owning, resizable range. Beast provides this +set of additional implementations of the dynamic buffer concept: + +[table Dynamic Buffer Implementations +[[Name][Description]] +[[ + [link beast.ref.boost__beast__buffers_adaptor `buffers_adaptor`] +][ + This wrapper adapts any __MutableBufferSequence__ into a + __DynamicBuffer__ with an upper limit on the total size of the input and + output areas equal to the size of the underlying mutable buffer sequence. + The implementation does not perform heap allocations. +]] +[[ + [link beast.ref.boost__beast__flat_buffer `flat_buffer`] + [link beast.ref.boost__beast__basic_flat_buffer `basic_flat_buffer`] +][ + Guarantees that input and output areas are buffer sequences with + length one. + Upon construction an optional upper limit to the total size of the + input and output areas may be set. + The basic container is an + [@https://en.cppreference.com/w/cpp/named_req/AllocatorAwareContainer [*AllocatorAwareContainer]]. +]] +[[ + [link beast.ref.boost__beast__multi_buffer `multi_buffer`] + [link beast.ref.boost__beast__basic_multi_buffer `basic_multi_buffer`] +][ + Uses a sequence of one or more character arrays of varying sizes. + Additional character array objects are appended to the sequence to + accommodate changes in the size of the character sequence. + The basic container is an + [@https://en.cppreference.com/w/cpp/named_req/AllocatorAwareContainer [*AllocatorAwareContainer]]. +]] +[[ + [link beast.ref.boost__beast__flat_static_buffer `flat_static_buffer`] + [link beast.ref.boost__beast__flat_static_buffer_base `flat_static_buffer_base`] +][ + Guarantees that input and output areas are buffer sequences with + length one. + Provides the facilities of a dynamic buffer, subject to an upper + limit placed on the total size of the input and output areas defined + by a constexpr template parameter. The storage for the sequences are + kept in the class; the implementation does not perform heap allocations. +]] +[[ + [link beast.ref.boost__beast__static_buffer `static_buffer`] + [link beast.ref.boost__beast__static_buffer_base `static_buffer_base`] +][ + Provides the facilities of a circular dynamic buffer. subject to an + upper limit placed on the total size of the input and output areas + defined by a constexpr template parameter. + The implementation never moves memory during buffer operations. + The storage for the sequences are kept in the class; the implementation + does not perform heap allocations. +]] +] + +The buffers provide different guarantees regarding the allocated memory; stable means that existing +mutable and const_buffers obtained by calling `data` or `prepare`, will remain valid. + +Note that copies always requires a new call to `data` and `prepare`.` + +[table Memory stability +[[Name] [Allocation] [buffer sequence length] [Max Size] [Movable] [prepare/commit] [consume]] +[ + [[link beast.ref.boost__beast__flat_buffer `flat_buffer`]] + [dynamic] [1] [dynamic] [yes] [invalidating] [invalidating] +] +[ + [[link beast.ref.boost__beast__multi_buffer `multi_buffer`]] + [dynamic] [dynamic] [stable] [yes] [invalidating] +] +[ + [[link beast.ref.boost__beast__flat_static_buffer `flat_static_buffer`]] + [static] [1] [static] [no] [invalidating] +] +[ + [[link beast.ref.boost__beast__static_buffer `static_buffer`]] + [static] [1-2] [static] [no] [may invalidate] +] +] + +These two functions facilitate buffer interoperability with standard +output streams. + +[table Buffer Output Streams +[[Name][Description]] +[[ + [link beast.ref.boost__beast__make_printable `make_printable`] +][ + This function wraps a __ConstBufferSequence__ so it may be + used with `operator<<` and `std::ostream`. +]] +[[ + [link beast.ref.boost__beast__ostream `ostream`] +][ + This function returns a `std::ostream` which wraps a dynamic buffer. + Characters sent to the stream using `operator<<` are stored in the + dynamic buffer. +]] +] + +These type traits are provided to facilitate writing compile-time +metafunctions which operate on buffers: + +[table Buffer Algorithms and Types +[[Name][Description]] +[[ + [link beast.ref.boost__beast__buffers_iterator_type `buffers_iterator_type`] +][ + This metafunction is used to determine the type of iterator + used by a particular buffer sequence. +]] +[[ + [link beast.ref.boost__beast__buffers_type `buffers_type`] +][ + This metafunction is used to determine the underlying buffer type for + a list of buffer sequence. The equivalent type of the alias will vary + depending on the template type argument. +]] +[[ + [link beast.ref.boost__beast__is_const_buffer_sequence `is_const_buffer_sequence`] +][ + This metafunction is used to determine if all of the specified types + meet the requirements of __ConstBufferSequence__. This type alias + will be `std::true_type` if each specified type meets the requirements, + otherwise, this type alias will be `std::false_type`. +]] +[[ + [link beast.ref.boost__beast__is_mutable_buffer_sequence `is_mutable_buffer_sequence`] +][ + This metafunction is used to determine if all of the specified types + meet the requirements of __MutableBufferSequence__. This type alias + will be `std::true_type` if each specified type meets the requirements, + otherwise, this type alias will be `std::false_type`. +]] +] + +[endsect] diff --git a/doc/qbk/03_core/6_files_zh_Hans.qbk b/doc/qbk/03_core/6_files_zh_Hans.qbk new file mode 100644 index 0000000..2d9ff2a --- /dev/null +++ b/doc/qbk/03_core/6_files_zh_Hans.qbk @@ -0,0 +1,46 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section Files] + +Often when implementing network algorithms such as servers, it is necessary +to interact with files on the system. Beast defines the __File__ concept +and several models to facilitate cross-platform interaction with the +underlying filesystem: + +[table File Types +[[Name][Description]] +[[ + [link beast.ref.boost__beast__file `file`] +][ + `file` is a type alias to one of the following implementations, + depending on what is available on the target platform. +]] +[[ + [link beast.ref.boost__beast__file_stdio `file_stdio`] +][ + This implementation of __File__ uses the C++ standard library + facilities obtained by including ``. +]] +[[ + [link beast.ref.boost__beast__file_win32 `file_win32`] +][ + This implements a __File__ for the Win32 API. It provides low level + access to the native file handle when necessary. +]] +[[ + [link beast.ref.boost__beast__file_posix `file_posix`] +][ + For POSIX systems, this class provides a suitable implementation + of __File__ which wraps the native file descriptor and provides + it if necessary. +]] +] + +[endsect] diff --git a/doc/qbk/03_core/7_composed_zh_Hans.qbk b/doc/qbk/03_core/7_composed_zh_Hans.qbk new file mode 100644 index 0000000..c59a50b --- /dev/null +++ b/doc/qbk/03_core/7_composed_zh_Hans.qbk @@ -0,0 +1,104 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section Writing Composed Operations] + +Asynchronous operations are started by calling a free function or member +function known as an asynchronous ['__async_initfn__]. This function accepts +parameters specific to the operation as well as a __CompletionToken__. The +token is either a completion handler, or a type defining how the caller is +informed of the asynchronous operation result. Networking provides the +special tokens __use_future__ and __yield_context__ for using futures +and coroutines respectively. This system of customizing the return value +and method of completion notification is known as the +['Universal Asynchronous Model] described in __N3747__, and a built in +to __NetTS__. Here is an example of an initiating function which reads a +line from the stream and echoes it back. This function is developed +further in the next section: + +[example_core_echo_op_1] + +[tip + This initiating function receives the dynamic buffer by lvalue-reference, + instead of by rvalue-reference as specified in networking. An explanation + for this difference may be found in + [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1100r0.html [P1100R0] Efficient composition with DynamicBuffer]. +] +Authors using Beast can reuse the library's primitives to create their +own initiating functions for performing a series of other, intermediate +asynchronous operations before invoking a final completion handler. +The set of intermediate actions produced by an initiating function is +known as a +[@http://blog.think-async.com/2009/08/composed-operations-coroutines-and-code.html ['composed operation]]. +To ensure full interoperability and well-defined behavior, __Asio__ imposes +requirements on the implementation of composed operations. These classes +and functions make it easier to develop initiating functions and their +composed operations: + +[table Asynchronous Helpers +[[Name][Description]] +[[ + [link beast.ref.boost__beast__async_base `async_base`] + [link beast.ref.boost__beast__stable_async_base `stable_async_base`] +][ + This class is designed to be used as a base class when authoring + composed asynchronous operations expressed as an intermediate + completion handler. This eliminates the need for the extensive + boilerplate to propagate the associated executor and the associated + allocator. +]] +[[ + [link beast.ref.boost__beast__allocate_stable `allocate_stable`] +][ + For composed operation algorithms which need stable storage for + temporary objects, this function may be used. Memory for the + stable storage is allocated using the allocator associated with + the final completion handler. The implementation automatically + destroys the temporary object before the final completion handler + is invoked, or when the intermediate completion handler is + destroyed. +]] +[[ + [link beast.ref.boost__beast__bind_handler `bind_handler`] +][ + This function creates a new handler which, when invoked, calls + the original handler with the list of bound arguments. Any + parameters passed in the invocation will be substituted for + placeholders present in the list of bound arguments. Parameters + which are not matched to placeholders are silently discarded. + + The passed handler and arguments are forwarded into the returned + handler, whose associated allocator and associated executor will + be the same as those of the original handler. +]] +[[ + [link beast.ref.boost__beast__bind_front_handler `bind_front_handler`] +][ + This function creates a new handler which, when invoked, calls + the original handler with the list of bound arguments, along with + the list of invoked arguments at either the front or the back of + the argument list. Placeholders are not supported. + + The passed handler and arguments are forwarded into the returned + handler, whose associated allocator and associated executor will + will be the same as those of the original handler. +]] +[[ + [link beast.ref.boost__beast__saved_handler `saved_handler`] +][ + This wrapper safely stores a completion handler so it may be invoked + later, allowing an implementation to "pause" an operation until some + condition is met. +]] +] + +[include 7a_echo.qbk] +[include 7b_detect_ssl.qbk] + +[endsect] diff --git a/doc/qbk/03_core/7a_echo_zh_Hans.qbk b/doc/qbk/03_core/7a_echo_zh_Hans.qbk new file mode 100644 index 0000000..a5f75d0 --- /dev/null +++ b/doc/qbk/03_core/7a_echo_zh_Hans.qbk @@ -0,0 +1,80 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section:echo Echo __example__] + +This example develops an initiating function called [*echo]. +The operation will read up to the first newline on a stream, and +then write the same line including the newline back on the stream. +First we define the input parameters and results, then declare our +initiation function. For our echo operation the only inputs are the +stream and the completion token. The output is the error code which +is usually included in all completion handler signatures. + +[example_core_echo_op_2] + +Now that we have a declaration, we will define the body of the function. +We want to achieve the following goals: perform static type checking on +the input parameters, set up the return value as per __N3747__, and launch +the composed operation by constructing an intermediate, stateful completion +handler and invoking it. + +The initiating function contains a few relatively simple parts. There is +the customization of the return value type, static type checking, building +the return value type using the helper, and creating and launching the +`echo_op` composed operation object. + +The implementation strategy is to make the composed object meet the +requirements of a completion handler by being movable, and by making it +invocable so it can be used as a continuation for the asynchronous operations +it launches. Rather than using `std::bind` or `boost::bind`, which destroys +the type information and therefore breaks the associators, +we will simply pass `std::move(*this)` as the completion handler parameter for +any operations that we initiate. For the move to work correctly, care must be +taken to ensure that no access to data members are made after the move takes +place. Here is the complete implementation of our composed operation: + +[example_core_echo_op_3] + +There are some common mistakes that should be avoided when writing +composed operations: + +* Type erasing the final handler. This will cause undefined behavior. + +* Forgetting to include a return statement after calling an + initiating function. + +* Calling a synchronous function by accident. In general composed + operations should not block for long periods of time, since this + ties up a thread running on the __io_context__. + +* Forgetting to provide `executor_type` and `get_executor` for the + composed operation. This will cause undefined behavior. For example, + if someone calls the initiating function with a strand-wrapped + function object, and there is more than thread running on the + __io_context__, the underlying stream may be accessed in a fashion + that violates safety guarantees. Beast provides class templates + to take care of this boilerplate for you. + +* Forgetting to create an object of type __executor_work_guard__ with the + type of executor returned by the stream's `get_executor` member function. + +* For operations which complete immediately (i.e. without calling an + intermediate initiating function), forgetting to use __post__ to + invoke the final handler. This breaks the following initiating + function guarantee: ['Regardless of whether the asynchronous operation + completes immediately or not, the handler will not be invoked from + within this function. Invocation of the handler will be performed + in a manner equivalent to using __post__]. The function + __bind_handler__ is provided for this purpose. + +The listing for a complete, runnable version of this example is in +[path_link example/echo-op/echo_op.cpp echo_op.cpp]. + +[endsect] diff --git a/doc/qbk/03_core/7b_detect_ssl_zh_Hans.qbk b/doc/qbk/03_core/7b_detect_ssl_zh_Hans.qbk new file mode 100644 index 0000000..e84c48b --- /dev/null +++ b/doc/qbk/03_core/7b_detect_ssl_zh_Hans.qbk @@ -0,0 +1,111 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section:detect_ssl Detect SSL __example__] + +In this example we will build a simple function to detect the presence of the +[@https://tools.ietf.org/html/rfc2246#section-7.4 TLS client handshake] +given an input buffer sequence. Then we build on the example by adding a +synchronous stream algorithm. Finally, we implement an asynchronous +detection function using a composed operation. This SSL detector may +be used to allow a server to accept both TLS and plain (unencrypted) +connections at the same port. + +Here is the declaration for a function template to detect the SSL client +handshake. The function accepts any object whose type meets the requirements +of __ConstBufferSequence__. This gives callers flexibility to use a buffer +object whose behavior is appropriate to the task. + +[example_core_detect_ssl_1] + +The algorithm examines the buffer starting from the beginning, and +performs a series of qualifying checks against the TLS specification. +When not enough data exists to be certain, the returned value of +`boost::indeterminate` informs the caller to read more data into the buffer. +The function definition for the declaration above follows: + +[example_core_detect_ssl_2] + +The detection function above is suitably generic and targeted in +focus that it may be used as a building block to create higher level +abstractions. Our goal is to create a ['stream algorithm]: a function +which is invoked with a stream, that reads or writes (or both) to achieve +a purpose. In this case, to detect the TLS client handshake. Stream +algorithms may be synchronous or asynchronous. Because synchronous algorithms +are easier to write, we start there. Then we build the asynchronous version, +trying to model it similarly to make reasoning about it easier. + +The synchronous version is implemented thusly: + +[example_core_detect_ssl_3] + +Now that we have the synchronous version, we can attempt to model the +asynchronous version similarly. A function which launches an asynchronous +operation is called an ['initiating function]. While the synchronous +version above produces an error code through an output parameter, the +asynchronous version delivers the error code to a completion handler +or other custom mechanism defined by the completion token. The signature +of the initiating function reflects these differences. + +First we declare the initiating function and document the requirements, +parameters, preconditions, and effects: + +[example_core_detect_ssl_4] + +There are two additional components required to implement the initiating +function: + +* An intermediate completion handler, called the "composed operation" + object, which holds the state of the operation while it is in progress, + and also holds the user's completion handler to be invoked when the + opeartion completes, and + +* An "initiation" function object which when invoked with parameters + captured at the call site of the initiating function, constructs the + composed operation with the captured arguments and launches it. + +Here we forward declare the composed operation type, and provide the +definition of the initiation function object. They are placed in the +`detail` namespace since they should not be public: + +[example_core_detect_ssl_5] + +The initiating function definition itself is straightforward. We perform +type checking on the parameters, and then let `net::async_initiate` +capture the parameter list along with a copy of our initiation function +object. Depending on the specialization of `async_result` for the type +of `CompletionToken`, the initiation function may be invoked immediately. +Alternatively, it may be invoked later, after the initiating function +returns. This is known as "lazy execution," and allows efficient and +expressive abstractions to be written. + +[example_core_detect_ssl_6] + +Now we will declare our composed operation. There is a considerable +amount of necessary boilerplate to get this right, but the result +is worth the effort. + +[example_core_detect_ssl_7] + +The boilerplate is all done, and now we need to implement the function +call operator that turns this composed operation a completion handler +with the signature `void(error_code, std::size_t)` which is exactly +the signature needed when performing asynchronous reads. This function +is a transformation of the synchronous version of `detect_ssl` above, +but with the inversion of flow that characterizes code written in the +callback style: + +[example_core_detect_ssl_8] + +The examples +[path_link example/advanced/server/advanced_server.cpp advanced-server] and +[path_link example/advanced/server-flex/advanced_server_flex.cpp advanced-server-flex] +use this SSL detection function. + +[endsect] diff --git a/doc/qbk/03_core/8_conf_macros_zh_Hans.qbk b/doc/qbk/03_core/8_conf_macros_zh_Hans.qbk new file mode 100644 index 0000000..1de67ee --- /dev/null +++ b/doc/qbk/03_core/8_conf_macros_zh_Hans.qbk @@ -0,0 +1,47 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section Configuration Preprocessor Definitions] + +A number of configuration preprocessor definitions can be used to change +the behavior of Beast. +The user should assume that they introduce significant changes to the public part +of this library's API and make sure that all translation units (usually files) +compiled and linked into a program use the same combination of configuration macros, +failure to do so may result in violations of ODR (One Definition Rule). + +[table Special Fields +[[Definition][Description]] +[ + [ + BOOST_BEAST_SEPARATE_COMPILATION + ][ + Enables the split compilation mode, which allows the user to compile + definitions of non-template entities in a single translation unit, thus + improving compilation speed. That translation unit has to include + boost/beast/src.hpp in order to compile the definitions. + ] +] +[ + [ + BOOST_BEAST_ALLOW_DEPRECATED + ][ + Enables the use of deprecated APIs within Beast. + ] +] +[ + [ + BOOST_BEAST_FILE_BUFFER_SIZE + ][ + Sets the small buffer size for the file_body. Defaults to 4096. + ] +] +] + +[endsect] diff --git a/doc/qbk/03_core/9_ssl_tls_certificate_zh_Hans.qbk b/doc/qbk/03_core/9_ssl_tls_certificate_zh_Hans.qbk new file mode 100644 index 0000000..f424ed9 --- /dev/null +++ b/doc/qbk/03_core/9_ssl_tls_certificate_zh_Hans.qbk @@ -0,0 +1,217 @@ +[/ + Copyright (c) 2025 Mohammad Nejati + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + + +[section SSL/TLS Certificate] + +[/-----------------------------------------------------------------------------] + +[heading Certificate Authority] + +A Certificate Authority (CA) is a trusted entity that signs digital +certificates, enabling users to verify their authenticity. Rather than storing +every individual certificate for each server (which would be impractical due to +the sheer volume and frequent renewals), users can store a limited set of root +certificates to authenticate server certificates as needed. + +Boost.Asio provides various methods for loading certificate authority +certificates: + +* [@boost:/doc/html/boost_asio/reference/ssl__context/add_certificate_authority.html `net::ssl::context::add_certificate_authority`] +* [@boost:/doc/html/boost_asio/reference/ssl__context/add_verify_path.html `net::ssl::context::add_verify_path`] +* [@boost:/doc/html/boost_asio/reference/ssl__context/load_verify_file.html `net::ssl::context::load_verify_file`] +* [@boost:/doc/html/boost_asio/reference/ssl__context/set_default_verify_paths.html `net::ssl::context::set_default_verify_paths`] + +It is important to set up peer verification so that the TLS/SSL handshake fails +if certificate verification is unsuccessful: + +[snippet_core_6] + +A client must also verify that the hostname or IP address in the certificate +matches the expected one. The +[@boost:/doc/html/boost_asio/reference/ssl__host_name_verification.html +`net::ssl::host_name_verification`] helper function object can perform this +verification according to the rules described in RFC 6125: + +[snippet_core_7] + +A server can also request and verify a client certificate to authenticate the +client: + +[snippet_core_8] + +[/-----------------------------------------------------------------------------] + +[heading Server Certificate] + +A Server Certificate is a digital certificate that confirms a server's identity +as the legitimate destination for a client. It contains a verifiable signature +that ensures it was issued by a trusted certificate authority (CA). + +When a server certificate is issued by an intermediate certificate authority, +and the client lacks those intermediate certificates, the server should provide +all the relevant certificates to the client. This allows the client to verify +the final certificate in the chain against the root certificate. + +The following Boost.Asio methods can be used for loading a certificate or a +certificate chain: + +* [@boost:/doc/html/boost_asio/reference/ssl__context/use_certificate.html `net::ssl::context::use_certificate`] +* [@boost:/doc/html/boost_asio/reference/ssl__context/use_certificate_file.html `net::ssl::context::use_certificate_file`] +* [@boost:/doc/html/boost_asio/reference/ssl__context/use_certificate_chain.html `net::ssl::context::use_certificate_chain`] +* [@boost:/doc/html/boost_asio/reference/ssl__context/use_certificate_chain_file.html `net::ssl::context::use_certificate_chain_file`] + +[/-----------------------------------------------------------------------------] + +[heading Client Certificate] + +A server can authenticate clients by requiring and verifying their certificates, +preventing access for those without a valid certificate and private key. The +server enforces this by modifying peer verification settings: + +[snippet_core_8] + +If used, the necessary CA certificates must be loaded into the server's SSL +context to enable verification of the client's certificate. + +[/-----------------------------------------------------------------------------] + +[heading Common Name and Subject Alternative Name] + +The Subject Alternative Name (SAN) is an extension in X.509 certificates that +allows multiple domain names, subdomains, or IP addresses to be associated with +a single SSL/TLS certificate. Before that it was the Common Name field in the +certificate subject which could contain a single hostname. + +[@https://datatracker.ietf.org/doc/html/rfc6125#appendix-B.2 RFC 6125] +recommends that if a certificate includes a SAN dNSName field, the client must +ignore the subject CN field. Some modern browsers, such as Google Chrome, check +only the SAN section in an SSL/TLS certificate and reject certificates that +contain only the CN field. + +[/-----------------------------------------------------------------------------] + +[heading Private Key] + +The private key of a certificate is required during the SSL/TLS handshake to +prove that the certificate's provider is its rightful owner + +The following Boost.Asio methods can be used for loading a private key: + +* [@boost:/doc/html/boost_asio/reference/ssl__context/use_private_key.html `net::ssl::context::use_private_key`] +* [@boost:/doc/html/boost_asio/reference/ssl__context/use_private_key_file.html `net::ssl::context::use_private_key_file`] +* [@boost:/doc/html/boost_asio/reference/ssl__context/use_rsa_private_key.html `net::ssl::context::use_rsa_private_key`] +* [@boost:/doc/html/boost_asio/reference/ssl__context/use_rsa_private_key_file.html `net::ssl::context::use_rsa_private_key_file`] + +If the private key is secured with a password, the +[@boost:/doc/html/boost_asio/reference/ssl__context/set_password_callback.html +net::ssl::context::set_password_callback] allows specifying a callable object to +retrieve the password. + +[/-----------------------------------------------------------------------------] + +[heading Self-Signed and Self-Issued Certificates] + +A self-issued certificate is a certificate where the issuer and subject are the +same entity. + +A self-signed certificate is a self-issued certificate in which the digital +signature can be verified using the public key within the certificate. + +[warning + Installing an untrusted, self-issued, or self-signed CA certificate poses a + significant security risk, as there are no restrictions on the domains for + which it can issue certificates. This allows attackers to generate + fraudulent certificates for any public domain, enabling man-in-the-middle + attacks if they gain access to your network. +] + +[/-----------------------------------------------------------------------------] + +[heading Diffie-Hellman (DH) Parameters] + +Diffie-Hellman (DH) key exchange is a cryptographic protocol that allows two +parties to securely establish a shared secret over an insecure communication +channel. The key exchange process involves both parties agreeing on a set of +parameters, known as Diffie-Hellman parameters, which include a large prime +number `p` and a generator `g`. Since generating these parameters is a +computationally expensive task, a user might prefer to provide a precomputed +value at startup. + +The following Boost.Asio methods can be used for loading DH parameters: + +* [@boost:/doc/html/boost_asio/reference/ssl__context/use_tmp_dh.html `net::ssl::context::use_tmp_dh`] +* [@boost:/doc/html/boost_asio/reference/ssl__context/use_tmp_dh_file.html `net::ssl::context::use_tmp_dh_file`] + +If no DH parameter is provided, OpenSSL will refuse to perform any handshake +that uses DHE-based cipher suites but will still work with other cipher suites, +such as those based on ECDHE. + +[/-----------------------------------------------------------------------------] + +[heading A Self-Issued Certificate Example] + +In the following example, we will generate a self-signed CA certificate and use +it to issue both server and client certificates. + +* Generate a CA certificate: + +``` +openssl req -new -newkey rsa:4096 -keyout ca.key -x509 -out ca.crt -subj "/CN=localhost" -days 365 +``` + + +* Generate a Server CSR: + +``` +openssl req -new -newkey rsa:4096 -keyout server.key -out server.csr -subj "/CN=localhost" -addext "subjectAltName=DNS:localhost,IP:127.0.0.1" +``` + + +* Sign the Server CSR using our CA: + +``` +openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -copy_extensions copy -days 365 -out server.crt +``` + + +* Generate a Client CSR: + +``` +openssl req -new -newkey rsa:4096 -keyout client.key -out client.csr -subj "/CN=client.1" +``` + + +* Sign the Client CSR using our CA: + +``` +openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -days 365 -out client.crt +``` + +* Generate a DH parameters file: + +``` +openssl dhparam -out dh4096.pem 4096 +``` + +Server example: [path_link example/doc/ssl/server.cpp server.cpp] + +Note that the server is configured in such a way that it requests and verifies +the client certificate. You can disable this by commenting out the related line +in the example. + +You can test the server using this cURL command: + +``` +curl https://localhost:8080 --cacert ca.crt --cert client.crt --key client.key +``` + +Also, you can use the client example: [path_link example/doc/ssl/client.cpp client.cpp] + +[endsect] diff --git a/doc/qbk/03_core/_core_zh_Hans.qbk b/doc/qbk/03_core/_core_zh_Hans.qbk new file mode 100644 index 0000000..7dea56a --- /dev/null +++ b/doc/qbk/03_core/_core_zh_Hans.qbk @@ -0,0 +1,79 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section:using_io 网络通信] + +该库使用的是 [@http://cplusplus.github.io/networking-ts/draft.pdf 网络技术规范],当时预计最早要到 2023 年才有可能成为 C++ 官方标准的一部分。目前已有三个实现版本,它们在接口上有细微差异,但函数签名和类型声明基本相同:分别是 Boost.Asio、独立版 Asio 以及 networking-ts-impl。下表展示了在各个实现中,如何通过引入对应的头文件并使用合适的命名空间别名来声明 `io_context` 类型的变量: + +[table 网络库的实现版本 +[[Name][命名空间与头文件示例]] +[ + [__Asio__] + [ +``` + #include + namespace net = boost::asio; + net::io_context ioc; +``` + ] +][ + [[@https://think-async.com/Asio/ Asio (Standalone)]] + [ +``` + #include + namespace net = asio; + net::io_context ioc; +``` + ] +][ + [[@https://github.com/chriskohlhoff/networking-ts-impl networking-ts-impl]] + [ +``` + #include + namespace net = std::experimental::net; + net::io_context ioc; +``` + ] +] +] + +本文档将上述三种实现统称为 [*网络库](或简称为 ['networking])。Boost.Asio 和 Asio 这两种网络库实现方式还提供了一些当前未纳入 C++ 标准提案但未来可能被加入的功能特性,例如: + +* [@boost:/doc/html/boost_asio/reference/serial_port.html Serial ports] +* [@boost:/doc/html/boost_asio/reference/local__stream_protocol.html UNIX domain sockets] +* [@boost:/doc/html/boost_asio/reference/signal_set.html POSIX signals] (e.g. SIGINT, SIGABORT) +* [@boost:/doc/html/boost_asio/reference/ssl__stream.html TLS streams] (such as OpenSSL) + +Boost.Beast 目前专门依赖于网络库的 Boost.Asio 实现(尽管未来可能会有所变化)。该库虽然提供了高性能的 HTTP 与 WebSocket 网络协议实现,但涉及域名解析(DNS 查询)、建立对外连接以及接受入站连接等通用任务时,仍需依赖网络库接口来完成。调用方需负责与网络库进行交互,将相关对象初始化至可供本库使用的正确状态。 + +在本文档、示例代码及具体实现中,使用 `net` 命名空间来限定网络库中的各类标识符。对于 Boost.Beast 而言,`net` 是 `boost::asio` 命名空间的别名。 + +为便于使用,本库提供了丰富的类型与算法集合。文档的此部分将对相关类型和算法进行说明,提供使用示例,同时包含网络库使用的复习与教程。 + +[heading 缩略语] + +本文档假定读者已熟悉 __Asio__(使用 Beast 的必要前提)。全文中的示例代码与标识符均按以下声明处于有效状态为前提编写: + +[snippet_core_1a] +[snippet_core_1b] + +[include 1_refresher.qbk] +[include 2_streams.qbk] +[include 3_timeouts.qbk] +[include 4__layers.qbk] +[include 5_buffers.qbk] +[include 6_files.qbk] +[include 7_composed.qbk] +[include 9_ssl_tls_certificate.qbk] +[include 10_ssl_tls_shutdown.qbk] +[endsect] + +[section:config 配置] +[include 8_conf_macros.qbk] +[endsect] diff --git a/doc/qbk/04_http/01_primer_zh_Hans.qbk b/doc/qbk/04_http/01_primer_zh_Hans.qbk new file mode 100644 index 0000000..3aa24db --- /dev/null +++ b/doc/qbk/04_http/01_primer_zh_Hans.qbk @@ -0,0 +1,155 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section Protocol Primer] + +The HTTP protocol defines the +[@https://tools.ietf.org/html/rfc7230#section-2.1 client and server roles]: +clients send requests and servers send back responses. When a client and +server have established a connection, the client sends a series of requests +while the server sends back at least one response for each received request +in the order those requests were received. + +A request or response is an +[@https://tools.ietf.org/html/rfc7230#section-3 HTTP message] +(referred to hereafter as "message") having two parts: +a header with structured metadata and an optional variable-length body +holding arbitrary data. A serialized header is one or more text lines +where each line ends in a carriage return followed by linefeed (`"\r\n"`). +An empty line marks the end of the header. The first line in the header +is called the ['start-line]. The contents of the start line contents are +different for requests and responses. + +Every message contains a set of zero or more field name/value pairs, +collectively called "fields". The names and values are represented using +text strings with various requirements. A serialized field contains the +field name, then a colon followed by a space (`": "`), and finally the field +value with a trailing CRLF. + +[heading Requests] + +Clients send requests, which contain a +[@https://tools.ietf.org/html/rfc7230#section-3.1.1 method] +and +[@https://tools.ietf.org/html/rfc7230#section-5.3 request-target], +and +[@https://tools.ietf.org/html/rfc7230#section-2.6 HTTP-version]. +The method identifies the operation to be performed while the target +identifies the object on the server to which the operation applies. +The version is almost always 1.1, but older programs sometimes use 1.0. + +[table +[[Serialized Request][Description]] +[[ +``` + GET / HTTP/1.1\r\n + User-Agent: Beast\r\n + \r\n +``` +][ + This request has a method of "GET", a target of "/", and indicates + HTTP version 1.1. It contains a single field called "User-Agent" + whose value is "Beast". There is no message body. +]] +] + +[heading Responses] + +Servers send responses, which contain a +[@https://tools.ietf.org/html/rfc7231#section-6 status-code], +[@https://tools.ietf.org/html/rfc7230#section-3.1.2 reason-phrase], and +[@https://tools.ietf.org/html/rfc7230#section-2.6 HTTP-version]. +The reason phrase is +[@https://tools.ietf.org/html/rfc7230#section-3.1.2 obsolete]: +clients SHOULD ignore the reason-phrase content. Here is a response which +includes a body. The special +[@https://tools.ietf.org/html/rfc7230#section-3.3.2 Content-Length] +field informs the remote host of the size of the body which follows. + +[table +[[Serialized Response][Description]] +[[ +``` + HTTP/1.1 200 OK\r\n + Server: Beast\r\n + Content-Length: 13\r\n + \r\n + Hello, world! +``` +][ + This response has a + [@https://tools.ietf.org/html/rfc7231#section-6 200 status code] + meaning the operation requested completed successfully. The obsolete + reason phrase is "OK". It specifies HTTP version 1.1, and contains + a body 13 octets in size with the text "Hello, world!". +]] +] + +[heading Body] + +Messages may optionally carry a body. The size of the message body +is determined by the semantics of the message and the special fields +Content-Length and Transfer-Encoding. +[@https://tools.ietf.org/html/rfc7230#section-3.3 rfc7230 section 3.3] +provides a comprehensive description for how the body length is +determined. + +[heading Special Fields] + +Certain fields appearing in messages are special. The library understands +these fields when performing serialization and parsing, taking automatic +action as needed when the fields are parsed in a message and also setting +the fields if the caller requests it. + +[table Special Fields +[[Field][Description]] +[ + [ + [@https://tools.ietf.org/html/rfc7230#section-6.1 [*`Connection`]] + + [@https://tools.ietf.org/html/rfc7230#appendix-A.1.2 [*`Proxy-Connection`]] + ][ + This field allows the sender to indicate desired control options + for the current connection. Common values include "close", + "keep-alive", and "upgrade". + ] +][ + [ + [@https://tools.ietf.org/html/rfc7230#section-3.3.2 [*`Content-Length`]] + ][ + When present, this field informs the recipient about the exact + size in bytes of the body which follows the message header. + ] +][ + [ + [@https://tools.ietf.org/html/rfc7230#section-3.3.1 [*`Transfer-Encoding`]] + ][ + This optional field lists the names of the sequence of transfer codings + that have been (or will be) applied to the content payload to form + the message body. + + Beast understands the "chunked" coding scheme when it is the last + (outermost) applied coding. The library will automatically apply + chunked encoding when the content length is not known ahead of time + during serialization, and the library will automatically remove chunked + encoding from parsed messages when present. + ] +][ + [ + [@https://tools.ietf.org/html/rfc7230#section-6.7 [*`Upgrade`]] + ][ + The Upgrade header field provides a mechanism to transition from + HTTP/1.1 to another protocol on the same connection. For example, it + is the mechanism used by WebSocket's initial HTTP handshake to + establish a WebSocket connection. + ] +] +] + +[endsect] diff --git a/doc/qbk/04_http/02_message_zh_Hans.qbk b/doc/qbk/04_http/02_message_zh_Hans.qbk new file mode 100644 index 0000000..9d7bc50 --- /dev/null +++ b/doc/qbk/04_http/02_message_zh_Hans.qbk @@ -0,0 +1,235 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section Message Containers] + +Beast provides a single class template __message__ and some aliases which +model HTTP/1 and +[@https://tools.ietf.org/html/rfc7540 HTTP/2] +messages: + +[table Message +[[Name][Description]] +[[ + __message__ +][ + ``` + /// An HTTP message + template< + bool isRequest, // `true` for requests, `false` for responses + class Body, // Controls the container and algorithms used for the body + class Fields = fields> // The type of container to store the fields + class message; + ``` +]] +[[ + [link beast.ref.boost__beast__http__request `request`] +][ + ``` + /// A typical HTTP request + template + using request = message; + ``` +]] +[[ + [link beast.ref.boost__beast__http__response `response`] +][ + ``` + /// A typical HTTP response + template + using response = message; + ``` +]] +] + +The container offers value semantics including move and copy if supported +by __Body__ and __Fields__. User defined template function parameters can +accept any message, or can use partial specialization to accept just +requests or responses. The default __fields__ is a provided associative +container using the standard allocator and supporting modification and +inspection of fields. As per __rfc7230__, a non-case-sensitive comparison +is used for field names. User defined types for fields are possible. +The `Body` type determines the type of the container used to represent the +body as well as the algorithms for transferring buffers to and from the +container. The library comes with a collection of common body types. As +with fields, user defined body types are possible. + +Sometimes it is desired to only work with a header. Beast provides a single +class template __header__ and some aliases to model HTTP/1 and HTTP/2 headers: + +[table Header +[[Name][Description]] +[[ + __header__ +][ + ``` + /// An HTTP header + template< + bool isRequest, // `true` for requests, `false` for responses + class Fields = fields> // The type of container to store the fields + class header; + ``` +]] +[[ + [link beast.ref.boost__beast__http__request_header `request_header`] +][ + ``` + /// A typical HTTP request header + template + using request_header = header; + ``` +]] +[[ + [link beast.ref.boost__beast__http__response_header `response_header`] +][ + ``` + /// A typical HTTP response header + template + using response_header = header; + ``` +]] +] + +Requests and responses share the version, fields, and body but have +a few members unique to the type. This is implemented by declaring the +header classes as partial specializations of `isRequest`. __message__ +is derived from __header__; a message may be passed as an argument to +a function taking a suitably typed header as a parameter. Additionally, +`header` is publicly derived from `Fields`; a message inherits all the +member functions of `Fields`. This diagram shows the inheritance +relationship between header and message, along with some of the +notable differences in members in each partial specialization: + +[$beast/images/message.png [width 730px] [height 459px]] + +[heading:body Body Types] + +Beast defines the __Body__ concept, which determines both the type of +the [link beast.ref.boost__beast__http__message.body `message::body`] member +(as seen in the diagram above) and may also include algorithms for +transferring buffers in and out. These algorithms are used during +parsing and serialization. Users may define their own body types which +meet the requirements, or use the ones that come with the library: + +[table +[[Name][Description]] +[[ + [link beast.ref.boost__beast__http__buffer_body `buffer_body`] +][ + A body whose + [link beast.ref.boost__beast__http__buffer_body__value_type `value_type`] + holds a raw pointer and size to a caller-provided buffer. + This allows for serialization of body data coming from + external sources, and incremental parsing of message body + content using a fixed size buffer. +]] +[[ + [link beast.ref.boost__beast__http__dynamic_body `dynamic_body`] + + [link beast.ref.boost__beast__http__basic_dynamic_body `basic_dynamic_body`] +][ + A body whose `value_type` is a __DynamicBuffer__. It inherits + the insertion complexity of the underlying choice of dynamic buffer. + Messages with this body type may be serialized and parsed. +]] +[[ + [link beast.ref.boost__beast__http__empty_body `empty_body`] +][ + A special body with an empty `value_type` indicating that the + message has no body. Messages with this body may be serialized + and parsed; however, body octets received while parsing a message + with this body will generate a unique error. +]] +[[ + [link beast.ref.boost__beast__http__file_body `file_body`] + + [link beast.ref.boost__beast__http__basic_file_body `basic_file_body`] +][ + This body is represented by a file opened for either reading or + writing. Messages with this body may be serialized and parsed. + HTTP algorithms will use the open file for reading and writing, + for streaming and incremental sends and receives. +]] +[[ + [link beast.ref.boost__beast__http__span_body `span_body`] +][ + A body whose `value_type` is a + [@boost:/libs/core/doc/html/core/span.html `span`], + a non-owning reference to a single linear buffer of bytes. + Messages with this body type may be serialized and parsed. +]] +[[ + [link beast.ref.boost__beast__http__string_body `string_body`] + + [link beast.ref.boost__beast__http__basic_string_body `basic_string_body`] +][ + A body whose `value_type` is `std::basic_string` or `std::string`. + Insertion complexity is amortized constant time, while capacity + grows geometrically. Messages with this body type may be serialized + and parsed. This is the type of body used in the examples. +]] +[[ + [link beast.ref.boost__beast__http__vector_body `vector_body`] +][ + A body whose `value_type` is `std::vector`. Insertion complexity + is amortized constant time, while capacity grows geometrically. + Messages with this body type may be serialized and parsed. +]] +] + +[heading Usage] + +These examples show how to create and fill in request and response +objects: Here we build an +[@https://tools.ietf.org/html/rfc7231#section-4.3.1 HTTP GET] +request with an empty message body: + +[table Create Request +[[Statements] [Serialized Result]] +[[ + [http_snippet_2] +][ +``` + GET /index.htm HTTP/1.1\r\n + Accept: text/html\r\n + User-Agent: Beast\r\n + \r\n +``` +]] +] + +In this code we create an HTTP response with a status code indicating success. +This message has a body with a non-zero length. The function +[link beast.ref.boost__beast__http__message.prepare_payload `message::prepare_payload`] +automatically sets the Content-Length or Transfer-Encoding field +depending on the content and type of the `body` member. Use of this function +is optional; these fields may also be set explicitly. + +[table Create Response +[[Statements] [Serialized Result]] +[[ + [http_snippet_3] +][ +``` + HTTP/1.1 200 OK\r\n + Server: Beast\r\n + Content-Length: 13\r\n + \r\n + Hello, world! +``` +]] +] + +The implementation will automatically fill in the obsolete +[@https://tools.ietf.org/html/rfc7230#section-3.1.2 reason-phrase] +from the status code when serializing a message. Or it may +be set directly using +[link beast.ref.boost__beast__http__header.reason.overload2 `header::reason`]. + +[endsect] diff --git a/doc/qbk/04_http/03_streams_zh_Hans.qbk b/doc/qbk/04_http/03_streams_zh_Hans.qbk new file mode 100644 index 0000000..ba7e565 --- /dev/null +++ b/doc/qbk/04_http/03_streams_zh_Hans.qbk @@ -0,0 +1,111 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section Message Stream Operations] + +Beast provides synchronous and asynchronous algorithms to parse and +serialize HTTP/1 wire format messages on streams. These functions form +the message-oriented stream interface: + +[table Message Stream Operations +[[Name][Description]] +[[ + [link beast.ref.boost__beast__http__read.overload3 [*read]] +][ + Read a __message__ from a __SyncReadStream__. +]] +[[ + [link beast.ref.boost__beast__http__async_read.overload2 [*async_read]] +][ + Read a __message__ from an __AsyncReadStream__. +]] +[[ + [link beast.ref.boost__beast__http__write.overload1 [*write]] +][ + Write a __message__ to a __SyncWriteStream__. +]] +[[ + [link beast.ref.boost__beast__http__async_write [*async_write]] +][ + Write a __message__ to an __AsyncWriteStream__. +]] +] + +All synchronous stream operations come in two varieties. One which throws +an exception upon error, and another which accepts as the last parameter an +argument of type [link beast.ref.boost__beast__error_code `error_code&`]. If an error +occurs this argument will be set to contain the error code. + + + +[heading Reading] + +Because a serialized header is not length-prefixed, algorithms which +parse messages from a stream may read past the end of a message for +efficiency. To hold this surplus data, all stream read operations use +a passed-in __DynamicBuffer__ which must be persisted between calls +until the end of stream is reached or the stream object is destroyed. +Each read operation may consume bytes remaining in the buffer, and +leave behind new bytes. In this example we declare the buffer and a +message variable, then read a complete HTTP request synchronously: + +[http_snippet_4] + +This example uses __flat_buffer__. Beast's __basic_parser__ is +optimized for structured HTTP data located in a single contiguous +(['flat]) memory buffer. When not using a flat buffer the implementation +may perform an additional memory allocations to restructure the input +into a single buffer for parsing. + +[tip + Other Implementations of __DynamicBuffer__ may avoid parser + memory allocation by always returning buffer sequences of + length one. +] + +Messages may also be read asynchronously. When performing asynchronous +stream read operations the stream, buffer, and message variables must +remain valid until the operation has completed. Beast asynchronous +initiation functions use Asio's completion handler model. This call +reads a message asynchronously and reports the error code upon +completion. The handler is called with the error, set to any that +occurs, and the number of bytes parsed. This number may be used to +measure the relative amount of work performed, or it may be ignored +as this example shows. + +[http_snippet_5] + +If a read stream algorithm cannot complete its operation without exceeding +the maximum specified size of the dynamic buffer provided, the error +[link beast.ref.boost__beast__http__error `buffer_overflow`] +is returned. This is one technique which may be used to impose a limit on +the maximum size of an HTTP message header for protection from buffer +overflow attacks. The following code will print the error message: + +[http_snippet_6] + + + +[heading Writing] + +A set of free functions allow serialization of an entire HTTP message to +a stream. This example constructs and sends an HTTP response: + +[http_snippet_7] + +The asynchronous version could be used instead: + +[http_snippet_8] + +The completion handler is called with the number of bytes written to the +stream, which includes protocol specific data such as the delimiters in +the header and line endings. The number may be used to measure the amount +of data transferred, or it may be ignored as in the example. + +[endsect] diff --git a/doc/qbk/04_http/04_serializer_streams_zh_Hans.qbk b/doc/qbk/04_http/04_serializer_streams_zh_Hans.qbk new file mode 100644 index 0000000..f37aae4 --- /dev/null +++ b/doc/qbk/04_http/04_serializer_streams_zh_Hans.qbk @@ -0,0 +1,112 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section Serializer Stream Operations] + +Non-trivial algorithms need to do more than send entire messages +at once, such as: + +* Send the header first, and the body later. + +* Send a message incrementally: bounded work in each I/O cycle. + +* Use a series of caller-provided buffers to represent the body. + +These tasks may be performed by using the serializer stream interfaces. +To use these interfaces, first construct an appropriate serializer +from the message to be sent: + +[table Serializer +[[Name][Description]] +[[ + __serializer__ +][ + ``` + /// Provides buffer oriented HTTP message serialization functionality. + template< + bool isRequest, + class Body, + class Fields = fields + > + class serializer; + ``` +]] +[[ + [link beast.ref.boost__beast__http__request_serializer `request_serializer`] +][ + ``` + /// A serializer for HTTP/1 requests + template< + class Body, + class Fields = fields + > + using request_serializer = serializer; + ``` +]] +[[ + [link beast.ref.boost__beast__http__response_serializer `response_serializer`] +][ + ``` + /// A serializer for HTTP/1 responses + template< + class Body, + class Fields = fields + > + using response_serializer = serializer; + ``` +]] +] + +The choices for template types must match the message passed on construction. +This code creates an HTTP response and the corresponding serializer: + +[http_snippet_10] + +The stream operations which work on serializers are: + +[table Serializer Stream Operations +[[Name][Description]] +[[ + [link beast.ref.boost__beast__http__write.overload1 [*write]] +][ + Send everything in a __serializer__ to a __SyncWriteStream__. +]] +[[ + [link beast.ref.boost__beast__http__async_write.overload1 [*async_write]] +][ + Send everything in a __serializer__ asynchronously to an __AsyncWriteStream__. +]] +[[ + [link beast.ref.boost__beast__http__write_header.overload1 [*write_header]] +][ + Send only the header from a __serializer__ to a __SyncWriteStream__. +]] +[[ + [link beast.ref.boost__beast__http__async_write_header [*async_write_header]] +][ + Send only the header from a __serializer__ asynchronously to an __AsyncWriteStream__. +]] +[[ + [link beast.ref.boost__beast__http__write_some.overload1 [*write_some]] +][ + Send part of a __serializer__ to a __SyncWriteStream__. +]] +[[ + [link beast.ref.boost__beast__http__async_write_some [*async_write_some]] +][ + Send part of a __serializer__ asynchronously to an __AsyncWriteStream__. +]] +] + +Here is an example of using a serializer to send a message on a stream +synchronously. This performs the same operation as calling `write(stream, m)`: + +[http_snippet_12] + +[endsect] diff --git a/doc/qbk/04_http/05_parser_streams_zh_Hans.qbk b/doc/qbk/04_http/05_parser_streams_zh_Hans.qbk new file mode 100644 index 0000000..3a9d217 --- /dev/null +++ b/doc/qbk/04_http/05_parser_streams_zh_Hans.qbk @@ -0,0 +1,152 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section Parser Stream Operations] + +Non-trivial algorithms need to do more than receive entire messages +at once, such as: + + +* Receive the header first and body later. + +* Receive a large body using a fixed-size buffer. + +* Receive a message incrementally: bounded work in each I/O cycle. + +* Defer the commitment to a __Body__ type until after reading the header. + +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 using the __basic_fields__ Fields container. + +[table Parser +[[Name][Description]] +[[ + __parser__ +][ + ``` + /// 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 Allocator = std::allocator> // The type of allocator for the header + class parser + : public basic_parser<...>; + ``` +]] +[[ + [link beast.ref.boost__beast__http__request_parser `request_parser`] +][ + ``` + /// An HTTP/1 parser for producing a request message. + template> + using request_parser = parser; + ``` +]] +[[ + [link beast.ref.boost__beast__http__response_parser `response_parser`] +][ + ``` + /// An HTTP/1 parser for producing a response message. + template> + using response_parser = parser; + ``` +]] +] + +[note + The __basic_parser__ and classes derived from it handle octet streams + serialized in the HTTP/1 format described in __rfc7230__. +] + +The stream operations which work on parsers are: + +[table Parser Stream Operations +[[Name][Description]] +[[ + [link beast.ref.boost__beast__http__read.overload1 [*read]] +][ + Read everything into a parser from a __SyncReadStream__. +]] +[[ + [link beast.ref.boost__beast__http__async_read.overload1 [*async_read]] +][ + Read everything into a parser asynchronously from an __AsyncReadStream__. +]] +[[ + [link beast.ref.boost__beast__http__read_header.overload1 [*read_header]] +][ + Read only the header octets into a parser from a __SyncReadStream__. +]] +[[ + [link beast.ref.boost__beast__http__async_read_header [*async_read_header]] +][ + Read only the header octets into a parser asynchronously from an __AsyncReadStream__. +]] +[[ + [link beast.ref.boost__beast__http__read_some.overload1 [*read_some]] +][ + Read some octets into a parser from a __SyncReadStream__. +]] +[[ + [link beast.ref.boost__beast__http__async_read_some [*async_read_some]] +][ + Read some octets into a parser asynchronously from an __AsyncReadStream__. +]] +] + +As with message stream operations, parser stream operations require a +persisted __DynamicBuffer__ for holding unused octets from the stream. +The basic parser implementation is optimized for the case where this dynamic +buffer stores its input sequence in a single contiguous memory buffer. It is +advised to use an instance of __flat_buffer__, __flat_static_buffer__, or +__flat_static_buffer_base__ for this purpose, although a user defined instance +of __DynamicBuffer__ which produces input sequences of length one is also +suitable. + +The parser contains a message constructed internally. Arguments passed +to the parser's constructor are forwarded into the message container. +The caller can access the message inside the parser by calling +[link beast.ref.boost__beast__http__parser.get `parser::get`]. +If the `Fields` and `Body` types are [*MoveConstructible], the caller +can take ownership of the message by calling +[link beast.ref.boost__beast__http__parser.release `parser::release`]. In this example +we read an HTTP response with a string body using a parser, then print +the response: + +[http_snippet_13] + + + +[section:incremental_read Incremental Read __example__] + +This function uses +[link beast.ref.boost__beast__http__buffer_body `buffer_body`] +and parser stream operations to read a message body progressively +using a small, fixed-size buffer: + +[example_incremental_read] + +[endsect] + + + +[section:read_large_response_body Reading large response body __example__] + +This example presents how to increase the default limit of the response body size, +thus the content larger than the default 8MB can be read. + +[example_read_large_response_body] + +[endsect] + + + +[endsect] diff --git a/doc/qbk/04_http/06_serializer_buffers_zh_Hans.qbk b/doc/qbk/04_http/06_serializer_buffers_zh_Hans.qbk new file mode 100644 index 0000000..f5379be --- /dev/null +++ b/doc/qbk/04_http/06_serializer_buffers_zh_Hans.qbk @@ -0,0 +1,81 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section Buffer-Oriented Serializing] +[block''''''] + +An instance of __serializer__ can be invoked directly, without using +the provided stream operations. This could be useful for implementing +algorithms on objects whose interface does not conform to __Stream__. +For example, a +[@https://github.com/libuv/libuv *libuv* socket]. +The serializer interface is interactive; the caller invokes it repeatedly +to produce buffers until all of the serialized octets have been generated. +Then the serializer is destroyed. + +To obtain the serialized next buffer sequence, call +[link beast.ref.boost__beast__http__serializer.next `serializer::next`]. +Then, call +[link beast.ref.boost__beast__http__serializer.consume `serializer::consume`] +to indicate the number of bytes consumed. This updates the next +set of buffers to be returned, if any. +`serializer::next` takes an error code parameter and invokes a visitor +argument with the error code and buffer of unspecified type. In C++14 +this is easily expressed with a generic lambda. The function +[link beast.ref.boost__beast__http__serializer.is_done `serializer::is_done`] +will return `true` when all the buffers have been produced. This C++14 +example prints the buffers to standard output: + +[http_snippet_14] + +Generic lambda expressions are only available in C++14 or later. A functor +with a templated function call operator is necessary to use C++11 as shown: + +[http_snippet_15] + +[heading Split Serialization] + +In some cases, such as the handling of the +[@https://tools.ietf.org/html/rfc7231#section-5.1.1 Expect: 100-continue] +field, it may be desired to first serialize the header, perform some other +action, and then continue with serialization of the body. This is +accomplished by calling +[link beast.ref.boost__beast__http__serializer.split `serializer::split`] +with a boolean indicating that when buffers are produced, the last buffer +containing serialized header octets will not contain any octets corresponding +to the body. The function +[link beast.ref.boost__beast__http__serializer.is_header_done `serializer::is_header_done`] +informs the caller whether the header been serialized fully. In this +C++14 example we print the header first, followed by the body: + +[http_snippet_16] + + + +[section:write_to_std_ostream Write To std::ostream __example__] + +The standard library provides the type `std::ostream` for performing high +level write operations on character streams. The variable `std::cout` is +based on this output stream. This example uses the buffer oriented interface +of __serializer__ to write an HTTP message to a `std::ostream`: + +[example_http_write_ostream] + +[tip + Serializing to a `std::ostream` could be implemented using an alternate + strategy: adapt the `std::ostream` interface to a __SyncWriteStream__, + enabling use with the library's existing stream algorithms. This is + left as an exercise for the reader. +] + +[endsect] + + + +[endsect] diff --git a/doc/qbk/04_http/07_parser_buffers_zh_Hans.qbk b/doc/qbk/04_http/07_parser_buffers_zh_Hans.qbk new file mode 100644 index 0000000..560c536 --- /dev/null +++ b/doc/qbk/04_http/07_parser_buffers_zh_Hans.qbk @@ -0,0 +1,109 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section Buffer-Oriented Parsing] +[block''''''] + +A subclass of __basic_parser__ can be invoked directly, without using +the provided stream operations. This could be useful for implementing +algorithms on objects whose interface does not conform to __Stream__. +For example, a +[@http://zeromq.org/ *ZeroMQ* socket]. +The basic parser interface is interactive; the caller invokes the function +[link beast.ref.boost__beast__http__basic_parser.put `basic_parser::put`] +repeatedly with buffers until an error occurs or the parsing is done. The +function +[link beast.ref.boost__beast__http__basic_parser.put_eof `basic_parser::put_eof`] +Is used when the caller knows that there will never be more data (for example, +if the underlying connection is closed), + +[heading Parser Options] + +The parser provides a few options which may be set before parsing begins: + +[table Parser Options +[[Name][Default][Description]] +[[ + [link beast.ref.boost__beast__http__basic_parser.eager.overload2 `eager`] +][ + `false` +][ + Normally the parser returns after successfully parsing a structured + element (header, chunk header, or chunk body) even if there are octets + remaining in the input. This is necessary when attempting to parse the + header first, or when the caller wants to inspect information which may + be invalidated by subsequent parsing, such as a chunk extension. The + `eager` option controls whether the parser keeps going after parsing + structured element if there are octets remaining in the buffer and no + error occurs. This option is automatically set or cleared during certain + stream operations to improve performance with no change in functionality. +]] +[[ + [link beast.ref.boost__beast__http__basic_parser.skip.overload2 `skip`] +][ + `false` +][ + This option controls whether or not the parser expects to see an HTTP + body, regardless of the presence or absence of certain fields such as + Content-Length or a chunked Transfer-Encoding. Depending on the request, + some responses do not carry a body. For example, a 200 response to a + [@https://tools.ietf.org/html/rfc7231#section-4.3.6 CONNECT] request + from a tunneling proxy, or a response to a + [@https://tools.ietf.org/html/rfc7231#section-4.3.2 HEAD] request. + In these cases, callers may use this function inform the parser that + no body is expected. The parser will consider the message complete + after the header has been received. +]] +[[ + [link beast.ref.boost__beast__http__basic_parser.body_limit `body_limit`] +][ + 1MB/8MB +][ + This function sets the maximum allowed size of the content body. + When a body larger than the specified size is detected, an error + is generated and parsing terminates. This setting helps protect + servers from resource exhaustion attacks. The default limit when + parsing requests is 1MB, and for parsing responses 8MB. +]] +[[ + [link beast.ref.boost__beast__http__basic_parser.header_limit `header_limit`] +][ + 8KB +][ + This function sets the maximum allowed size of the header + including all field name, value, and delimiter characters + and also including the CRLF sequences in the serialized + input. +]] +] + + + +[section:read_from_std_istream Read From std::istream __example__] + +The standard library provides the type `std::istream` for performing high +level read operations on character streams. The variable `std::cin` is based +on this input stream. This example uses the buffer oriented interface of +__basic_parser__ to build a stream operation which parses an HTTP message +from a `std::istream`: + +[example_http_read_istream] + +[tip + Parsing from a `std::istream` could be implemented using an alternate + strategy: adapt the `std::istream` interface to a __SyncReadStream__, + enabling use with the library's existing stream algorithms. This is + left as an exercise for the reader. +] + +[endsect] + + + +[endsect] diff --git a/doc/qbk/04_http/08_chunked_encoding_zh_Hans.qbk b/doc/qbk/04_http/08_chunked_encoding_zh_Hans.qbk new file mode 100644 index 0000000..e0d01a0 --- /dev/null +++ b/doc/qbk/04_http/08_chunked_encoding_zh_Hans.qbk @@ -0,0 +1,264 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section Chunked Encoding] + +For message payloads whose size is not known ahead of time, HTTP +version 1.1 defines the +[@https://tools.ietf.org/html/rfc7230#section-4.1 ['chunked]] +transfer coding. This coding consists of zero or more +[@https://tools.ietf.org/html/rfc7230#section-4.1 ['chunked bodies]], +followed by a +[@https://tools.ietf.org/html/rfc7230#section-4.1 ['last chunk]]. +Each chunked body may contain optional application-defined, connection-specific +[@https://tools.ietf.org/html/rfc7230#section-4.1.1 ['chunk-extensions]]. +The last chunk may contain additional HTTP field values in a section +of the last chunk called a +[@https://tools.ietf.org/html/rfc7230#section-4.1.2 ['chunk-trailer]]. +The field values are "promised" in the header as a comma delimited list +of field names in the +[@https://tools.ietf.org/html/rfc7230#section-4.4 [*Trailer]] +field value. Clients indicate their willingness to accept trailers +by including the "trailers" token in the +[@https://tools.ietf.org/html/rfc7230#section-4.3 [*TE]] +field value. + +[heading Serializing Chunks] + +The __serializer__ automatically applies the chunked transfer encoding +when a message returns `true` from +[link beast.ref.boost__beast__http__message.chunked.overload1 `message::chunked`]. +The boundaries between chunks emitted by the serializer are implementation +defined. Chunk extensions and trailers are omitted. Applications which +need precise control over the chunk boundaries, extensions, and trailers +may use a set of helper classes which enable manual emission of message +payloads using chunk encoding. + +To use these helper classes, first serialize the header portion of the +message using the standard interface. Then prepare the buffers, chunk +extensions, and desired trailers, and use them with these helpers: + +[table Chunking Helpers +[[Name][Description]] +[ + [[link beast.ref.boost__beast__http__chunk_body `chunk_body`]] + [ + A buffer sequence representing a complete chunk body. + ] +][ + [[link beast.ref.boost__beast__http__chunk_crlf `chunk_crlf`]] + [ + A buffer sequence representing the CRLF (`"\r\n"`) delimiter. + This class is used when the caller desires to emit the + chunk body in two or more individual stream operations. + ] +][ + [ + [link beast.ref.boost__beast__http__chunk_extensions `chunk_extensions`] + + + [link beast.ref.boost__beast__http__basic_chunk_extensions `basic_chunk_extensions`] + ] + [ + This is a simple, allocating container which lets callers + easily build up a set of chunk extensions. + ] +][ + [[link beast.ref.boost__beast__http__chunk_header `chunk_header`]] + [ + A buffer sequence representing a hex-encoded chunk size, + followed by an optional set of chunk extensions, including + the terminating CRLF (`"\r\n"`) delimiter which precedes + the chunk body. This class is used when the caller desires + to emit the chunk body in two or more individual stream + operations. + ] +][ + [[link beast.ref.boost__beast__http__chunk_last `chunk_last`]] + [ + A buffer sequence representing a last chunk. The last chunk + indicates the end of the chunked message payload, and may + contain optional trailer fields. + ] +][ + [ + [link beast.ref.boost__beast__http__make_chunk `make_chunk`] + + [link beast.ref.boost__beast__http__make_chunk_last `make_chunk_last`] + ] + [ + These helper functions are used to construct a chunk + or last chunk directly at call sites. + ] +]] + +We demonstrate the use of these objects first by declaring a function +which returns the next buffer sequence to use as a chunk body: + +[http_snippet_17] + +This example demonstrates sending a complete chunked message payload +manually. No chunk extensions or trailers are emitted: + +[http_snippet_18] + +The following code sends additional chunks, and sets chunk extensions +using the helper container. The container automatically quotes values +in the serialized output when necessary: + +[http_snippet_19] + +Callers can take over the generation and management of the extensions +buffer by passing a non-owning string. Note that this requires the +string contents to adhere to the correct syntax for chunk extensions, +including the needed double quotes for values which contain spaces: + +[http_snippet_20] + +The next code sample emits a chunked response which promises two +trailer fields and delivers them in the last chunk. The implementation +allocates memory using the default or a passed-in allocator to hold +the state information required to serialize the trailer: + +[http_snippet_21] + +Using a custom allocator to serialize the last chunk: + +[http_snippet_22] + +Alternatively, callers can take over the generation and lifetime +management of the serialized trailer fields by passing in a non-owning +string: + +[http_snippet_23] + +For the ultimate level of control, a caller can manually compose the +chunk itself by first emitting a header with the correct chunk body +size, and then by emitting the chunk body in multiple calls to the +stream write function. In this case the caller is responsible for +also emitting the terminating CRLF (`"\r\n"`): + +[http_snippet_24] + +[heading Parsing Chunks] + +The __parser__ automatically removes the chunked transfer coding when +it is the last encoding in the list. However, it also discards the +chunk extensions and does not provide a way to determine the boundaries +between chunks. Advanced applications which need to access the chunk +extensions or read complete individual chunks may use a callback +interface provided by __parser__: + +[table Chunking Parse Callbacks +[[Name][Description]] +[ + [[link beast.ref.boost__beast__http__parser.on_chunk_header `on_chunk_header`]] + [ + Set a callback to be invoked on each chunk header. + + The callback will be invoked once for every chunk in the message + payload, as well as once for the last chunk. The invocation + happens after the chunk header is available but before any body + octets have been parsed. + + The extensions are provided in raw, validated form, use + [link beast.ref.boost__beast__http__basic_chunk_extensions.parse `chunk_extensions::parse`] + to parse the extensions into a structured container for easier access. + The implementation type-erases the callback without requiring + a dynamic allocation. For this reason, the callback object is + passed by a non-constant reference. + + The function object will be called with this equivalent signature: + ``` + void + callback( + std::uint64_t size, // Size of the chunk, zero for the last chunk + string_view extensions, // The chunk-extensions in raw form + error_code& ec); // May be set by the callback to indicate an error + ``` + ] +][ + [[link beast.ref.boost__beast__http__parser.on_chunk_body `on_chunk_body`]] + [ + Set a callback to be invoked on chunk body data. + + The callback will be invoked one or more times to provide + buffers corresponding to the chunk body for the current chunk. + The callback receives the number of octets remaining in this + chunk body including the octets in the buffer provided. + + The callback must return the number of octets actually consumed. + Any octets not consumed will be presented again in a subsequent + invocation of the callback. + The implementation type-erases the callback without requiring + a dynamic allocation. For this reason, the callback object is + passed by a non-constant reference. + + The function object will be called with this equivalent signature: + ``` + std::size_t + callback( + std::uint64_t remain, // Octets remaining in this chunk, includes `body` + string_view body, // A buffer holding some or all of the remainder of the chunk body + error_code& ec); // May be set by the callback to indicate an error + ``` + ] +]] + +This example will read a message header from the stream, and then manually +read each chunk. It recognizes the chunk boundaries and outputs the contents +of each chunk as it comes in. Any chunk extensions are printed, each extension +on its own line. Finally, any trailers promised in the header are printed. + +[example_chunk_parsing] + +Given the HTTP response as input on the left, the output of the function shown +above is shown on the right: + +[table Chunk Parsing Example Output +[[Input][Output]] +[ + [ + ``` + HTTP/1.1 200 OK\r\n + Server: test\r\n + Trailer: Expires, Content-MD5\r\n + Transfer-Encoding: chunked\r\n + \r\n + 5\r\n + First\r\n + d;quality=1.0\r\n + Hello, world!\r\n + e;file=abc.txt;quality=0.7\r\n + The Next Chunk\r\n + 8;last\r\n + Last one\r\n + 0\r\n + Expires: never\r\n + Content-MD5: f4a5c16584f03d90\r\n + \r\n + ``` + ] + [ + ``` + Chunk Body: First + Extension: quality = 1.0 + Chunk Body: Hello, world! + Extension: file = abc.txt + Extension: quality = 0.7 + Chunk Body: The Next Chunk + Extension: last + Chunk Body: Last one + Expires: never + Content-MD5: f4a5c16584f03d90 + ``` + ] +]] + +[endsect] diff --git a/doc/qbk/04_http/09_custom_body_zh_Hans.qbk b/doc/qbk/04_http/09_custom_body_zh_Hans.qbk new file mode 100644 index 0000000..ac918eb --- /dev/null +++ b/doc/qbk/04_http/09_custom_body_zh_Hans.qbk @@ -0,0 +1,155 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section Custom Body Types] +[block''''''] + +User-defined types are possible for the message body, where the type meets the +__Body__ requirements. This simplified class declaration +shows the customization points available to user-defined body types: +``` +/// Defines a Body type +struct body +{ + /// This determines the return type of the `message::body` member function + using value_type = ...; + + /// An optional function, returns the body's payload size (which may be zero) + static + std::uint64_t + size(value_type const& v); + + /// The algorithm used for extracting buffers + class reader; + + /// The algorithm used for inserting buffers + class writer; +} +``` + +The meaning of the nested types is as follows + +[table Body Type Members +[[Name][Description]] +[ + [`value_type`] + [ + Determines the type of the + [link beast.ref.boost__beast__http__message.body `message::body`] + member. + ] +][ + [`reader`] + [ + An optional nested type meeting the requirements of __BodyReader__, + which provides the algorithm for storing a forward range of buffer + sequences in the body representation. + If present, this body type may be used with a __parser__. + ] +][ + [`writer`] + [ + An optional nested type meeting the requirements of __BodyWriter__, + which provides the algorithm for converting the body representation + to a forward range of buffer sequences. + If present this body type may be used with a __serializer__. + ] +] +] + +[heading Value Type] + +The `value_type` nested type allows the body to define the declaration of +the body type as it appears in the message. This can be any type. For +example, a body's value type may specify `std::vector` or +`std::list`. A custom body may even set the value type to +something that is not a container for body octets, such as a +[@boost:/libs/filesystem/doc/reference.html#class-path `boost::filesystem::path`]. +Or, a more structured container may be chosen. This declares a body's +value type as a JSON tree structure produced from a +[@boost:/doc/html/json/input_output.html#json.input_output.parsing.streaming_parser `boost::json::stream_parser`]: +``` +#include + +struct Body +{ + using value_type = boost::json::value; + + class reader; + class writer; +}; +``` + +As long as a suitable reader or writer is available to provide the +algorithm for transferring buffers in and out of the value type, +those bodies may be parsed or serialized. + + + +[section:file_body File Body __example__] + +Use of the flexible __Body__ concept customization point enables authors to +preserve the self-contained nature of the __message__ object while allowing +domain specific behaviors. Common operations for HTTP servers include sending +responses which deliver file contents, and allowing for file uploads. In this +example we build the +[link beast.ref.boost__beast__http__basic_file_body `basic_file_body`] +type which supports both reading and +writing to a file on the file system. The interface is a class templated +on the type of file used to access the file system, which must meet the +requirements of __File__. + +First we declare the type with its nested types: + +[example_http_file_body_1] + +We will start with the definition of the `value_type`. Our strategy +will be to store the file object directly in the message container +through the `value_type` field. To use this body it will be necessary +to call `msg.body.file().open()` first with the required information +such as the path and open mode. This ensures that the file exists +throughout the operation and prevent the race condition where the +file is removed from the file system in between calls. + +[example_http_file_body_2] + +Our implementation of __BodyWriter__ will contain a small buffer +from which the file contents are read. The buffer is provided to +the implementation on each call until everything has been read in. + +[example_http_file_body_3] + +And here are the definitions for the functions we have declared: + +[example_http_file_body_4] + +Files can be read now, and the next step is to allow writing to files +by implementing the __BodyReader__. The style is similar to the writer, +except that buffers are incoming instead of outgoing. Here's the +declaration: + +[example_http_file_body_5] + +Finally, here is the implementation of the reader member functions: + +[example_http_file_body_6] + +We have created a full featured body type capable of reading and +writing files on the filesystem, integrating seamlessly with the +HTTP algorithms and message container. The body type works with +any file implementation meeting the requirements of __File__ so +it may be transparently used with solutions optimized for particular +platforms. Example HTTP servers which use file bodies are available +in the example directory. + +[endsect] + + + +[endsect] diff --git a/doc/qbk/04_http/10_custom_parsers_zh_Hans.qbk b/doc/qbk/04_http/10_custom_parsers_zh_Hans.qbk new file mode 100644 index 0000000..facc520 --- /dev/null +++ b/doc/qbk/04_http/10_custom_parsers_zh_Hans.qbk @@ -0,0 +1,31 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section Custom Parsers] + +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 strategies for storing parsed results: the basic parser processes +input buffers into elements according to the HTTP/1 protocol specification, +while the derived class decides what to do with those elements. Custom parsers +will work with all of the HTTP stream read algorithms, as those algorithms use +only the basic parser interface. Some use cases for implementing custom +parsers are: + +* Inspect incoming header fields and keep or discard them. + +* Use a container provided by an external interface. + +The basic parser uses virtual functions. To declare your user-defined parser, +derive from __basic_parser__ and implement all the required virtual functions. +A declaration for the derived class may look like this: + +[code_http_10_custom_parser] + +[endsect] diff --git a/doc/qbk/04_http/_http_zh_Hans.qbk b/doc/qbk/04_http/_http_zh_Hans.qbk new file mode 100644 index 0000000..998060b --- /dev/null +++ b/doc/qbk/04_http/_http_zh_Hans.qbk @@ -0,0 +1,212 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section:using_http HTTP] + +[warning + Higher level functions such as Basic + Authentication, mime/multipart encoding, cookies, automatic handling + of redirects, gzipped transfer encodings, caching, or proxying (to name + a few) are not directly provided, but nothing stops users from creating + these features using Beast's HTTP message types. +] + +This library offers programmers simple and performant models of HTTP messages +and their associated operations including synchronous, asynchronous, and +buffer-oriented parsing and serialization of messages in the HTTP/1 wire +format using __Asio__. Specifically, the library provides: + +[variablelist +[ + [Message Containers] + [ + Complete HTTP messages are modeled using the __message__ class, + with possible user customizations. + ] +][ + [Stream Reading] + [ + The functions + [link beast.ref.boost__beast__http__read `read`], + [link beast.ref.boost__beast__http__read_header `read_header`], + [link beast.ref.boost__beast__http__read_some `read_some`], + [link beast.ref.boost__beast__http__async_read `async_read`], + [link beast.ref.boost__beast__http__async_read_header `async_read_header`], and + [link beast.ref.boost__beast__http__async_read_some `async_read_some`] + read HTTP/1 message data from a + [link beast.concepts.streams stream]. +] +][ + [Stream Writing] + [ + The functions + [link beast.ref.boost__beast__http__write `write`], + [link beast.ref.boost__beast__http__write_header `write_header`], + [link beast.ref.boost__beast__http__write_some `write_some`], + [link beast.ref.boost__beast__http__async_write `async_write`], + [link beast.ref.boost__beast__http__async_write_header `async_write_header`], and + [link beast.ref.boost__beast__http__async_write_some `async_write_some`] + write HTTP/1 message data to a + [link beast.concepts.streams stream]. + ] +][ + [Serialization] + [ + The __serializer__ produces a series of octet buffers + conforming to the __rfc7230__ wire representation of + a __message__. + ] +][ + [Parsing] + [ + The __parser__ attempts to convert a series of octet + buffers into a __message__. + ] +] +] + +Interfaces for operating on HTTP messages are structured into several +layers. The highest level provides ease of use, while lower levels provide +progressively more control, options, and flexibility. At the lowest level +customization points are provided, where user defined types can replace +parts of the implementation. The layers are arranged thusly: + +[table +[[Level][Read/Write What][Description]] +[ + [[*6]] + [ + __message__ + ][ + At the highest level, these free functions send or receive + a complete HTTP message in one call. They are designed for + ease of use: + [link beast.ref.boost__beast__http__read.overload4 `read`], + [link beast.ref.boost__beast__http__write.overload4 `write`], + [link beast.ref.boost__beast__http__async_read.overload2 `async_read`], and + [link beast.ref.boost__beast__http__async_write.overload2 `async_write`]. + ] +][ + [[*5]] + [ + __parser__, __serializer__ + ][ + For more control, callers may take responsibility for managing the + required __parser__ or __serializer__ transient state objects. + This allows additional configuration such as limiting the number + of bytes for message components during parsing, or regulating the + size of buffers emitted during output. These functions send or + receive complete messages using a serializer or parser: + [link beast.ref.boost__beast__http__read.overload2 `read`], + [link beast.ref.boost__beast__http__write.overload2 `write`], + [link beast.ref.boost__beast__http__async_read.overload1 `async_read`], and + [link beast.ref.boost__beast__http__async_write.overload1 `async_write`]. + + ] +][ + [[*4]] + [ + __header__ + ][ + Sometimes it is necessary to first send or receive the HTTP + header. For example, to read the header and take action before + continuing to read the body. These functions use a __parser__ + or __serializer__ to read or write the header: + [link beast.ref.boost__beast__http__read_header.overload2 `read_header`], + [link beast.ref.boost__beast__http__write_header.overload2 `write_header`], + [link beast.ref.boost__beast__http__async_read_header `async_read_header`], and + [link beast.ref.boost__beast__http__async_write_header `async_write_header`]. + ] +][ + [[*3]] + [ + partial __message__ + ][ + All of the stream operations at higher levels thus far have operated + on a complete header or message. At this level it is possible to + send and receive messages incrementally. This allows resource + constrained implementations to perform work bounded on storage, + or allows better control when setting timeouts for example. + These functions read or write bounded amounts of data and return + the number of bytes transacted: + [link beast.ref.boost__beast__http__read_some.overload2 `read_some`], + [link beast.ref.boost__beast__http__write_some.overload2 `write_some`], + [link beast.ref.boost__beast__http__async_read_some `async_read_some`], and + [link beast.ref.boost__beast__http__async_write_some `async_write_some`]. + ] +][ + [[*2]] + [ + [@https://tools.ietf.org/html/rfc7230#section-4.1 ['chunked-body]] + ][ + Until now parse and serialize operations apply or remove the chunked + transfer coding as needed for message payloads whose size is not known + ahead of time. For some domain specific niches, it is necessary + to assume direct control over incoming or outgoing chunks in a chunk + encoded message payload. + For parsing this is achieved by setting hooks using the functions + [link beast.ref.boost__beast__http__parser.on_chunk_header `on_chunk_header`] and/or + [link beast.ref.boost__beast__http__parser.on_chunk_body `on_chunk_body`]. + For serializing callers may first emit the header, and then use + these buffer sequence adapters to control the contents of each chunk + including + [@https://tools.ietf.org/html/rfc7230#section-4.1.1 ['chunk extensions]] + and the + [@https://tools.ietf.org/html/rfc7230#section-4.1.2 ['trailer-part]]: + [link beast.ref.boost__beast__http__chunk_body `chunk_body`], + [link beast.ref.boost__beast__http__chunk_crlf `chunk_crlf`], + [link beast.ref.boost__beast__http__chunk_header `chunk_header`], and + [link beast.ref.boost__beast__http__chunk_last `chunk_last`]. + ] +][ + [[*1]] + [ + buffers + ][ + For ultimate control, the use of library stream algorithms may + be bypassed entirely and instead work directly with buffers by + calling members of __parser__ or __serializer__. + ] +][ + [[*0]] + [ + ['user-defined] + ][ + In addition to the typical customization points of __Stream__ + and __DynamicBuffer__, user-defined types may replace parts of + the library implementation at the lowest level. The customization + points include __Fields__ for creating a container to store HTTP + fields, __Body__ for defining containers and algorithms used for + HTTP message payloads, and user-defined subclasses of + __basic_parser__ for implementing custom message representation + strategies. + ] +]] + +[note + This documentation assumes some familiarity with __Asio__ and + the HTTP protocol specification described in __rfc7230__. Sample + code and identifiers mentioned in this section is written as if + these declarations are in effect: + + [http_snippet_1] +] + +[include 01_primer.qbk] +[include 02_message.qbk] +[include 03_streams.qbk] +[include 04_serializer_streams.qbk] +[include 05_parser_streams.qbk] +[include 06_serializer_buffers.qbk] +[include 07_parser_buffers.qbk] +[include 08_chunked_encoding.qbk] +[include 09_custom_body.qbk] +[include 10_custom_parsers.qbk] + +[endsect] diff --git a/doc/qbk/05_http_examples/_http_examples_zh_Hans.qbk b/doc/qbk/05_http_examples/_http_examples_zh_Hans.qbk new file mode 100644 index 0000000..1bd14e5 --- /dev/null +++ b/doc/qbk/05_http_examples/_http_examples_zh_Hans.qbk @@ -0,0 +1,149 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section:more_examples HTTP Examples] + +These examples in this section are working functions that may be found +in the examples directory. They demonstrate the usage of the library for +a variety of scenarios. + + + +[section:change_body_type Change Body Type __example__] + +Sophisticated servers may wish to defer the choice of the Body template type +until after the header is available. Then, a body type may be chosen +depending on the header contents. For example, depending on the verb, +target path, or target query parameters. To accomplish this, a parser +is declared to read in the header only, using a trivial body type such as +[link beast.ref.boost__beast__http__empty_body `empty_body`]. Then, a new parser is constructed +from this existing parser where the body type is conditionally determined +by information from the header or elsewhere. + +This example illustrates how a server may make the commitment of a body +type depending on the method verb: + +[example_http_defer_body] + +[endsect] + + + +[section:expect_100_continue_client Expect 100-continue (Client) __example__] + +The Expect field with the value "100-continue" in a request is special. It +indicates that the after sending the message header, a client desires an +immediate informational response before sending the message body, which +presumably may be expensive to compute or large. This behavior is described in +[@https://tools.ietf.org/html/rfc7231#section-5.1.1 rfc7231 section 5.1.1]. +Invoking the 100-continue behavior is implemented easily in a client by +constructing a __serializer__ to send the header first, then receiving +the server response, and finally conditionally send the body using the same +serializer instance. A synchronous, simplified version (no timeout) of +this client action looks like this: + +[example_http_send_expect_100_continue] + +[endsect] + + + +[section:expect_100_continue_server Expect 100-continue (Server) __example__] + +The Expect field with the value "100-continue" in a request is special. It +indicates that the after sending the message header, a client desires an +immediate informational response before sending the message body, which +presumably may be expensive to compute or large. This behavior is described in +[@https://tools.ietf.org/html/rfc7231#section-5.1.1 rfc7231 section 5.1.1]. +Handling the Expect field can be implemented easily in a server by constructing +a __parser__ to read the header first, then send an informational HTTP +response, and finally read the body using the same parser instance. A +synchronous version of this server action looks like this: + +[example_http_receive_expect_100_continue] + +[endsect] + + + +[section:head_request_client HEAD request (Client) __example__] + +The +[@https://tools.ietf.org/html/rfc7231#section-4.3.2 HEAD request] +method indicates to the server that the client wishes to receive the +entire header that would be delivered if the method was GET, except +that the body is omitted. When a client wishes to receive the response +to a HEAD request, it is necessary to inform the parser not to expect +a body. This is done by calling +[link beast.ref.boost__beast__http__basic_parser.skip `basic_parser::skip`] +with the value `true`, as shown in this example: + +[example_http_do_head_request] + +[endsect] + + + +[section:head_response_server HEAD response (Server) __example__] + +When a server receives a +[@https://tools.ietf.org/html/rfc7231#section-4.3.2 HEAD request], +the response should contain the entire header that would be delivered +if the method was GET, except that the body is omitted. + +[example_http_do_head_response] + +[endsect] + + + +[section:http_relay HTTP Relay __example__] + +An HTTP proxy acts as a relay between client and server. The proxy reads a +request from the client and sends it to the server, possibly adjusting some +of the headers and representation of the body along the way. Then, the +proxy reads a response from the server and sends it back to the client, +also with the possibility of changing the headers and body representation. + +The example that follows implements a synchronous HTTP relay. It uses a +fixed size buffer, to avoid reading in the entire body so that the upstream +connection sees a header without unnecessary latency. This example brings +together all of the concepts discussed so far, it uses both a __serializer__ +and a __parser__ to achieve its goal: + +[example_http_relay] + +[endsect] + + + +[section:send_child_process_output Send Child Process Output __example__] + +Sometimes it is necessary to send a message whose body is not conveniently +described by a single container. For example, when implementing an HTTP relay +function a robust implementation needs to present body buffers individually +as they become available from the downstream host. These buffers should be +fixed in size, otherwise creating the unnecessary and inefficient burden of +reading the complete message body before forwarding it to the upstream host. + +To enable these use-cases, the body type __buffer_body__ is provided. This +body uses a caller-provided pointer and size instead of an owned container. +To use this body, instantiate an instance of the serializer and fill in +the pointer and size fields before calling a stream write function. + +This example reads from a child process and sends the output back in an +HTTP response. The output of the process is sent as it becomes available: + +[example_http_send_cgi_response] + +[endsect] + + + +[endsect] diff --git a/doc/qbk/06_websocket/01_connecting_zh_Hans.qbk b/doc/qbk/06_websocket/01_connecting_zh_Hans.qbk new file mode 100644 index 0000000..c07dd24 --- /dev/null +++ b/doc/qbk/06_websocket/01_connecting_zh_Hans.qbk @@ -0,0 +1,33 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section:establishing_connections Connecting] + +Before messages can be exchanged, a websocket stream first needs to be +connected, and then to have the websocket handshake performed. The stream +delegates the task of establishing the connection to the next layers. +For example, if the next layer is a connectible stream or socket object, +it can be accessed to call the necessary function for connecting. +Here we make an outbound connection as a client would do. + +[code_websocket_1_1] + +To accept incoming connections, an acceptor is used. The websocket stream +may be constructed from the socket returned by the acceptor when an +incoming connection is established. + +[code_websocket_1_2] + +Alternatively, the incoming connection may be accepted directly into +the socket owned by the websocket stream, using this overload of the +acceptor member function. + +[code_websocket_1_3] + +[endsect] diff --git a/doc/qbk/06_websocket/02_handshaking_zh_Hans.qbk b/doc/qbk/06_websocket/02_handshaking_zh_Hans.qbk new file mode 100644 index 0000000..5066091 --- /dev/null +++ b/doc/qbk/06_websocket/02_handshaking_zh_Hans.qbk @@ -0,0 +1,176 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section Handshaking] + +[/-----------------------------------------------------------------------------] + +[heading Client Role] + +A WebSocket session begins when a client sends the HTTP/1.1 +[@https://tools.ietf.org/html/rfc7230#section-6.7 Upgrade] +request for +[@https://tools.ietf.org/html/rfc6455#section-1.3 WebSocket] +on an established connection, and the server sends an appropriate response +indicating that the request was accepted and that the connection has been +upgraded. The Upgrade request must include the +[@https://tools.ietf.org/html/rfc7230#section-5.4 Host] +field, and the +[@https://tools.ietf.org/html/rfc7230#section-5.3 target] +of the resource to request. +A typical HTTP Upgrade request created and sent by the implementation +will look like this: + +[table WebSocket HTTP Upgrade Request +[[Wire Format][Description]] +[[ +``` + GET / HTTP/1.1 + Host: www.example.com + Upgrade: websocket + Connection: upgrade + Sec-WebSocket-Key: 2pGeTR0DsE4dfZs2pH+8MA== + Sec-WebSocket-Version: 13 + User-Agent: Boost.Beast/216 +``` +][ + The host and target parameters become part of the Host field + and request-target in the resulting HTTP request. The key is + generated by the implementation. Callers who wish to add, + modify, or inspect fields may set the ['decorator] option + on the stream (described later). +]]] + +The +[link beast.ref.boost__beast__websocket__stream `websocket::stream`] +member functions +[link beast.ref.boost__beast__websocket__stream.handshake `handshake`] and +[link beast.ref.boost__beast__websocket__stream.async_handshake `async_handshake`] +are used to send the request with the required host and target strings. This +code connects to the IP address returned from a hostname lookup, then performs +the WebSocket handshake in the client role. + +[code_websocket_2_1] + +When a client receives an HTTP Upgrade response from the server indicating +a successful upgrade, the caller may wish to perform additional validation +on the received HTTP response message. For example, to check that the +response to a basic authentication challenge is valid. To achieve this, +overloads of the handshake member function allow the caller to store the +received HTTP message in an output reference argument of type +[link beast.ref.boost__beast__websocket__response_type `response_type`] +as follows: + +[code_websocket_2_2] + +[/-----------------------------------------------------------------------------] + +[heading Server Role] + +For servers accepting incoming connections, the +[link beast.ref.boost__beast__websocket__stream `websocket::stream`] +can read the incoming upgrade request and automatically reply. If the handshake +meets the requirements, the stream sends back the upgrade response with a +[@https://tools.ietf.org/html/rfc6455#section-4.2.2 ['101 Switching Protocols]] +status code. If the handshake does not meet the requirements, or falls outside +the range of allowed parameters specified by stream options set previously by +the caller, the stream sends back an HTTP response with a status code indicating +an error. Depending on the keep alive setting, the connection may remain open +for a subsequent handshake attempt. A typical HTTP Upgrade response created and +sent by the implementation upon receiving an upgrade request handshake will +look like this: + +[table WebSocket Upgrade HTTP Response +[[Wire Format][Description]] +[[ + ``` + HTTP/1.1 101 Switching Protocols + Upgrade: websocket + Connection: upgrade + Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= + Server: Boost.Beast + ``` +][ + The + [@https://tools.ietf.org/html/rfc6455#section-11.3.3 ['Sec-WebSocket-Accept]] + field value is generated from the request in a fashion specified by + the WebSocket protocol. +]]] + +The +[link beast.ref.boost__beast__websocket__stream `stream`] +member functions +[link beast.ref.boost__beast__websocket__stream.accept `accept`] and +[link beast.ref.boost__beast__websocket__stream.async_accept `async_accept`] +are used to read the WebSocket HTTP Upgrade request handshake from a stream +already connected to an incoming peer, and then send the WebSocket HTTP +Upgrade response, as shown: + +[code_websocket_2_3] + +[heading Handshake Buffering] + +It is possible for servers to read data from the stream and decide later +that the buffered bytes should be interpreted as a WebSocket upgrade +request. To address this usage, overloads of +[link beast.ref.boost__beast__websocket__stream.accept `accept`] and +[link beast.ref.boost__beast__websocket__stream.async_accept `async_accept`] +which accept an additional buffer sequence parameter are provided. + +In this example, the server reads the initial HTTP request header into a +dynamic buffer, then later uses the buffered data to attempt a websocket +upgrade. + +[code_websocket_2_4] + +[heading Inspecting HTTP Requests] + +When implementing an HTTP server that also supports WebSocket, the +server usually reads the HTTP request from the client. To detect when +the incoming HTTP request is a WebSocket Upgrade request, the function +[link beast.ref.boost__beast__websocket__is_upgrade `is_upgrade`] may be used. + +Once the caller determines that the HTTP request is a WebSocket Upgrade, +additional overloads of +[link beast.ref.boost__beast__websocket__stream.accept `accept`] and +[link beast.ref.boost__beast__websocket__stream.async_accept `async_accept`] +are provided which receive the entire HTTP request header as an object +to perform the handshake. By reading the request manually, the program +can handle normal HTTP requests as well as upgrades. The program may +also enforce policies based on the HTTP fields, such as Basic +Authentication. In this example, the request is first read in +using the HTTP algorithms, and then passed to a newly constructed +stream: + +[code_websocket_2_5] + +[heading Subprotocols] + +The WebSocket protocol understands the concept of subprotocols. If the client +is requesting one of a set of subprotocols it will set the header +[@https://tools.ietf.org/html/rfc6455#section-11.3.4 Sec-WebSocket-Protocol] +in the initial WebSocket Upgrade HTTP request. It is up to the server to +parse the header and select one of the protocols to accept. The server +indicates the selected protocol by setting the +[@https://tools.ietf.org/html/rfc6455#section-11.3.4 Sec-WebSocket-Protocol] +header in the accept header. + +This is accomplished with a +[link beast.ref.boost__beast__websocket__stream_base__decorator `decorator`]. + +The code that follows demonstrates how a server reads an HTTP request, identifies it +as a WebSocket Upgrade, and then checks for a preferred matching subprotocol before +performing the WebSocket handshake: + +[code_websocket_2_6] + + +[/-----------------------------------------------------------------------------] + +[endsect] diff --git a/doc/qbk/06_websocket/03_decorator_zh_Hans.qbk b/doc/qbk/06_websocket/03_decorator_zh_Hans.qbk new file mode 100644 index 0000000..fdf14ef --- /dev/null +++ b/doc/qbk/06_websocket/03_decorator_zh_Hans.qbk @@ -0,0 +1,86 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[/-----------------------------------------------------------------------------] + +[section:decorator Decorator] + +For programs which need to modify either the outgoing WebSocket HTTP Upgrade +request, the outgoing WebSocket HTTP Upgrade response, or both, the stream +supports an optional property called a ['decorator]. This is a function +pointer or callable object which is invoked before the implementation +sends an HTTP message. The decorator receives a modifiable reference to +the message, allowing for modifications. The interface to this system +uses: + +[table WebSocket Decorator Interface +[[Name][Description]] +[[ + [link beast.ref.boost__beast__websocket__request_type `request_type`] +][ + This is the type of the object passed to the decorator to + represent HTTP Upgrade requests. +]] +[[ + [link beast.ref.boost__beast__websocket__response_type `response_type`] +][ + This is the type of the object passed to the decorator to + represent HTTP Upgrade response. +]] +[[ + [link beast.ref.boost__beast__websocket__stream_base__decorator `stream_base::decorator`] +][ + Objects of this type are used to hold a decorator to be + set on the stream using `set_option`. +]] +[[ + [link beast.ref.boost__beast__websocket__stream.set_option `stream::set_option`] +][ + This function is used to set a `stream_base::decorator` on the stream. +]] +] + +This declares a normal function which decorates outgoing HTTP requests: + +[code_websocket_3_1] + +When using a decorator, it must be set on the stream before any handshaking +takes place. This sets the decorator on the stream, to be used for all +subsequent calls to accept or handshake: + +[code_websocket_3_2] + +Alternatively, a function object may be used. Small function objects will +not incur a memory allocation. The follow code declares and sets a function +object as a decorator: + +[code_websocket_3_3] + +A lambda may be used in place of a named function object: + +[code_websocket_3_4] + +It also possible for a single decorator to handle both requests and +responses, if it is overloaded for both types either as a generic +lambda (C++14 and later) or as a class as shown here: + +[code_websocket_3_5] + +The implementation takes ownership by decay-copy of the invocable object +used as the decorator. Move-only types are possible: + +[code_websocket_3_6] + +[important + Undefined behavior results if the decorator modifies the fields + specific to perform the WebSocket Upgrade, such as the Upgrade + or Connection fields. +] + +[endsect] diff --git a/doc/qbk/06_websocket/04_messages_zh_Hans.qbk b/doc/qbk/06_websocket/04_messages_zh_Hans.qbk new file mode 100644 index 0000000..e5bc49a --- /dev/null +++ b/doc/qbk/06_websocket/04_messages_zh_Hans.qbk @@ -0,0 +1,122 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[/-----------------------------------------------------------------------------] + +[section:messages Messages] + +Once a websocket session is established, messages can be sent unsolicited by +either peer at any time. A message is made up of one or more ['messages frames]. +Each frame is prefixed with the size of the payload in bytes, followed by the +data. A frame also contains a flag (called 'fin') indicating whether or not it +is the last frame of the message. When a message is made up from only one frame, +it is possible to know immediately what the size of the message will be. +Otherwise, the total size of the message can only be determined once +the last frame is received. + +The boundaries between frames of a multi-frame message are not not considered +part of the message. Intermediaries such as proxies which forward the websocket +traffic are free to "reframe" (split frames and combine them) the message in +arbitrary ways. These intermediaries include Beast, which can reframe messages +automatically in some cases depending on the options set on the stream. + +[caution + An algorithm should never depend on the way that incoming or outgoing + messages are split up into frames. +] + +Messages can be either text or binary. A message sent as text must contain +consist of valid utf8, while a message sent as binary may contain arbitrary +data. In addition to message frames, websocket provides ['control frames] +in the form of ping, pong, and close messages which have a small upper limit +on their payload size. Depending on how a message is framed, control frames +may have more opportunities to be sent in-between. + +[heading Sending] + +These stream members are used to write websocket messages: + +[table WebSocket Stream Write Operations +[[Function][Description]] +[ + [ + [link beast.ref.boost__beast__websocket__stream.write.overload2 `write`], + [link beast.ref.boost__beast__websocket__stream.async_write `async_write`] + ][ + Send a buffer sequence as a complete message. + ] +][ + [ + [link beast.ref.boost__beast__websocket__stream.write_some.overload2 `write_some`], + [link beast.ref.boost__beast__websocket__stream.async_write_some `async_write_some`] + ][ + Send a buffer sequence as part of a message. + ] +]] + +This example shows how to send a buffer sequence as a complete message. + +[code_websocket_4_1] + +The same message could be sent in two or more frames thusly. + +[heading Receiving] + +[table WebSocket Stream Read Operations +[[Function][Description]] +[ + [ + [link beast.ref.boost__beast__websocket__stream.read.overload2 `read`], + [link beast.ref.boost__beast__websocket__stream.async_read `async_read`] + ][ + Read a complete message into a __DynamicBuffer__. + ] +][ + [ + [link beast.ref.boost__beast__websocket__stream.read_some.overload2 `read_some`], + [link beast.ref.boost__beast__websocket__stream.async_read_some.overload1 `async_read_some`] + ][ + Read part of a message into a __DynamicBuffer__. + ] +][ + [ + [link beast.ref.boost__beast__websocket__stream.read_some.overload4 `read_some`], + [link beast.ref.boost__beast__websocket__stream.async_read_some.overload2 `async_read_some`] + ][ + Read part of a message into a __MutableBufferSequence__. + ] +]] + +After the WebSocket handshake is accomplished, callers may send and receive +messages using the message oriented interface. This interface requires that +all of the buffers representing the message are known ahead of time: + +[code_websocket_4_2] + +[important + [link beast.ref.boost__beast__websocket__stream `websocket::stream`] + is not thread-safe. Calls to stream member functions must + all be made from the same implicit or explicit strand. +] + +[heading Frames] + +Some use-cases make it impractical or impossible to buffer the entire +message ahead of time: + +* Streaming multimedia to an endpoint. +* Sending a message that does not fit in memory at once. +* Providing incremental results as they become available. + +For these cases, the partial data oriented interface may be used. This +example reads and echoes a complete message using this interface: + +[code_websocket_4_3] + +[endsect] diff --git a/doc/qbk/06_websocket/05_control_frames_zh_Hans.qbk b/doc/qbk/06_websocket/05_control_frames_zh_Hans.qbk new file mode 100644 index 0000000..e4d6970 --- /dev/null +++ b/doc/qbk/06_websocket/05_control_frames_zh_Hans.qbk @@ -0,0 +1,119 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section Control Frames] + +Control frames are small (less than 128 bytes) messages entirely contained +in an individual WebSocket frame. They may be sent at any time by either +peer on an established connection, and can appear in between continuation +frames for a message. There are three types of control frames: ping, pong, +and close. + +A sent ping indicates a request that the sender wants to receive a pong. A +pong is a response to a ping. Pongs may be sent unsolicited, at any time. +One use for an unsolicited pong is to inform the remote peer that the +session is still active after a long period of inactivity. A close frame +indicates that the remote peer wishes to close the WebSocket connection. +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. 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.boost__beast__websocket__error `error::closed`] +being delivered to the caller in a subsequent read operation, assuming +no other error takes place. + +A consequence of this automatic behavior is that caller-initiated read +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/pong operation in +progress, while the implementation also automatically handles control +frames. + +[heading Control Callback] + +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.boost__beast__websocket__stream.ping `ping`], +[link beast.ref.boost__beast__websocket__stream.pong `pong`]. +and +[link beast.ref.boost__beast__websocket__stream.close `close`]. +To be notified of control frames, callers may register a +['control callback] using +[link beast.ref.boost__beast__websocket__stream.control_callback `control_callback`]. +The object provided with this option should be callable with the following +signature: + +[code_websocket_5_1] + +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.boost__beast__websocket__stream.reason `reason`]. + +Unlike regular completion handlers used in calls to asynchronous initiation +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 + control callback is invoked in the same manner as that used to + invoke the final completion handler of the corresponding read + function. +] + +[heading Close Frames] + +The WebSocket protocol defines a procedure and control message for +initiating a close of the session. In this procedure, a host requests +the close by sending a +[@https://tools.ietf.org/html/rfc6455#section-5.5.1 ['close frame]]. +To request a close use a close function such as +[link beast.ref.boost__beast__websocket__stream.close.overload2 `close`] or +[link beast.ref.boost__beast__websocket__stream.async_close `async_close`]: + +[code_websocket_5_2] + +The close function will send a close frame, read and discard incoming +message data until receiving a close frame, and then shut down the +underlying connection before returning. + +When a close frame is received by during a read operation, the implementation +will automatically respond with a close frame and then shut down the +underlying connection before returning. In this case, the read operation +will complete with the code +[link beast.ref.boost__beast__websocket__error `error::closed`]. +This indicates to the caller that the connection has been closed cleanly. + +[important + To receive the + [link beast.ref.boost__beast__websocket__error `error::closed`] + error, a read operation is required. +] + +[heading Auto-fragment] + +To ensure timely delivery of control frames, large outgoing messages can +be broken up into smaller sized frames. The automatic fragment option +turns on this feature, and the write buffer size option determines the +maximum size of the fragments: + +[code_websocket_5_3] + +[endsect] diff --git a/doc/qbk/06_websocket/06_timeouts_zh_Hans.qbk b/doc/qbk/06_websocket/06_timeouts_zh_Hans.qbk new file mode 100644 index 0000000..e39a5df --- /dev/null +++ b/doc/qbk/06_websocket/06_timeouts_zh_Hans.qbk @@ -0,0 +1,110 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[/-----------------------------------------------------------------------------] + +[section:timeouts Timeouts] + +While +[link beast.ref.boost__beast__basic_stream `basic_stream`] and +[link beast.ref.boost__beast__basic_stream `tcp_stream`] support timeouts on +general logical operations, the websocket stream has a more sophisticated timeout +mechanism built-in which may be enabled and configured. The timeout features +of the TCP or basic stream should not be used when working with a websocket +stream. The interface to these timeout features is shown in this table. + +[table WebSocket Timeout Interface +[[Name][Description]] +[[ + [link beast.ref.boost__beast__websocket__stream_base__timeout `stream_base::timeout`] +][ + This represents configured timeout settings for a websocket stream. +]] +[[ + [link beast.ref.boost__beast__websocket__stream_base__timeout.suggested `stream_base::timeout::suggested`] +][ + This function returns the suggested timeout settings for a given role + (client or server). +]] +[[ + [link beast.ref.boost__beast__websocket__stream.set_option `stream::set_option`] +][ + This function sets timeout and other options on the stream. +]] +] + +There are three timeout settings which may be set independently on the stream: + +[table WebSocket Timeout Interface (2) +[[Name][Type][Description]] +[ + [[link beast.ref.boost__beast__websocket__stream_base__timeout.handshake_timeout `timeout::handshake_timeout`]] + [`duration`] + [ + This is the amount of time after which a handshake will time out. + The handshake timeout applies to client handshakes, server handshakes, + as well as the websocket closing handshake performed when either + end of the connection wish to shut down. + The value returned by + [link beast.ref.boost__beast__websocket__stream_base.none `stream_base::none()`] + may be assigned to disable this timeout. + ] +][ + [[link beast.ref.boost__beast__websocket__stream_base__timeout.idle_timeout `timeout::idle_timeout`]] + [`duration`] + [ + If no data or control frames are received from the peer for a time + equal to the idle timeout, then the connection will time out. + The value returned by + [link beast.ref.boost__beast__websocket__stream_base.none `stream_base::none()`] + may be assigned to disable this timeout. + ] +][ + [[link beast.ref.boost__beast__websocket__stream_base__timeout.keep_alive_pings `timeout::keep_alive_pings`]] + [`bool`] + [ + If the idle timeout is enabled, then the value of this setting + controls whether or not a ping frame will be sent to the peer if + no data is received for half of the idle timeout interval. + ] +] +] + +By default, timeouts on websocket streams are disabled. The easiest way +to turn them on is to set the suggested timeout settings on the stream. + +[code_websocket_6_1] + +For manual control over the settings, a timeout options object may be +constructed. Here we enable only the handshake timeout. + +[code_websocket_6_2] + +Timeout notifications are delivered to the caller by invoking the completion +handler for an outstanding asynchronous read operation with the error code +[link beast.ref.boost__beast__error `error::timeout`]. The implementation +will close the socket or stream before delivering this error. It is not +necessary to manually shut down the connection, as it will already be shut +down. A read operation must be outstanding for the error to be delivered. + +[code_websocket_6_3] + +[note + Websocket timeout features are available only when using asynchronous I/O. +] + +The timeouts on the websocket stream are incompatible with the timeouts +used in the `tcp_stream`. When constructing a websocket stream from a tcp +stream that has timeouts enabled, the timeout should be disabled first before +constructing the websocket stream, as shown. + +[code_websocket_6_4] + + +[endsect] diff --git a/doc/qbk/06_websocket/07_teardown_zh_Hans.qbk b/doc/qbk/06_websocket/07_teardown_zh_Hans.qbk new file mode 100644 index 0000000..53507a5 --- /dev/null +++ b/doc/qbk/06_websocket/07_teardown_zh_Hans.qbk @@ -0,0 +1,66 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section Teardown] + +The WebSocket protocol requirements described in rfc6455 section 7.1.1 +outline an operation described as +[@https://tools.ietf.org/html/rfc6455#section-7.1.1 ['Close the WebSocket Connection]]. +This operation cleanly discards bytes remaining at receiving endpoints +and also closes the underlying TCP/IP connection. Orderly shutdowns are +always preferred; for TLS or SSL streams, a protocol-level shutdown is +desired. This presents a small issue for the +[link beast.ref.boost__beast__websocket__stream `stream`] +implementation: the stream's `NextLayer` template type requires only +__SyncStream__ or __AsyncStream__, but those concepts do not support +the operations to shut down the connection. + +To enable the implementation to perform the shutdown components of the +close operation, the library exposes two customization points expressed +as free functions associated with the next layer type: + +* [link beast.ref.boost__beast__websocket__teardown `teardown`]: Overloads + of this function drain and shut down a stream synchronously. + +* [link beast.ref.boost__beast__websocket__async_teardown `async_teardown`]: + Overloads of this function drain and shut down a stream asynchronously. + +The implementation provides suitable overloads of the teardown +customization points when websocket streams are instantiated using the +Asio types __socket__ or __ssl_stream__ for the next layer. In this +case no user action is required. However, when the websocket stream is +instantiated for a user-defined type, compile errors will result if the +customization points are not provided for the user defined type. +Furthermore, user-defined types that wrap one of the Asio objects +mentioned earlier may wish to invoke a teardown customization point +for the wrapped object. This is how those tasks are accomplished. + +[heading User-defined Teardown] + +To provide overloads of teardown for a user-defined type, simply declare +the two free functions with the correct signature, accepting a reference +to the user-defined type as the stream parameter: + +[code_websocket_7_1] + +When the implementation invokes the asynchronous teardown function, it +always uses an invokable completion handler. It is not necessary +to specify the return type customization when creating user-defined +overloads of `async_teardown`. + +[heading Invoking Teardown] + +To invoke the customization point, first bring the default implementation +into scope with a `using` statement. Then call the customization point +without namespace qualification, allowing argument-dependent lookup to +take effect: + +[code_websocket_7_2] + +[endsect] diff --git a/doc/qbk/06_websocket/08_notes_zh_Hans.qbk b/doc/qbk/06_websocket/08_notes_zh_Hans.qbk new file mode 100644 index 0000000..10226b5 --- /dev/null +++ b/doc/qbk/06_websocket/08_notes_zh_Hans.qbk @@ -0,0 +1,75 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section Notes] + +Because calls to read data may return a variable amount of bytes, the +interface to calls that read data require an object that meets the requirements +of __DynamicBuffer__. This concept is modeled on __streambuf__. + +The implementation does not perform queueing or buffering of messages. If +desired, these features should be provided by callers. The impact of this +design is that library users are in full control of the allocation strategy +used to store data and the back-pressure applied on the read and write side +of the underlying TCP/IP connection. + +[heading Asynchronous Operations] + +Asynchronous versions are available for all functions: + +[code_websocket_8_1] + +Calls to asynchronous initiation functions support the extensible asynchronous +model developed by the Boost.Asio author, allowing for traditional completion +handlers, stackful or stackless coroutines, and even futures: + +[code_websocket_8_1f] + +The example programs that come with the library demonstrate the usage of +websocket stream operations with all asynchronous varieties. + +[heading The io_context] + +The creation and operation of the __io_context__ associated with the +underlying stream is left to the callers, permitting any implementation +strategy including one that does not require threads for environments +where threads are unavailable. Beast WebSocket itself does not use +or require threads. + +[heading Thread Safety] + +Like a regular __Asio__ socket, a +[link beast.ref.boost__beast__websocket__stream `stream`] +is not thread safe. Callers are responsible for synchronizing operations on +the socket using an implicit or explicit strand, as per the Asio documentation. +The websocket stream asynchronous interface supports one of each of the +following operations to be active at the same time: + +* [link beast.ref.boost__beast__websocket__stream.async_read `async_read`] or [link beast.ref.boost__beast__websocket__stream.async_read_some `async_read_some`] +* [link beast.ref.boost__beast__websocket__stream.async_write `async_write`] or [link beast.ref.boost__beast__websocket__stream.async_write_some `async_write_some`] +* [link beast.ref.boost__beast__websocket__stream.async_ping `async_ping`] or [link beast.ref.boost__beast__websocket__stream.async_pong `async_pong`] +* [link beast.ref.boost__beast__websocket__stream.async_close `async_close`] + +For example, the following code is produces undefined behavior, because the +program is attempting to perform two simultaneous reads: + +[code_websocket_8_2] + +However, this code is correct: + +[code_websocket_8_3] + +The implementation uses composed asynchronous operations; although +some individual operations can perform both reads and writes, this +behavior is coordinated internally to make sure the underlying stream +is operated in a safe fashion. This allows an asynchronous read operation +to respond to a received ping frame even while a user-initiated call to +asynchronous write is active. + +[endsect] diff --git a/doc/qbk/06_websocket/_websocket_zh_Hans.qbk b/doc/qbk/06_websocket/_websocket_zh_Hans.qbk new file mode 100644 index 0000000..65157ef --- /dev/null +++ b/doc/qbk/06_websocket/_websocket_zh_Hans.qbk @@ -0,0 +1,157 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section:using_websocket WebSocket] + +[/-----------------------------------------------------------------------------] + +The WebSocket Protocol enables two-way communication between a client running +untrusted code in a controlled environment to a remote host that has opted-in +to communications from that code. The protocol consists of an opening handshake +followed by basic message framing, layered over TCP. The goal of this +technology is to provide a mechanism for browser-based applications needing +two-way communication with servers without relying on opening multiple HTTP +connections. + +Beast provides developers with a robust WebSocket implementation +built on Boost.Asio with a consistent asynchronous model using a modern C++ +approach. + +[note + This documentation assumes familiarity with __Asio__ and + the protocol specification described in __rfc6455__. + Sample code and identifiers appearing in this section is written + as if these declarations are in effect: + + [code_websocket_1a] + '''''' + [code_websocket_1b] +] + +[/-----------------------------------------------------------------------------] + +[heading Construction] + +A WebSocket connection requires a stateful object, represented in Beast by a +single class template +[link beast.ref.boost__beast__websocket__stream `websocket::stream`]. +The interface uses the layered stream model. A websocket stream object contains +another stream object, called the "next layer", which it uses to perform I/O. +Descriptions of each template parameter follow: + +[code_websocket_1h] + +[table WebSocket Stream Template Parameters +[[Name][Description]] +[ + [`NextLayer`] + [ + The type of the next layer. An object of this type will be constructed + and maintained for the lifetime of the stream. All reads and writes + will go through the next layer. This type must meet the requirements + of either __SyncStream__, __AsyncStream__, or both, depending on the + style of I/O that is to be performed. + ] +][ + [`deflateSupported`] + [ + When this value is `true`, the stream will support (but not require) + the [@https://tools.ietf.org/html/rfc7692 permessage-deflate extension]. + Whether or not the stream actually requests or accepts the extension + during a handshake depends on a separate configurable option. + + When the value is `false` the extension is disabled. Streams will + never request the extension in the client role or accept a request + for the extension in the server role. An additional benefit of + disabling the extension is that compilation will be faster, and + the resulting program executable will contain less code. + ] +]] + +When a stream is constructed, any arguments provided to the constructor are +forwarded to the next layer object's constructor. This declares a stream +over a plain TCP/IP socket using an I/O context: + +[code_websocket_1f] + +[tip + Websocket streams use their own protocol-specific timeout feature. When + using a websocket stream with the + [link beast.ref.boost__beast__tcp_stream `tcp_stream`] or + [link beast.ref.boost__beast__basic_stream `basic_stream`] + class template, timeouts should be disabled on the TCP or basic stream + after the connection is established, otherwise the behavior of the + stream is undefined. +] + +As with most I/O objects, a websocket stream is [*not thread-safe]. Undefined +behavior results if two different threads access the object concurrently. +For multi-threaded programs, the `tcp_stream` can be constructed from an +executor, in this case a strand. The stream declared below will use a +strand to invoke all completion handlers: + +[code_websocket_2f] + +If the next layer supports move-construction, then the websocket stream can be +constructed from a moved-from object. + +[code_websocket_3f] + +The next layer may be accessed by calling +[link beast.ref.boost__beast__websocket__stream.next_layer.overload1 `stream::next_layer`]. + +[code_websocket_4f] + +[/-----------------------------------------------------------------------------] + +[heading Using SSL] + +To use WebSockets over SSL, use an instance of the __ssl_stream__ +class template as the template type for the stream. The required +__io_context__ and __ssl_context__ arguments are forwarded to the +wrapped stream's constructor: + +[code_websocket_5f] + +[important + Code which declares websocket stream objects using Asio SSL types + must include the file [include_file boost/beast/websocket/ssl.hpp]. +] + +As before, the underlying SSL stream may be accessed by calling `next_layer`. + +[code_websocket_6f] + +With multi-layered streams such as the one declared above, accessing an +individual layer can be cumbersome when using chained calls to `next_layer`. +The function +[link beast.ref.boost__beast__get_lowest_layer `get_lowest_layer`] +returns the last stream in a stack of layers in a layered stream. Here we +access the lowest layer to cancel all outstanding I/O. + +[code_websocket_7f] + +[/-----------------------------------------------------------------------------] + +[heading Non-Blocking Mode] + +Please note that websocket streams do not support non-blocking modes. + +[/-----------------------------------------------------------------------------] + +[include 01_connecting.qbk] +[include 02_handshaking.qbk] +[include 03_decorator.qbk] +[include 04_messages.qbk] +[include 05_control_frames.qbk] +[include 06_timeouts.qbk] +[include 07_teardown.qbk] +[include 08_notes.qbk] + +[endsect] diff --git a/doc/qbk/07_concepts/BodyReader_zh_Hans.qbk b/doc/qbk/07_concepts/BodyReader_zh_Hans.qbk new file mode 100644 index 0000000..974156c --- /dev/null +++ b/doc/qbk/07_concepts/BodyReader_zh_Hans.qbk @@ -0,0 +1,119 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section:BodyReader BodyReader] + +A [*BodyReader] provides an online algorithm to transfer a series of zero +or more buffers containing parsed body octets into a message container. The +__parser__ creates an instance of this type when needed, and calls into +it zero or more times to transfer buffers. The interface of [*BodyReader] +is intended to allow the conversion of buffers into these scenarios for +representation: + +* Storing a body in a dynamic buffer +* Storing a body in a user defined container with a custom allocator +* Transformation of incoming body data before storage, for example + to compress it first. +* Saving body data to a file + +[heading Associated Types] + +* [link beast.ref.boost__beast__http__is_body_reader `is_body_reader`] +* __Body__ + +[heading Requirements] + +[warning + These requirements may undergo non-backward compatible + changes in subsequent versions. +] + +In this table: + +* `R` denotes a type meeting the requirements of [*BodyReader]. +* `B` denotes a __Body__ where + `std::is_same::value == true`. +* `a` denotes a value of type `R`. +* `b` is an object whose type meets the requirements of __ConstBufferSequence__ +* `h` denotes a value of type `header&`. +* `v` denotes a value of type `Body::value_type&`. +* `n` is a value of type `boost::optional`. +* `ec` is a value of type [link beast.ref.boost__beast__error_code `error_code&`]. + +[table Valid expressions +[[Expression] [Type] [Semantics, Pre/Post-conditions]] +[ + [`R{h,v};`] + [] + [ + Constructible from `h` and `v`. The lifetime of `h` and `v` + is guaranteed to end no earlier than after the `R` is destroyed. + The reader shall not access the contents of `h` or `v` before + the first call to `init`, permitting lazy construction of the + message. + ] +][ + [`a.init(n, ec)`] + [] + [ + Called once to fully initialize the object before any calls to + `put`. The message body is valid before entering this function, + and remains valid until the reader is destroyed. + The value of `n` will be set to the content length of the + body if known, otherwise `n` will be equal to `boost::none`. + Implementations of [*BodyReader] may use this information to + optimize allocation. + + The function will ensure that `!ec` is `true` if there was + no error or set to the appropriate error code if there was one. + ] +][ + [`a.put(b,ec)`] + [`std::size_t`] + [ + This function is called to append some or all of the buffers + specified by `b` into the body representation. The number of + bytes inserted from `b` is returned. If the number of bytes + inserted is less than the total input, the remainder of the + input will be presented in the next call to `put`. + The function will ensure that `!ec` is `true` if there was + no error or set to the appropriate error code if there was one. + ] +][ + [`a.finish(ec)`] + [] + [ + This function is called when no more body octets are remaining. + The function will ensure that `!ec` is `true` if there was + no error or set to the appropriate error code if there was one. + ] +][ + [`is_body_reader`] + [`std::true_type`] + [ + An alias for `std::true_type` for `B`, otherwise an alias + for `std::false_type`. + ] +]] + +[heading Exemplar] + +[concept_BodyReader] + +[heading Models] + +* [link beast.ref.boost__beast__http__basic_dynamic_body.reader `basic_dynamic_body::reader`] +* [link beast.ref.boost__beast__http__basic_file_body__reader `basic_file_body::reader`] +* [link beast.ref.boost__beast__http__basic_string_body.reader `basic_string_body::reader`] +* [link beast.ref.boost__beast__http__buffer_body.reader `buffer_body::reader`] +* [link beast.ref.boost__beast__http__empty_body.reader `empty_body::reader`] +* [link beast.ref.boost__beast__http__span_body.reader `span_body::reader`] +* [link beast.ref.boost__beast__http__vector_body.reader `vector_body::reader`] + +[endsect] diff --git a/doc/qbk/07_concepts/BodyWriter_zh_Hans.qbk b/doc/qbk/07_concepts/BodyWriter_zh_Hans.qbk new file mode 100644 index 0000000..8962aa0 --- /dev/null +++ b/doc/qbk/07_concepts/BodyWriter_zh_Hans.qbk @@ -0,0 +1,124 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section:BodyWriter BodyWriter] + +A [*BodyWriter] provides an +[@https://en.wikipedia.org/wiki/Online_algorithm online algorithm] +to obtain a sequence of zero +or more buffers from a body during serialization. The implementation creates +an instance of this type when needed, and calls into it one or more times to +retrieve buffers holding body octets. The interface of [*BodyWriter] is +intended to obtain buffers for these scenarios: + +* A body that does not entirely fit in memory. +* A body produced incrementally from coroutine output. +* A body represented by zero or more buffers already in memory. +* A body whose size is not known ahead of time. +* Body data generated dynamically from other threads. +* Body data computed algorithmically. + +[heading Associated Types] + +* [link beast.ref.boost__beast__http__is_body_writer `is_body_writer`] +* __Body__ + +[heading Requirements] + +[warning + These requirements may undergo non-backward compatible + changes in subsequent versions. +] + +In this table: + +* `W` denotes a type meeting the requirements of [*BodyWriter]. +* `B` denotes a __Body__ where + `std::is_same::value == true`. +* `a` denotes a value of type `W`. +* `h` denotes a const value of type `header const&`. +* `v` denotes a possibly const value of type `Body::value_type&`. +* `ec` is a value of type [link beast.ref.boost__beast__error_code `error_code&`]. +* `W` is the type `boost::optional>`. + +[table Valid expressions +[[Expression] [Type] [Semantics, Pre/Post-conditions]] +[ + [`W::const_buffers_type`] + [] + [ + A type which meets the requirements of __ConstBufferSequence__. + This is the type of buffer returned by `W::get`. + ] +][ + [`W{h,v};`] + [] + [ + Constructible from `h` and `v`. The lifetime of `h` and `v` + are guaranteed to end no earlier than after the `W` is destroyed. + The writer shall not access the contents of `h` or `v` before + the first call to `init`, permitting lazy construction of the + message. + + The constructor may optionally require that `h` and `v` are + `const` references, with these consequences: + + * If `W` requires that `h` and `v` are const references, then + the corresponding serializer constructors for messages with this + body type will will accept a const reference to a message, + otherwise: + + * If `W` requires that `h` and `v` are non-const references, + then the corresponding serializer constructors for messages with + this body type will require a non-const reference to a message. + ] +][ + [`a.init(ec)`] + [] + [ + Called once to fully initialize the object before any calls to + `get`. The message body becomes valid before entering this function, + and remains valid until the writer is destroyed. + The function will ensure that `!ec` is `true` if there was + no error or set to the appropriate error code if there was one. + ] +][ + [`a.get(ec)`] + [`W`] + [ + Called one or more times after `init` succeeds. This function + returns `boost::none` if all buffers representing the body have + been returned in previous calls or if it sets `ec` to indicate an + error. Otherwise, if there are buffers remaining the function + should return a pair with the first element containing a non-zero + length buffer sequence representing the next set of octets in + the body, while the second element is a `bool` meaning `true` + if there may be additional buffers returned on a subsequent call, + or `false` if the buffer returned on this call is the last + buffer representing the body. + The function will ensure that `!ec` is `true` if there was + no error or set to the appropriate error code if there was one. + ] +]] + +[heading Exemplar] + +[concept_BodyWriter] + +[heading Models] + +* [link beast.ref.boost__beast__http__basic_dynamic_body.writer `basic_dynamic_body::writer`] +* [link beast.ref.boost__beast__http__basic_file_body__writer `basic_file_body::writer`] +* [link beast.ref.boost__beast__http__basic_string_body.writer `basic_string_body::writer`] +* [link beast.ref.boost__beast__http__buffer_body.writer `buffer_body::writer`] +* [link beast.ref.boost__beast__http__empty_body.writer `empty_body::writer`] +* [link beast.ref.boost__beast__http__span_body.writer `span_body::writer`] +* [link beast.ref.boost__beast__http__vector_body.writer `vector_body::writer`] + +[endsect] diff --git a/doc/qbk/07_concepts/Body_zh_Hans.qbk b/doc/qbk/07_concepts/Body_zh_Hans.qbk new file mode 100644 index 0000000..56c8397 --- /dev/null +++ b/doc/qbk/07_concepts/Body_zh_Hans.qbk @@ -0,0 +1,113 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section:Body Body] + +A [*Body] type is supplied as a template argument to the __message__ class. It +controls both the type of the data member of the resulting message object, and +the algorithms used during parsing and serialization. + +[heading Associated Types] + +* [link beast.ref.boost__beast__http__is_body `is_body`] +* __BodyReader__ +* __BodyWriter__ + +[heading Requirements] + +In this table: + +* `B` is a type meeting the requirements of [*Body]. +* `m` is a value of type `message` where `b` is a `bool` value + and `F` is a type meeting the requirements of __Fields__. + +[table Valid expressions +[[Expression] [Type] [Semantics, Pre/Post-conditions]] +[ + [`B::value_type`] + [] + [ + The return type of the `message::body` member function. + If this is not movable or not copyable, the containing message + will be not movable or not copyable. + ] +][ + [`B::reader`] + [] + [ + If present, indicates that the body can be parsed. The type + must meet the requirements of __BodyReader__. The implementation + constructs an object of this type to obtain buffers into which + parsed body octets are placed. + ] +][ + [`B::writer`] + [] + [ + If present, indicates that the body is serializable. The type + must meet the requirements of __BodyWriter__. The implementation + constructs an object of this type to obtain buffers representing + the message body for serialization. + ] +][ + [ + ``` + B::size( + B::value_type body) + ``` + ] + [`std::uint64_t`] + [ + This static member function is optional. It returns the payload + size of `body` in bytes not including any chunked transfer encoding. + The return value may be zero, to indicate that the message is known + to have no payload. The function shall not exit via an exception. + + When this function is present: + + * The function shall not fail + + * A call to + [link beast.ref.boost__beast__http__message.payload_size `message::payload_size`] + will return the same value as `size`. + + * A call to + [link beast.ref.boost__beast__http__message.prepare_payload `message::prepare_payload`] + will remove "chunked" from the Transfer-Encoding field if it appears + as the last encoding, and will set the Content-Length field to the + returned value. + + Otherwise, when the function is omitted: + + * A call to + [link beast.ref.boost__beast__http__message.payload_size `message::payload_size`] + will return `boost::none`. + + * A call to + [link beast.ref.boost__beast__http__message.prepare_payload `message::prepare_payload`] + will erase the Content-Length field, and add "chunked" as the last + encoding in the Transfer-Encoding field if it is not already present. + ] +]] + +[heading Exemplar] + +[concept_Body] + +[heading Models] + +* [link beast.ref.boost__beast__http__basic_dynamic_body `basic_dynamic_body`] +* [link beast.ref.boost__beast__http__basic_file_body `basic_file_body`] +* [link beast.ref.boost__beast__http__basic_string_body `basic_string_body`] +* [link beast.ref.boost__beast__http__buffer_body `buffer_body`] +* [link beast.ref.boost__beast__http__empty_body `empty_body`] +* [link beast.ref.boost__beast__http__span_body `span_body`] +* [link beast.ref.boost__beast__http__vector_body `vector_body`] + +[endsect] diff --git a/doc/qbk/07_concepts/BufferSequence_zh_Hans.qbk b/doc/qbk/07_concepts/BufferSequence_zh_Hans.qbk new file mode 100644 index 0000000..86612dd --- /dev/null +++ b/doc/qbk/07_concepts/BufferSequence_zh_Hans.qbk @@ -0,0 +1,17 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section:BufferSequence BufferSequence] + +A [*BufferSequence] is a type meeting either of the following requirements: + +* __ConstBufferSequence__ +* __MutableBufferSequence__ + +[endsect] diff --git a/doc/qbk/07_concepts/BuffersGenerator_zh_Hans.qbk b/doc/qbk/07_concepts/BuffersGenerator_zh_Hans.qbk new file mode 100644 index 0000000..1f2dcd2 --- /dev/null +++ b/doc/qbk/07_concepts/BuffersGenerator_zh_Hans.qbk @@ -0,0 +1,146 @@ +[/ + Copyright (c) 2016-2022 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section:BuffersGenerator BuffersGenerator] + +A [*BuffersGenerator] provides a generalized interface for generating +serialized data for sequential processing. + +The generator will be asked to produce buffers. The consuming code will signal +how much of the data has been consumed, and repeatedly query for buffers until +no more data is available, or the generator indicates an error condition. + +In this way, serializers can be adapted as [*BuffersGenerator], for example +[link beast.ref.boost__beast__http__message_generator +`http::message_generator`] which provides a type-erased interface for a variety +of concrete http message types. + +Overloads of [link beast.ref.boost__beast__write `write`] and [link +beast.ref.boost__beast__async_write `async_write`] operations are provided as +free functions. These operations will consume the output of a +[*BuffersGenerator] and process the data by writing them to a +__SyncWriteStream__ or __AsyncWriteStream__ respectively. + +[heading Associated Types] + +* [link beast.ref.boost__beast__is_buffers_generator `is_buffers_generator`] +* __ConstBufferSequence__ + +[heading Requirements] + +In this table: + +* `G` denotes a type meeting the requirements of [*BuffersGenerator]. +* `g` denotes a value of type `G`. +* `c` denotes a possibly-const value of type `G`. +* `n` is a value of type `std::size_t`. +* `ec` is a value of type [link beast.ref.boost__beast__error_code `error_code&`]. + +[table Valid expressions +[[Expression] [Type] [Semantics, Pre/Post-conditions]] +[ + [`G::const_buffers_type`] + [] + [ + A type which meets the requirements of __ConstBufferSequence__. + This is the type of buffer returned by `g.prepare(ec)`. + ] +][ + [`c.is_done()`] + [`bool`] + [ + Called to ask the generator for its completion status. + + A generator has completed when no new buffer will be produced and + previously produced buffers have been fully consumed. + + [*Note:] The result of invoking `prepare` on `g` once it has completed + is unspecified. + ] +][ + [`g.prepare(ec)`] + [`G::const_buffers_type`] + [ + Called to ask the generator to produce buffers containing data for + processing. + + The returned value is the __ConstBufferSequence__ representing + unconsumed data. + + The function will ensure that `ec.failed()` is `false` if there was no + error or set to the appropriate error code if there was one. + + If no unconsumed data is available, this operation shall make progress + to eventually reach completion. + + The result of invoking `prepare` after completion or encountered + error(s) is defined by the generator implementation. It can not be + assumed to be meaningful or safe to do so, in general. + + The capacity of the buffer returned is defined by the generator + implementation. + + [*Note:] Any buffers obtained by previous calls to `prepare` are + invalidated. + ] +][ + [`g.consume(n)`] + [] + [ + This function is called to signal that the consumer (caller) of the + generator has processed part of the data returned by the previous call + to `prepare`. + + The value of `n` indicates how much of the data processed (in bytes). + + When `n` exceeds the number of bytes returned from the last call to + `prepare`, `consume` shall behave as if `n` was equal to that number. + + Remaining unconsumed data will be returned from subsequent calls to + `prepare`. + + [*Note:] Any buffers obtained by previous calls to `prepare` are + invalidated. + ] +][ + [`is_buffers_generator`] + [`std::bool_constant`] + [ + An alias for `std::true_type` for `G`, otherwise an alias + for `std::false_type`. + ] +]] + +[heading Exemplar] + +``` + // A buffer sequence generator + struct BuffersGenerator + { + using const_buffers_type = net::const_buffer; + + bool is_done() const; + const_buffers_type prepare( error_code& ec ); + void consume( std::size_t n ); + }; + + static_assert( + is_buffers_generator::value, ""); +``` + +[heading Models] + +* [link beast.ref.boost__beast__http__message_generator `http::message_generator`] + +[heading Algorithms] + +* [link beast.ref.boost__beast__async_write `async_write`] +* [link beast.ref.boost__beast__write `write`] + +[endsect] diff --git a/doc/qbk/07_concepts/DynamicBuffer_zh_Hans.qbk b/doc/qbk/07_concepts/DynamicBuffer_zh_Hans.qbk new file mode 100644 index 0000000..3ea5b7a --- /dev/null +++ b/doc/qbk/07_concepts/DynamicBuffer_zh_Hans.qbk @@ -0,0 +1,136 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section:DynamicBuffer DynamicBuffer] + +A dynamic buffer encapsulates memory storage that may be automatically resized +as required, where the memory is divided into an input sequence followed by an +output sequence. These memory regions are internal to the dynamic buffer, but +direct access to the elements is provided to permit them to be efficiently used +with I/O operations, such as the send or receive operations of a socket. Data +written to the output sequence of a dynamic buffer object is appended to the +input sequence of the same object. + +The interface to this concept is intended to permit the following +implementation strategies: + +* A single contiguous octet array, which is reallocated as necessary to + accommodate changes in the size of the octet sequence. This is the + implementation approach currently offered by __flat_buffer__. + +* A sequence of one or more octet arrays, where each array is of the same + size. Additional octet array objects are appended to the sequence to + accommodate changes in the size of the octet sequence. + +* A sequence of one or more octet arrays of varying sizes. Additional octet + array objects are appended to the sequence to accommodate changes in the + size of the character sequence. This is the implementation approach + currently offered by __multi_buffer__. + +[heading Associated With] + +* `boost::asio::is_dynamic_buffer` +* __ConstBufferSequence__ +* __MutableBufferSequence__ + +[heading Requirements] + +* `D` denotes a dynamic buffer class. +* `a` denotes a value of type `D`. +* `c` denotes a (possibly const) value of type `D`. +* `n` denotes a value of type `std::size_t`. +* `T` denotes a type meeting the requirements for __ConstBufferSequence__. +* `U` denotes a type meeting the requirements for __MutableBufferSequence__. + +[table Valid expressions +[[Expression] [Type] [Semantics, Pre/Post-conditions]] +[ + [`D::const_buffers_type`] + [`T`] + [ + This type represents the memory associated with the input sequence. + ] +][ + [`D::mutable_buffers_type`] + [`U`] + [ + This type represents the memory associated with the output sequence. + ] +][ + [`c.size()`] + [`std::size_t`] + [ + Returns the size, in bytes, of the input sequence. + ] +][ + [`c.max_size()`] + [`std::size_t`] + [ + Returns the permitted maximum of the sum of the sizes of the input + sequence and output sequence. + ] +][ + [`c.capacity()`] + [`std::size_t`] + [ + Returns the maximum sum of the sizes of the input sequence and output + sequence that the dynamic buffer can hold without requiring reallocation. + ] +][ + [`c.data()`] + [`D::const_buffers_type`] + [ + Returns a constant buffer sequence u that represents the memory + associated with the input sequence, and where `buffer_size(u) == size()`. + ] +][ + [`a.prepare(n)`] + [`D::mutable_buffers_type`] + [ + Returns a mutable buffer sequence u representing the output sequence, + and where `buffer_size(u) == n`. The dynamic buffer reallocates memory + as required. All constant or mutable buffer sequences previously + obtained using `data()` or `prepare()` are invalidated. + + Throws: `length_error` if `size() + n` exceeds `max_size()`. + ] +][ + [`a.commit(n)`] + [ ] + [ + Appends `n` bytes from the start of the output sequence to the end of + the input sequence. The remainder of the output sequence is discarded. + If `n` is greater than the size of the output sequence, the entire + output sequence is appended to the input sequence. All constant or + mutable buffer sequences previously obtained using `data()` or + `prepare()` are invalidated. + ] +][ + [`a.consume(n)`] + [ ] + [ + Removes `n` bytes from beginning of the input sequence. If `n` is + greater than the size of the input sequence, the entire input sequence + is removed. All constant or mutable buffer sequences previously + obtained using `data()` or `prepare()` are invalidated. + ] +]] + +[heading Models] + +* [link beast.ref.boost__beast__basic_flat_buffer `basic_flat_buffer`] +* [link beast.ref.boost__beast__basic_multi_buffer `basic_multi_buffer`] +* [link beast.ref.boost__beast__flat_buffer `flat_buffer`] +* [link beast.ref.boost__beast__flat_static_buffer `flat_static_buffer`] +* [link beast.ref.boost__beast__flat_static_buffer_base `flat_static_buffer_base`] +* [link beast.ref.boost__beast__static_buffer `static_buffer`] +* [link beast.ref.boost__beast__static_buffer_base `static_buffer_base`] +* [link beast.ref.boost__beast__multi_buffer `multi_buffer`] + +[endsect] diff --git a/doc/qbk/07_concepts/FieldsWriter_zh_Hans.qbk b/doc/qbk/07_concepts/FieldsWriter_zh_Hans.qbk new file mode 100644 index 0000000..f8d0af6 --- /dev/null +++ b/doc/qbk/07_concepts/FieldsWriter_zh_Hans.qbk @@ -0,0 +1,100 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section:FieldsWriter FieldsWriter] + +A [*FieldsWriter] provides a algorithm to obtain a sequence of buffers +representing the complete serialized HTTP/1 header for a set of fields. +The implementation constructs an instance of this type when needed, and +calls into it once to retrieve the buffers. + +[heading Associated Types] + +* __FieldsWriter__ + +[heading Requirements] + +[warning + These requirements may undergo non-backward compatible + changes in subsequent versions. +] + +In this table: + +* `W` denotes a type that meets the requirements of [*FieldsWriter]. +* `F` denotes a __Fields__ where + `std::is_same::value == true`. +* `a` is a value of type `W`. +* `f` is a value of type `F`. +* `v` is an `unsigned` value representing the HTTP version. +* `c` is an `unsigned` representing the HTTP status-code. +* `m` is a value of type [link beast.ref.boost__beast__http__verb `verb`]. + +[table Valid expressions +[[expression][type][semantics, pre/post-conditions]] +[ + [`W::const_buffers_type`] + [] + [ + A type which meets the requirements of __ConstBufferSequence__. + This is the type of buffer returned by `W::get`. + ] +][ + [`W{f,v,m}`] + [] + [ + The implementation calls this constructor to indicate + that the fields being serialized form part of an HTTP + request. The lifetime of `f` is guaranteed + to end no earlier than after the `W` is destroyed. + ] +][ + [`W{f,v,c}`] + [] + [ + The implementation calls this constructor to indicate + that the fields being serialized form part of an HTTP + response. The lifetime of `f` is guaranteed + to end no earlier than after the `W` is destroyed. + ] +][ + [`W{f}`] + [] + [ + The implementation calls this constructor to indicate + that the fields being serialized form part of a chunked + encoding final-chunk trailer. The lifetime of `f` is + guaranteed to end no earlier than after the `W` is + destroyed. + ] +][ + [`a.get()`] + [`W::const_buffers_type`] + [ + Called once after construction, this function returns + a constant buffer sequence containing the serialized + representation of the HTTP request or response including + the final carriage return linefeed sequence (`"\r\n"`). + + Copies may be made of the returned sequence, but the + underlying memory is still owned by the writer. The + implementation will destroy all copies of the buffer + sequence before destroying `a`. + ] +]] + +[heading Exemplar] + +[concept_FieldsWriter] + +[heading Models] + +* [link beast.ref.boost__beast__http__basic_fields.writer `basic_fields::writer`] + +[endsect] diff --git a/doc/qbk/07_concepts/Fields_zh_Hans.qbk b/doc/qbk/07_concepts/Fields_zh_Hans.qbk new file mode 100644 index 0000000..381463f --- /dev/null +++ b/doc/qbk/07_concepts/Fields_zh_Hans.qbk @@ -0,0 +1,233 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section:Fields Fields] + +An instance of [*Fields] is a container for holding HTTP header fields +and their values. The implementation also calls upon the container to +store the request target and non-standard strings for method and obsolete +reason phrase as needed. Types which meet these requirements can always +be serialized. + +[heading Associated Types] + +* [link beast.ref.boost__beast__http__is_fields `is_fields`] +* __FieldsWriter__ + +[heading Requirements] + +In this table: + +* `F` denotes a type that meets the requirements of [*Fields]. +* `W` denotes a type meeting the requirements of __FieldsWriter__. +* `a` denotes a value of type `F`. +* `c` denotes a (possibly const) value of type `F`. +* `b` is a value of type `bool` +* `n` is a value of type `boost::optional`. +* `s` is a value of type [link beast.ref.boost__beast__string_view `string_view`]. +* `v` is a value of type `unsigned int` representing the HTTP-version. + +[table Valid expressions +[[Expression] [Type] [Semantics, Pre/Post-conditions]] +[ + [`F::writer`] + [`W`] + [ + A type which meets the requirements of __FieldsWriter__. + ] +][ + [`c.get_method_impl()`] + [`string_view`] + [ + Returns the method text. + The implementation only calls this function for request + headers when retrieving the method text previously set + with a call to `set_method_impl` using a non-empty string. + ] +][ + [`c.get_target_impl()`] + [`string_view`] + [ + Returns the target string. + The implementation only calls this function for request headers. + ] +][ + [`c.get_reason_impl()`] + [`string_view`] + [ + Returns the obsolete request text. + The implementation only calls this for response headers when + retrieving the reason text previously set with a call to + `set_reason_impl` using a non-empty string. + ] +][ + [`c.get_chunked_impl()`] + [`bool`] + [ + Returns `true` if the + [@https://tools.ietf.org/html/rfc7230#section-3.3.1 [*Transfer-Encoding]] + field value indicates that the payload is chunk encoded. Both + of these conditions must be true: + [itemized_list + [ + The Transfer-Encoding field is present in the message. + ][ + The last item in value of the field is "chunked". + ]] + ] +][ + [`c.get_keep_alive_impl(v)`] + [`bool`] + [ + Returns `true` if the semantics of the + [@https://tools.ietf.org/html/rfc7230#section-6.1 [*Connection]] + field and version indicate that the connection should remain + open after the corresponding response is transmitted or received: + + [itemized_list + [ + If `(v < 11)` the function returns `true` if the "keep-alive" + token is present in the Connection field value. Otherwise the + function returns `false`. + ][ + If `(v == 11)`, the function returns `false` if the "close" + token is present in the Connection field value. Otherwise the + function returns `true`. + ]] + ] +][ + [`c.has_content_length()`] + [`bool`] + [ + Returns `true` if the + [@https://tools.ietf.org/html/rfc7230#section-3.3.2 [*Content-Length]] + field is present. + ] +][ + [`a.set_method_impl(s)`] + [] + [ + Stores a copy of `s` as the method text, or erases the previously + stored value if `s` is empty. + The implementation only calls this function for request headers. + This function may throw `std::invalid_argument` if the operation + is not supported by the container. + ] +][ + [`a.set_target_impl(s)`] + [] + [ + Stores a copy of `s` as the target, or erases the previously + stored value if `s` is empty. + The implementation only calls this function for request headers. + This function may throw `std::invalid_argument` if the operation + is not supported by the container. + ] +][ + [`a.set_reason_impl(s)`] + [] + [ + Stores a copy of `s` as the reason text, or erases the previously + stored value of the reason text if `s` is empty. + The implementation only calls this function for request headers. + This function may throw `std::invalid_argument` if the operation + is not supported by the container. + ] +][ + [`a.set_chunked_impl(b)`] + [] + [ + Adjusts the + [@https://tools.ietf.org/html/rfc7230#section-3.3.1 [*Transfer-Encoding]] + field value as follows: + + [itemized_list + [ + If `b` is `true`, the "chunked" token is appended + to the list of encodings if it does not already appear + last in the list. + If the Transfer-Encoding field is absent, the field will + be inserted to the container with the value "chunked". + ][ + If `b` is `false, the "chunked" token is removed from the + list of encodings if it appears last in the list. + If the result of the removal leaves the list of encodings + empty, the Transfer-Encoding field shall not appear when + the associated __FieldsWriter__ serializes the fields. + ]] + + If the result of adjusting the field value produces an empty + string, the field is removed from the container. + ] + +][ + [`a.set_content_length_impl(n)`] + [] + [ + Adjusts the + [@https://tools.ietf.org/html/rfc7230#section-3.3.2 [*Content-Length]] + field value as follows: + + [itemized_list + [ + If `n` contains a value, the Content-Length field + will be set to the text representation of the value. + Any previous Content-Length fields are removed from + the container. + ][ + If `n` does not contain a value, any present Content-Length + fields are removed from the container. + ]] + ] + +][ + [`a.set_keep_alive_impl(v,b)`] + [] + [ + Adjusts the + [@https://tools.ietf.org/html/rfc7230#section-6.1 [*Connection]] + field value depending on the values of `v` and `b`. The field + value is treated as + [@https://tools.ietf.org/html/rfc7230#section-6.1 ['connection-option]] + (rfc7230). + + [itemized_list + [ + If `(v < 11 && b)`, then all "close" tokens present in the + value are removed, and the "keep-alive" token is added to + the value if it is not already present. + ][ + If `(v < 11 && ! b)`, then all "close" and "keep-alive" + tokens present in the value are removed. + + ][ + If `(v == 11 && b)`, then all "keep-alive" and "close" + tokens present in the value are removed. + ][ + If `(v == 11 && ! b)`, then all "keep-alive" tokens present + in the value are removed, and the "close" token is added to + the value if it is not already present. + ]] + + If the result of adjusting the field value produces an empty + string, the field is removed from the container. + ] + +]] + +[heading Exemplar] + +[concept_Fields] + +[heading Models] + +* [link beast.ref.boost__beast__http__basic_fields `basic_fields`] +* [link beast.ref.boost__beast__http__fields `fields`] + +[endsect] diff --git a/doc/qbk/07_concepts/File_zh_Hans.qbk b/doc/qbk/07_concepts/File_zh_Hans.qbk new file mode 100644 index 0000000..b00ea8c --- /dev/null +++ b/doc/qbk/07_concepts/File_zh_Hans.qbk @@ -0,0 +1,180 @@ +[/ + Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +] + +[section:File File] + +The [*File] concept abstracts access to files in the underlying file system. +To support other platform interfaces, users may author their own [*File] +types which meet these requirements. + +[heading Associated Types] + +* [link beast.ref.boost__beast__file_mode `file_mode`] +* [link beast.ref.boost__beast__is_file `is_file`] + +[heading Requirements] + +In this table: + +* `F` is a [*File] type +* `f` is an instance of `F` +* `p` is a value of type `char const*` which points to a null + terminated utf-8 encoded string. +* `m` is an instance of [link beast.ref.boost__beast__file_mode `file_mode`] +* `n` is a number of bytes, convertible to `std::size_t` +* `o` is a byte offset in the file, convertible to `std::uint64_t` +* `b` is any non-const pointer to memory +* `c` is any possibly-const pointer to memory +* `ec` is a reference of type [link beast.ref.boost__beast__error_code `error_code`] + +[table Valid expressions +[[Expression] [Type] [Semantics, Pre/Post-conditions]] +[[Operation] [Return Type] [Semantics, Pre/Post-conditions]] +[ + [`F()`] + [ ] + [ + Default constructable + ] +] +[ + [`f.~F()`] + [ ] + [ + Destructible. + If `f` refers to an open file, it is first closed + as if by a call to `close` with the error ignored. + ] +] +[ + [`f.is_open()`] + [`bool`] + [ + Returns `true` if `f` refers to an open file, `false` otherwise. + ] +] +[ + [`f.close(ec)`] + [] + [ + If `f` refers to an open file, this function attempts to + close the file. + Regardless of whether an error occurs or not, a subsequent + call to `f.is_open()` will return `false`. + The function will ensure that `!ec` is `true` if there was + no error or set to the appropriate error code if an error + occurred. + ] +] +[ + [`f.open(p,m,ec)`] + [] + [ + Attempts to open the file at the path specified by `p` + with the mode specified by `m`. + Upon success, a subsequent call to `f.is_open()` will + return `true`. + If `f` refers to an open file, it is first closed + as if by a call to `close` with the error ignored. + The function will ensure that `!ec` is `true` if there was + no error or set to the appropriate error code if an error + occurred. + + ] +] +[ + [`f.size(ec)`] + [`std::uint64_t`] + [ + If `f` refers to an open file, this function attempts to + determine the file size and return its value. + If `f` does not refer to an open file, the function will + set `ec` to `errc::invalid_argument` and return 0. + The function will ensure that `!ec` is `true` if there was + no error or set to the appropriate error code if an error + occurred. + ] +] +[ + [`f.pos(ec)`] + [`std::uint64_t`] + [ + If `f` refers to an open file, this function attempts to + determine the current file offset and return it. + If `f` does not refer to an open file, the function will + set `ec` to `errc::invalid_argument` and return 0. + The function will ensure that `!ec` is `true` if there was + no error or set to the appropriate error code if an error + occurred. + ] +] +[ + [`f.seek(o,ec)`] + [] + [ + Attempts to reposition the current file offset to the value + `o`, which represents a byte offset relative to the beginning + of the file. + If `f` does not refer to an open file, the function will + set `ec` to `errc::invalid_argument` and return immediately. + The function will ensure that `!ec` is `true` if there was + no error or set to the appropriate error code if an error + occurred. + ] +] +[ + [`f.read(b,n,ec)`] + [`std::size_t`] + [ + Attempts to read `n` bytes starting at the current file offset + from the open file referred to by `f`. + Bytes read are stored in the memory buffer at address `b` which + must be at least `n` bytes in size. + The function advances the file offset by the amount read, and + returns the number of bytes actually read, which may be less + than `n`. + If `f` does not refer to an open file, the function will + set `ec` to `errc::invalid_argument` and return immediately. + The function will ensure that `!ec` is `true` if there was + no error or set to the appropriate error code if an error + occurred. + If an end-of-file condition is detected prior to reading any + bytes, the function will ensure that `!ec` is `true` and the + return value shall be 0. + ] +] +[ + [`f.write(c,n,ec)`] + [`std::size_t`] + [ + Attempts to write `n` bytes from the buffer pointed to by `c` to + the current file offset of the open file referred to by `f`. + The memory buffer at `c` must point to storage of at least `n` + bytes meant to be copied to the file. + The function advances the file offset by the amount written, + and returns the number of bytes actually written, which may be + less than `n`. + If `f` does not refer to an open file, the function will + set `ec` to `errc::invalid_argument` and return immediately. + The function will ensure that `!ec` is `true` if there was + no error or set to the appropriate error code if an error + occurred. + ] +] +] + +[heading Exemplar] + +[concept_File] + +[heading Models] + +* [link beast.ref.boost__beast__file_posix `file_posix`] +* [link beast.ref.boost__beast__file_stdio `file_stdio`] +* [link beast.ref.boost__beast__file_win32 `file_win32`] + +[endsect] diff --git a/doc/qbk/07_concepts/RatePolicy_zh_Hans.qbk b/doc/qbk/07_concepts/RatePolicy_zh_Hans.qbk new file mode 100644 index 0000000..80a4cef --- /dev/null +++ b/doc/qbk/07_concepts/RatePolicy_zh_Hans.qbk @@ -0,0 +1,124 @@ +[/ + Copyright (c) 2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section:RatePolicy RatePolicy] + +An instance of [*RatePolicy] is associated with a +[link beast.ref.boost__beast__basic_stream `basic_stream`], +and controls the rate at which bytes may be independently sent and +received. This may be used to achieve fine-grained bandwidth management +and flow control. + +[heading Associated Types] + +* [link beast.ref.boost__beast__rate_policy_access `rate_policy_access`] + +[warning + These requirements may undergo non-backward compatible + changes in subsequent versions. +] + +[heading Requirements] + +In this table: + +* `P` denotes a type that meets the requirements of [*RatePolicy]. +* `x` denotes an xvalue of type `P` +* `a` denotes a value of type `P`. +* `n` denotes a value of type `std::size_t` + +[table Valid expressions +[[Expression] [Type] [Semantics, Pre/Post-conditions]] +[ + [`P a(x)`] + [] + [ + Requires ['MoveConstructible]. + ] +][ + [`friend rate_policy_access`] + [] + [ + The member functions required in `P` should be private. + [link beast.ref.boost__beast__rate_policy_access `rate_policy_access`] + must be a friend of `P` for the implementation to gain access + to the required member functions. + ] +][ + [`a.available_read_bytes()`] + [`std::size_t`] + [ + This function is called by the implementation to determine + the maximum number of allowed bytes to be transferred + in the next read operation. The actual number of bytes + subsequently transferred may be less than this number. + + If the policy returns a value of zero, the read operation + will asynchronously wait until the next timer interval + before retrying. When the retry occurs, this function will + be called again. + ] +][ + [`a.available_write_bytes()`] + [`std::size_t`] + [ + This function is called by the implementation to determine + the maximum number of allowed bytes to be transferred + in the next write operation. The actual number of bytes + subsequently transferred may be less than this number. + + If the policy returns a value of zero, the read operation + will asynchronously wait until the next timer interval + before retrying. When the retry occurs, this function will + be called again. + ] +][ + [`a.transfer_read_bytes(n)`] + [] + [ + The implementation calls this function to inform the + policy that `n` bytes were successfully transferred + in the most recent read operation. The policy object + may optionally use this information to calculate + throughputs and/or inform the algorithm used to + determine subsequently queried transfer maximums. + ] +][ + [`a.transfer_write_bytes(n)`] + [] + [ + The implementation calls this function to inform the + policy that `n` bytes were successfully transferred + in the most recent write operation. The policy object + may optionally use this information to calculate + throughputs and/or inform the algorithm used to + determine subsequently queried transfer limits. + ] +][ + [`a.on_timer()`] + [] + [ + The implementation calls this function every time the + internal timer expires. The policy object may optionally + use this opportunity to calculate elapsed time and + throughput, and/or inform the algorithm used to + determine subsequently queried transfer limits. + ] +]] + +[heading Exemplar] + +[concept_RatePolicy] + +[heading Models] + +* [link beast.ref.boost__beast__simple_rate_policy `simple_rate_policy`] +* [link beast.ref.boost__beast__unlimited_rate_policy `unlimited_rate_policy`] + +[endsect] diff --git a/doc/qbk/07_concepts/Streams_zh_Hans.qbk b/doc/qbk/07_concepts/Streams_zh_Hans.qbk new file mode 100644 index 0000000..54b2538 --- /dev/null +++ b/doc/qbk/07_concepts/Streams_zh_Hans.qbk @@ -0,0 +1,41 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section:streams Streams] + +A stream in the context of Beast and networking, represents a full-duplex +connection between two programs or hosts, where data represented as +bytes may be received reliably in the same order they were written. +Streams may support any combination of synchronous and/or asynchronous +reading and writing. + +Stream concepts are based on named requirements in networking: + +[heading:Stream Stream] + +A type modeling [*Stream] meets either or both of the following requirements: + +* [*AsyncStream] +* [*SyncStream] + +[heading:AsyncStream AsyncStream] + +A type modeling [*AsyncStream] meets the following requirements: + +* __AsyncReadStream__ +* __AsyncWriteStream__ + +[heading:SyncStream SyncStream] + +A type modeling [*SyncStream] meets the following requirements: + +* __SyncReadStream__ +* __SyncWriteStream__ + +[endsect] diff --git a/doc/qbk/07_concepts/_concepts_zh_Hans.qbk b/doc/qbk/07_concepts/_concepts_zh_Hans.qbk new file mode 100644 index 0000000..ac35fd3 --- /dev/null +++ b/doc/qbk/07_concepts/_concepts_zh_Hans.qbk @@ -0,0 +1,26 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section:concepts Concepts] + +This section describes all of the concepts defined by the library. + +[include Body.qbk] +[include BodyReader.qbk] +[include BodyWriter.qbk] +[include BufferSequence.qbk] +[include BuffersGenerator.qbk] +[include DynamicBuffer.qbk] +[include Fields.qbk] +[include FieldsWriter.qbk] +[include File.qbk] +[include RatePolicy.qbk] +[include Streams.qbk] + +[endsect] diff --git a/doc/qbk/08_design/1_http_message_zh_Hans.qbk b/doc/qbk/08_design/1_http_message_zh_Hans.qbk new file mode 100644 index 0000000..cd3154c --- /dev/null +++ b/doc/qbk/08_design/1_http_message_zh_Hans.qbk @@ -0,0 +1,361 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast + + +] + +[section:http_message_container HTTP Message Container __video__] + +The following video presentation was delivered at +[@https://cppcon.org/ CppCon] +in 2017. The presentation provides a simplified explanation of the design +process for the HTTP message container used in Beast. The slides and code +used are available in the +[@https://github.com/vinniefalco/CppCon2017 GitHub repository]. + +[/ "Make Classes Great Again! (Using Concepts for Customization Points)"] +[block''' + + + + + +'''] + +In this section we describe the problem of modeling HTTP messages and explain +how the library arrived at its solution, with a discussion of the benefits +and drawbacks of the design choices. The goal for creating a message model +is to create a container with value semantics, possibly movable and/or +copyable, that contains all the information needed to serialize, or all +of the information captured during parsing. More formally, given: + +* `m` is an instance of an HTTP message container + +* `x` is a series of octets describing a valid HTTP message in + the serialized format described in __rfc7230__. + +* `S(m)` is a serialization function which produces a series of octets + from a message container. + +* `P(x)` is a parsing function which produces a message container from + a series of octets. + +These relations are true: + +* `S(m) == x` + +* `P(S(m)) == m` + +We would also like our message container to have customization points +permitting the following: allocator awareness, user-defined containers +to represent header fields, and user-defined types and algorithms to +represent the body. And finally, because requests and responses have +different fields in the ['start-line], we would like the containers for +requests and responses to be represented by different types for function +overloading. + +Here is our first attempt at declaring some message containers: + +[table +[[ +``` +/// An HTTP request +template +struct request +{ + int version; + std::string method; + std::string target; + Fields fields; + + typename Body::value_type body; +}; +``` +][ +``` +/// An HTTP response +template +struct response +{ + int version; + int status; + std::string reason; + Fields fields; + + typename Body::value_type body; +}; +``` +]] +] + +These containers are capable of representing everything in the model +of HTTP requests and responses described in __rfc7230__. Request and +response objects are different types. The user can choose the container +used to represent the fields. And the user can choose the [*Body] type, +which is a concept defining not only the type of `body` member but also +the algorithms used to transfer information in and out of that member +when performing serialization and parsing. + +However, a problem arises. How do we write a function which can accept +an object that is either a request or a response? As written, the only +obvious solution is to make the message a template type. Additional traits +classes would then be needed to make sure that the passed object has a +valid type which meets the requirements. These unnecessary complexities +are bypassed by making each container a partial specialization: +``` +/// An HTTP message +template +struct message; + +/// An HTTP request +template +struct message +{ + int version; + std::string method; + std::string target; + Fields fields; + + typename Body::value_type body; +}; + +/// An HTTP response +template +struct message +{ + int version; + int status; + std::string reason; + Fields fields; + + typename Body::value_type body; +}; +``` + +Now we can declare a function which takes any message as a parameter: +``` +template +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 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 +this, there needs to be a way to model the header portion of a message. +And we'd like to do this in a way that allows functions which take the +header as a parameter, to also accept a type representing the whole +message (the function will see just the header part). This suggests +inheritance, by splitting a new base class off of the message: +``` +/// An HTTP message header +template +struct header; +``` + +Code which accesses the fields has to laboriously mention the `fields` +member, so we'll not only make `header` a base class but we'll make +a quality of life improvement and derive the header from the fields +for notational convenience. In order to properly support all forms +of construction of [*Fields] there will need to be a set of suitable +constructor overloads (not shown): +``` +/// An HTTP request header +template +struct header : Fields +{ + int version; + std::string method; + std::string target; +}; + +/// An HTTP response header +template +struct header : Fields +{ + int version; + int status; + std::string reason; +}; + +/// An HTTP message +template +struct message : header +{ + typename Body::value_type body; + + /// Construct from a `header` + message(header&& h); +}; + +``` + +Note that the `message` class now has a constructor allowing messages +to be constructed from a similarly typed `header`. This handles the case +where the user already has the header and wants to make a commitment to the +type for [*Body]. A function can be declared which accepts any header: +``` +template +void f(header& msg); +``` + +Until now we have not given significant consideration to the constructors +of the `message` class. But to achieve all our goals we will need to make +sure that there are enough constructor overloads to not only provide for +the special copy and move members if the instantiated types support it, +but also allow the fields container and body container to be constructed +with arbitrary variadic lists of parameters. This allows the container +to fully support allocators. + +The solution used in the library is to treat the message like a `std::pair` +for the purposes of construction, except that instead of `first` and `second` +we have the `Fields` base class and `message::body` member. This means that +single-argument constructors for those fields should be accessible as they +are with `std::pair`, and that a mechanism identical to the pair's use of +`std::piecewise_construct` should be provided. Those constructors are too +complex to repeat here, but interested readers can view the declarations +in the corresponding header file. + +There is now significant progress with our message container but a stumbling +block remains. There is no way to control the allocator for the `std::string` +members. We could add an allocator to the template parameter list of the +header and message classes, use it for those strings. This is unsatisfying +because of the combinatorial explosion of constructor variations needed to +support the scheme. It also means that request messages could have [*four] +different allocators: two for the fields and body, and two for the method +and target strings. A better solution is needed. + +To get around this we make an interface modification and then add +a requirement to the [*Fields] type. First, the interface change: +``` +/// An HTTP request header +template +struct header : Fields +{ + int version; + + verb method() const; + string_view method_string() const; + void method(verb); + void method(string_view); + + string_view target(); const; + void target(string_view); + +private: + verb method_; +}; + +/// An HTTP response header +template +struct header : Fields +{ + int version; + int result; + string_view reason() const; + void reason(string_view); +}; +``` + +The start-line data members are replaced by traditional accessors +using non-owning references to string buffers. The method is stored +using a simple integer instead of the entire string, for the case +where the method is recognized from the set of known verb strings. + +Now we add a requirement to the fields type: management of the +corresponding string is delegated to the [*Fields] container, which can +already be allocator aware and constructed with the necessary allocator +parameter via the provided constructor overloads for `message`. The +delegation implementation looks like this (only the response header +specialization is shown): +``` +/// An HTTP response header +template +struct header : Fields +{ + int version; + int status; + + string_view + reason() const + { + return this->reason_impl(); // protected member of Fields + } + + void + reason(string_view s) + { + this->reason_impl(s); // protected member of Fields + } +}; +``` + +Now that we've accomplished our initial goals and more, there are a few +more quality of life improvements to make. Users will choose different +types for `Body` far more often than they will for `Fields`. Thus, we +swap the order of these types and provide a default. Then, we provide +type aliases for requests and responses to soften the impact of using +`bool` to choose the specialization: + +``` +/// An HTTP header +template +struct header; + +/// An HTTP message +template +struct message; + +/// An HTTP request +template +using request = message; + +/// An HTTP response +template +using response = message; +``` + +This allows concise specification for the common cases, while +allowing for maximum customization for edge cases: +``` +request req; + +response res; +``` + +This container is also capable of representing complete HTTP/2 messages. +Not because it was explicitly designed for, but because the IETF wanted to +preserve message compatibility with HTTP/1. Aside from version specific +fields such as Connection, the contents of HTTP/1 and HTTP/2 messages are +identical even though their serialized representation is considerably +different. The message model presented in this library is ready for HTTP/2. + +In conclusion, this representation for the message container is well thought +out, provides comprehensive flexibility, and avoids the necessity of defining +additional traits classes. User declarations of functions that accept headers +or messages as parameters are easy to write in a variety of ways to accomplish +different results, without forcing cumbersome SFINAE declarations everywhere. + +[endsect] diff --git a/doc/qbk/08_design/2_http_comparison_zh_Hans.qbk b/doc/qbk/08_design/2_http_comparison_zh_Hans.qbk new file mode 100644 index 0000000..4909d9d --- /dev/null +++ b/doc/qbk/08_design/2_http_comparison_zh_Hans.qbk @@ -0,0 +1,456 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section HTTP Comparison to Other Libraries] + +There are a few C++ published libraries which implement some of the HTTP +protocol. We analyze the message model chosen by those libraries and discuss +the advantages and disadvantages relative to Beast. + +The general strategy used by the author to evaluate external libraries is +as follows: + +* Review the message model. Can it represent a complete request or + response? What level of allocator support is present? How much + customization is possible? + +* Review the stream abstraction. This is the type of object, such as + a socket, which may be used to parse or serialize (i.e. read and write). + Can user defined types be specified? What's the level of conformance to + to Asio or Networking-TS concepts? + +* Check treatment of buffers. Does the library manage the buffers + or can users provide their own buffers? + +* How does the library handle corner cases such as trailers, + Expect: 100-continue, or deferred commitment of the body type? + +[note + Declarations examples from external libraries have been edited: + portions have been removed for simplification. +] + + + +[heading cpp-netlib] + +[@https://github.com/cpp-netlib/cpp-netlib/tree/092cd570fb179d029d1865aade9f25aae90d97b9 [*cpp-netlib]] +is a network programming library previously intended for Boost but not +having gone through formal review. As of this writing it still uses the +Boost name, namespace, and directory structure although the project states +that Boost acceptance is no longer a goal. The library is based on Boost.Asio +and bills itself as ['"a collection of network related routines/implementations +geared towards providing a robust cross-platform networking library"]. It +cites ['"Common Message Type"] as a feature. As of the branch previous +linked, it uses these declarations: +``` +template +struct basic_message { + public: + typedef Tag tag; + + typedef typename headers_container::type headers_container_type; + typedef typename headers_container_type::value_type header_type; + typedef typename string::type string_type; + + headers_container_type& headers() { return headers_; } + headers_container_type const& headers() const { return headers_; } + + string_type& body() { return body_; } + string_type const& body() const { return body_; } + + string_type& source() { return source_; } + string_type const& source() const { return source_; } + + string_type& destination() { return destination_; } + string_type const& destination() const { return destination_; } + + private: + friend struct detail::directive_base; + friend struct detail::wrapper_base >; + + mutable headers_container_type headers_; + mutable string_type body_; + mutable string_type source_; + mutable string_type destination_; +}; +``` + +This container is the base class template used to represent HTTP messages. +It uses a "tag" type style specializations for a variety of trait classes, +allowing for customization of the various parts of the message. For example, +a user specializes `headers_container` to determine what container type +holds the header fields. We note some problems with the container declaration: + +* The header and body containers may only be default-constructed. + +* No stateful allocator support. + +* There is no way to defer the commitment of the type for `body_` to + after the headers are read in. + +* The message model includes a "source" and "destination." This is + extraneous metadata associated with the connection which is not part + of the HTTP protocol specification and belongs elsewhere. + +* The use of `string_type` (a customization point) for source, + destination, and body suggests that `string_type` models a + [*ForwardRange] whose `value_type` is `char`. This representation + is less than ideal, considering that the library is built on + Boost.Asio. Adapting a __DynamicBuffer__ to the required forward + range destroys information conveyed by the __ConstBufferSequence__ + and __MutableBufferSequence__ used in dynamic buffers. The consequence + is that cpp-netlib implementations will be less efficient than an + equivalent __NetTS__ conforming implementation. + +* The library uses specializations of `string` to change the type + of string used everywhere, including the body, field name and value + pairs, and extraneous metadata such as source and destination. The + user may only choose a single type: field name, field values, and + the body container will all use the same string type. This limits + utility of the customization point. The library's use of the string + trait is limited to selecting between `std::string` and `std::wstring`. + We do not find this use-case compelling given the limitations. + +* The specialized trait classes generate a proliferation of small + additional framework types. To specialize traits, users need to exit + their namespace and intrude into the `boost::network::http` namespace. + The way the traits are used in the library limits the usefulness + of the traits to trivial purpose. + +* The `string customization point constrains user defined body types + to few possible strategies. There is no way to represent an HTTP message + body as a filename with accompanying algorithms to store or retrieve data + from the file system. + +The design of the message container in this library is cumbersome +with its system of customization using trait specializations. The +use of these customizations is extremely limited due to the way they +are used in the container declaration, making the design overly +complex without corresponding benefit. + + + +[heading Boost.HTTP] + +[@https://github.com/BoostGSoC14/boost.http/tree/45fc1aa828a9e3810b8d87e669b7f60ec100bff4 [*boost.http]] +is a library resulting from the 2014 Google Summer of Code. It was submitted +for a Boost formal review and rejected in 2015. It is based on Boost.Asio, +and development on the library has continued to the present. As of the branch +previously linked, it uses these message declarations: +``` +template +struct basic_message +{ + typedef Headers headers_type; + typedef Body body_type; + + headers_type &headers(); + + const headers_type &headers() const; + + body_type &body(); + + const body_type &body() const; + + headers_type &trailers(); + + const headers_type &trailers() const; + +private: + headers_type headers_; + body_type body_; + headers_type trailers_; +}; + +typedef basic_message> message; + +template +struct is_message>: public std::true_type {}; +``` + +* This container cannot model a complete message. The ['start-line] items + (method and target for requests, reason-phrase for responses) are + communicated out of band, as is the ['http-version]. A function that + operates on the message including the start line requires additional + parameters. This is evident in one of the + [@https://github.com/BoostGSoC14/boost.http/blob/45fc1aa828a9e3810b8d87e669b7f60ec100bff4/example/basic_router.cpp#L81 example programs]. + The `500` and `"OK"` arguments represent the response ['status-code] and + ['reason-phrase] respectively: + ``` + ... + http::message reply; + ... + self->socket.async_write_response(500, string_ref("OK"), reply, yield); + ``` + +* `headers_`, `body_`, and `trailers_` may only be default-constructed, + since there are no explicitly declared constructors. + +* There is no way to defer the commitment of the [*Body] type to after + the headers are read in. This is related to the previous limitation + on default-construction. + +* No stateful allocator support. This follows from the previous limitation + on default-construction. Buffers for start-line strings must be + managed externally from the message object since they are not members. + +* The trailers are stored in a separate object. Aside from the combinatorial + explosion of the number of additional constructors necessary to fully + support arbitrary forwarded parameter lists for each of the headers, body, + and trailers members, the requirement to know in advance whether a + particular HTTP field will be located in the headers or the trailers + poses an unnecessary complication for general purpose functions that + operate on messages. + +* The declarations imply that `std::vector` is a model of [*Body]. + More formally, that a body is represented by the [*ForwardRange] + concept whose `value_type` is an 8-bit integer. This representation + is less than ideal, considering that the library is built on + Boost.Asio. Adapting a __DynamicBuffer__ to the required forward range + destroys information conveyed by the __ConstBufferSequence__ and + __MutableBufferSequence__ used in dynamic buffers. The consequence is + that Boost.HTTP implementations will be less efficient when dealing + with body containers than an equivalent __NetTS__ conforming + implementation. + +* The [*Body] customization point constrains user defined types to + very limited implementation strategies. For example, there is no way + to represent an HTTP message body as a filename with accompanying + algorithms to store or retrieve data from the file system. + +This representation addresses a narrow range of use cases. It has +limited potential for customization and performance. It is more difficult +to use because it excludes the start line fields from the model. + + + +[heading C++ REST SDK (cpprestsdk)] + +[@https://github.com/Microsoft/cpprestsdk/tree/381f5aa92d0dfb59e37c0c47b4d3771d8024e09a [*cpprestsdk]] +is a Microsoft project which ['"...aims to help C++ developers connect to and +interact with services"]. It offers the most functionality of the libraries +reviewed here, including support for Websocket services using its websocket++ +dependency. It can use native APIs such as HTTP.SYS when building Windows +based applications, and it can use Boost.Asio. The WebSocket module uses +Boost.Asio exclusively. + +As cpprestsdk is developed by a large corporation, it contains quite a bit +of functionality and necessarily has more interfaces. We will break down +the interfaces used to model messages into more manageable pieces. This +is the container used to store the HTTP header fields: +``` +class http_headers +{ +public: + ... + +private: + std::map m_headers; +}; +``` + +This declaration is quite bare-bones. We note the typical problems of +most field containers: + +* The container may only be default-constructed. + +* No support for allocators, stateful or otherwise. + +* There are no customization points at all. + +Now we analyze the structure of +the larger message container. The library uses a handle/body idiom. There +are two public message container interfaces, one for requests (`http_request`) +and one for responses (`http_response`). Each interface maintains a private +shared pointer to an implementation class. Public member function calls +are routed to the internal implementation. This is the first implementation +class, which forms the base class for both the request and response +implementations: +``` +namespace details { + +class http_msg_base +{ +public: + http_headers &headers() { return m_headers; } + + _ASYNCRTIMP void set_body(const concurrency::streams::istream &instream, const utf8string &contentType); + + /// Set the stream through which the message body could be read + void set_instream(const concurrency::streams::istream &instream) { m_inStream = instream; } + + /// Set the stream through which the message body could be written + void set_outstream(const concurrency::streams::ostream &outstream, bool is_default) { m_outStream = outstream; m_default_outstream = is_default; } + + const pplx::task_completion_event & _get_data_available() const { return m_data_available; } + +protected: + /// Stream to read the message body. + concurrency::streams::istream m_inStream; + + /// stream to write the msg body + concurrency::streams::ostream m_outStream; + + http_headers m_headers; + bool m_default_outstream; + + /// The TCE is used to signal the availability of the message body. + pplx::task_completion_event m_data_available; +}; +``` + +To understand these declarations we need to first understand that cpprestsdk +uses the asynchronous model defined by Microsoft's +[@https://msdn.microsoft.com/en-us/library/dd504870.aspx [*Concurrency Runtime]]. +Identifiers from the [@https://msdn.microsoft.com/en-us/library/jj987780.aspx [*`pplx` namespace]] +define common asynchronous patterns such as tasks and events. The +`concurrency::streams::istream` parameter and `m_data_available` data member +indicates a lack of separation of concerns. The representation of HTTP messages +should not be conflated with the asynchronous model used to serialize or +parse those messages in the message declarations. + +The next declaration forms the complete implementation class referenced by the +handle in the public interface (which follows after): +``` +/// Internal representation of an HTTP request message. +class _http_request final : public http::details::http_msg_base, public std::enable_shared_from_this<_http_request> +{ +public: + _ASYNCRTIMP _http_request(http::method mtd); + + _ASYNCRTIMP _http_request(std::unique_ptr server_context); + + http::method &method() { return m_method; } + + const pplx::cancellation_token &cancellation_token() const { return m_cancellationToken; } + + _ASYNCRTIMP pplx::task reply(const http_response &response); + +private: + + // Actual initiates sending the response, without checking if a response has already been sent. + pplx::task _reply_impl(http_response response); + + http::method m_method; + + std::shared_ptr m_progress_handler; +}; + +} // namespace details +``` + +As before, we note that the implementation class for HTTP requests concerns +itself more with the mechanics of sending the message asynchronously than +it does with actually modeling the HTTP message as described in __rfc7230__: + +* The constructor accepting `std::unique_ptrmethod(); } + + void set_method(const http::method &method) const { _m_impl->method() = method; } + + /// Extract the body of the request message as a string value, checking that the content type is a MIME text type. + /// A body can only be extracted once because in some cases an optimization is made where the data is 'moved' out. + pplx::task extract_string(bool ignore_content_type = false) + { + auto impl = _m_impl; + return pplx::create_task(_m_impl->_get_data_available()).then([impl, ignore_content_type](utility::size64_t) { return impl->extract_string(ignore_content_type); }); + } + + /// Extracts the body of the request message into a json value, checking that the content type is application/json. + /// A body can only be extracted once because in some cases an optimization is made where the data is 'moved' out. + pplx::task extract_json(bool ignore_content_type = false) const + { + auto impl = _m_impl; + return pplx::create_task(_m_impl->_get_data_available()).then([impl, ignore_content_type](utility::size64_t) { return impl->_extract_json(ignore_content_type); }); + } + + /// Sets the body of the message to the contents of a byte vector. If the 'Content-Type' + void set_body(const std::vector &body_data); + + /// Defines a stream that will be relied on to provide the body of the HTTP message when it is + /// sent. + void set_body(const concurrency::streams::istream &stream, const utility::string_t &content_type = _XPLATSTR("application/octet-stream")); + + /// Defines a stream that will be relied on to hold the body of the HTTP response message that + /// results from the request. + void set_response_stream(const concurrency::streams::ostream &stream); + { + return _m_impl->set_response_stream(stream); + } + + /// Defines a callback function that will be invoked for every chunk of data uploaded or downloaded + /// as part of the request. + void set_progress_handler(const progress_handler &handler); + +private: + friend class http::details::_http_request; + friend class http::client::http_client; + + std::shared_ptr _m_impl; +}; +``` + +It is clear from this declaration that the goal of the message model in +this library is driven by its use-case (interacting with REST servers) +and not to model HTTP messages generally. We note problems similar to +the other declarations: + +* There are no compile-time customization points at all. The only + customization is in the `concurrency::streams::istream` and + `concurrency::streams::ostream` reference parameters. Presumably, + these are abstract interfaces which may be subclassed by users + to achieve custom behaviors. + +* The extraction of the body is conflated with the asynchronous model. + +* No way to define an allocator for the container used when extracting + the body. + +* A body can only be extracted once, limiting the use of this container + when using a functional programming style. + +* Setting the body requires either a vector or a `concurrency::streams::istream`. + No user defined types are possible. + +* The HTTP request container conflates HTTP response behavior (see the + `set_response_stream` member). Again this is likely purpose-driven but + the lack of separation of concerns limits this library to only the + uses explicitly envisioned by the authors. + +The general theme of the HTTP message model in cpprestsdk is "no user +definable customizations". There is no allocator support, and no +separation of concerns. It is designed to perform a specific set of +behaviors. In other words, it does not follow the open/closed principle. + +Tasks in the Concurrency Runtime operate in a fashion similar to +`std::future`, but with some improvements such as continuations which +are not yet in the C++ standard. The costs of using a task based +asynchronous interface instead of completion handlers is well +documented: synchronization points along the call chain of composed +task operations which cannot be optimized away. See: +[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3747.pdf +[*A Universal Model for Asynchronous Operations]] (Kohlhoff). + +[endsect] diff --git a/doc/qbk/08_design/3_websocket_zaphoyd_zh_Hans.qbk b/doc/qbk/08_design/3_websocket_zaphoyd_zh_Hans.qbk new file mode 100644 index 0000000..41beee0 --- /dev/null +++ b/doc/qbk/08_design/3_websocket_zaphoyd_zh_Hans.qbk @@ -0,0 +1,436 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section Comparison to Zaphoyd Studios WebSocket++] + +[variablelist + +[[ + How does this compare to [@https://www.zaphoyd.com/websocketpp websocketpp], + an alternate header-only WebSocket implementation? +][ +[variablelist + +[[1. Synchronous Interface][ + +Beast offers full support for WebSockets using a synchronous interface. It +uses the same style of interfaces found in Boost.Asio: versions that throw +exceptions, or versions that return the error code in a reference parameter: + +[table + [ + [[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L774 Beast]] + [websocketpp] + ][ + [``` + template + void + read(DynamicBuffer& dynabuf) + ```] + [ + // + ] +]]]] + +[[2. Connection Model][ + +websocketpp supports multiple transports by utilizing a trait, the `config::transport_type` +([@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/asio/connection.hpp#L60 asio transport example]) +To get an idea of the complexity involved with implementing a transport, +compare the asio transport to the +[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/iostream/connection.hpp#L59 `iostream` transport] +(a layer that allows websocket communication over a `std::iostream`). + +In contrast, Beast abstracts the transport by defining just one [*`NextLayer`] +template argument The type requirements for [*`NextLayer`] are +already familiar to users as they are documented in Asio: +__AsyncReadStream__, __AsyncWriteStream__, __SyncReadStream__, __SyncWriteStream__. + +The type requirements for instantiating `beast::websocket::stream` versus +`websocketpp::connection` with user defined types are vastly reduced +(18 functions versus 2). Note that websocketpp connections are passed by +`shared_ptr`. Beast does not use `shared_ptr` anywhere in its public interface. +A `beast::websocket::stream` is constructible and movable in a manner identical +to a `boost::asio::ip::tcp::socket`. Callers can put such objects in a +`shared_ptr` if they want to, but there is no requirement to do so. + +[table + [ + [[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp Beast]] + [[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L234 websocketpp]] + ][ + [``` + template + class stream + { + NextLayer next_layer_; + ... + } + ```] + [``` + template + class connection + : public config::transport_type::transport_con_type + , public config::connection_base + { + public: + typedef lib::shared_ptr ptr; + ... + } + ```] +]]]] + +[[3. Client and Server Role][ + +websocketpp provides multi-role support through a hierarchy of +different classes. A `beast::websocket::stream` is role-agnostic, it +offers member functions to perform both client and server handshakes +in the same class. The same types are used for client and server +streams. + +[table + [ + [Beast] + [[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/roles/server_endpoint.hpp#L39 websocketpp], + [@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/roles/client_endpoint.hpp#L42 also]] + ][ + [ + // + ] + [``` + template + class client : public endpoint,config>; + template + class server : public endpoint,config>; + ```] +]]]] + +[[4. Thread Safety][ + +websocketpp uses mutexes to protect shared data from concurrent +access. In contrast, Beast does not use mutexes anywhere in its +implementation. Instead, it follows the Asio pattern. Calls to +asynchronous initiation functions use the same method to invoke +intermediate handlers as the method used to invoke the final handler, +through the associated executor mechanism. + +The only requirement in Beast is that calls to asynchronous initiation +functions are made from the same implicit or explicit strand. For +example, if the `io_context` associated with a `beast::websocket::stream` +is single threaded, this counts as an implicit strand and no performance +costs associated with mutexes are incurred. + +[table + [ + [[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/impl/read_frame_op.ipp#L118 Beast]] + [[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/iostream/connection.hpp#L706 websocketpp]] + ][ + [``` + mutex_type m_read_mutex; + ```] +]]]] + +[[5. Callback Model][ + +websocketpp requires a one-time call to set the handler for each event +in its interface (for example, upon message receipt). The handler is +represented by a `std::function` equivalent. Its important to recognize +that the websocketpp interface performs type-erasure on this handler. + +In comparison, Beast handlers are specified in a manner identical to +Boost.Asio. They are function objects which can be copied or moved but +most importantly they are not type erased. The compiler can see +through the type directly to the implementation, permitting +optimization. Furthermore, Beast follows the Asio rules for treatment +of handlers. It respects any allocation, executors, cancellations +associated with the handler through the use of argument +dependent lookup overloads of functions such as `bind_allocaotr`. + +The Beast completion handler is provided at the call site. For each +call to an asynchronous initiation function, it is guaranteed that +there will be exactly one final call to the handler. This functions +exactly the same way as the asynchronous initiation functions found in +Boost.Asio, allowing the composition of higher level abstractions. + +[table + [ + [[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L834 Beast]] + [[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L281 websocketpp], + [@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L473 also]] + ][ + [``` + template< + class DynamicBuffer, // Supports user defined types + class ReadHandler // Handler is NOT type-erased + > + typename async_completion< // Return value customization + ReadHandler, // supports futures and coroutines + void(error_code) + >::result_type + async_read( + DynamicBuffer& dynabuf, + ReadHandler&& handler); + ```] + [``` + typedef lib::function< + void(connection_hdl,message_ptr) + > message_handler; + void set_message_handler(message_handler h); + ```] +]]]] + +[[6. Extensible Asynchronous Model][ + +Beast fully supports the +[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3896.pdf Extensible Asynchronous Model] +developed by Christopher Kohlhoff, author of Boost.Asio (see Section 8). + +Beast websocket asynchronous interfaces may be used seamlessly with +`std::future` stackful/stackless coroutines, or user defined customizations. + +[table + [ + [[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/impl/stream.ipp#L378 Beast]] + [websocketpp] + ][ + [``` + beast::async_completion< + ReadHandler, + void(error_code)> completion{handler}; + read_op< + DynamicBuffer, decltype(completion.handler)>{ + completion.handler, *this, op, buffer}; + + return completion.result.get(); // Customization point + ```] + [ + // + ] +]]]] + +[[7. Message Buffering][ + +websocketpp defines a message buffer, passed in arguments by +`shared_ptr`, and an associated message manager which permits +aggregation and reuse of memory. The implementation of +`websocketpp::message` uses a `std::string` to hold the payload. If an +incoming message is broken up into multiple frames, the string may be +reallocated for each continuation frame. The `std::string` always uses +the standard allocator, it is not possible to customize the choice of +allocator. + +Beast allows callers to specify the object for receiving the message +or frame data, which is of any type meeting the requirements of +__DynamicBuffer__ (modeled after `boost::asio::streambuf`). + +Beast comes with the class __basic_multi_buffer__, an efficient +implementation of the __DynamicBuffer__ concept which makes use of multiple +allocated octet arrays. If an incoming message is broken up into +multiple pieces, no reallocation occurs. Instead, new allocations are +appended to the sequence when existing allocations are filled. Beast +does not impose any particular memory management model on callers. The +__basic_multi_buffer__ provided by beast supports standard allocators through +a template argument. Use the __DynamicBuffer__ that comes with beast, +customize the allocator if you desire, or provide your own type that +meets the requirements. + +[table + [ + [[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L774 Beast]] + [[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/message_buffer/message.hpp#L78 websocketpp]] + ][ + [``` + template + read(DynamicBuffer& dynabuf); + ```] + [``` + template class con_msg_manager> + class message { + public: + typedef lib::shared_ptr ptr; + ... + std::string m_payload; + ... + }; + ```] +]]]] + +[[8. Sending Messages][ + +When sending a message, websocketpp requires that the payload is +packaged in a `websocketpp::message` object using `std::string` as the +storage, or it requires a copy of the caller provided buffer by +constructing a new message object. Messages are placed onto an +outgoing queue. An asynchronous write operation runs in the background +to clear the queue. No user facing handler can be registered to be +notified when messages or frames have completed sending. + +Beast doesn't allocate or make copies of buffers when sending data. The +caller's buffers are sent in-place. You can use any object meeting the +requirements of __ConstBufferSequence, permitting efficient scatter-gather I/O. + +The [*ConstBufferSequence] interface allows callers to send data from +memory-mapped regions (not possible in websocketpp). Callers can also +use the same buffers to send data to multiple streams, for example +broadcasting common subscription data to many clients at once. For +each call to `async_write` the completion handler is called once when +the data finishes sending, in a manner identical to `boost::asio::async_write`. + +[table + [ + [[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L1048 Beast]] + [[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L672 websocketpp]] + ][ + [``` + template + void + write(ConstBufferSequence const& buffers); + ```] + [``` + lib::error_code send(std::string const & payload, + frame::opcode::value op = frame::opcode::text); + ... + lib::error_code send(message_ptr msg); + ```] +]]]] + +[[9. Streaming Messages][ + +websocketpp requires that the entire message fit into memory, and that +the size is known ahead of time. + +Beast allows callers to compose messages in individual frames. This is +useful when the size of the data is not known ahead of time or if it +is not desired to buffer the entire message in memory at once before +sending it. For example, sending periodic output of a database query +running on a coroutine. Or sending the contents of a file in pieces, +without bringing it all into memory. + +[table + [ + [[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L1151 Beast]] + [websocketpp] + ][ + [``` + template + void + write_some(bool fin, + ConstBufferSequence const& buffers); + ```] + [ + // + ] +]]]] + +[[10. Flow Control][ + +The websocketpp read implementation continuously reads asynchronously +from the network and buffers message data. To prevent unbounded growth +and leverage TCP/IP's flow control mechanism, callers can periodically +turn this 'read pump' off and back on. + +In contrast a `beast::websocket::stream` does not independently begin +background activity, nor does it buffer messages. It receives data only +when there is a call to an asynchronous initiation function (for +example `beast::websocket::stream::async_read`) with an associated handler. +Applications do not need to implement explicit logic to regulate the +flow of data. Instead, they follow the traditional model of issuing a +read, receiving a read completion, processing the message, then +issuing a new read and repeating the process. + +[table + [ + [Beast] + [[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L728 websocketpp]] + ][ + [ + // + ] + [``` + lib::error_code pause_reading(); + lib::error_code resume_reading(); + ```] +]]]] + +[[11. Connection Establishment][ + +websocketpp offers the `endpoint` class which can handle binding and +listening to a port, and spawning connection objects. + +Beast does not reinvent the wheel here, callers use the interfaces +already in `boost::asio` for receiving incoming connections resolving +host names, or establishing outgoing connections. After the socket (or +`boost::asio::ssl::stream`) is connected, the `beast::websocket::stream` +is constructed around it and the WebSocket handshake can be performed. + +Beast users are free to implement their own "connection manager", but +there is no requirement to do so. + +[table + [ + [[@http://www.boost.org/doc/html/boost_asio/reference/async_connect.html Beast], + [@http://www.boost.org/doc/html/boost_asio/reference/basic_socket_acceptor/async_accept.html also]] + [[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/asio/endpoint.hpp#L52 websocketpp]] + ][ + [``` + #include + ```] + [``` + template + class endpoint : public config::socket_type; + ```] +]]]] + +[[12. WebSocket Handshaking][ + +Callers invoke `beast::websocket::accept` to perform the WebSocket +handshake, but there is no requirement to use this function. Advanced +users can perform the WebSocket handshake themselves. Beast WebSocket +provides the tools for composing the request or response, and the +Beast HTTP interface provides the container and algorithms for sending +and receiving HTTP/1 messages including the necessary HTTP Upgrade +request for establishing the WebSocket session. + +Beast allows the caller to pass the incoming HTTP Upgrade request for +the cases where the caller has already received an HTTP message. +This flexibility permits novel and robust implementations. For example, +a listening socket that can handshake in multiple protocols on the +same port. + +Sometimes callers want to read some bytes on the socket before reading +the WebSocket HTTP Upgrade request. Beast allows these already-received +bytes to be supplied to an overload of the accepting function to permit +sophisticated features. For example, a listening socket that can +accept both regular WebSocket and Secure WebSocket (SSL) connections. + +[table + [ + [[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L501 Beast], + [@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L401 also]] + [websocketpp] + ][ + [``` + template + void + accept(ConstBufferSequence const& buffers); + + template + void + accept(http::header> const& req); + ```] + [ + // + ] +]]]] +] +]] + +] + +[endsect] diff --git a/doc/qbk/08_design/4_faq_zh_Hans.qbk b/doc/qbk/08_design/4_faq_zh_Hans.qbk new file mode 100644 index 0000000..9b0808a --- /dev/null +++ b/doc/qbk/08_design/4_faq_zh_Hans.qbk @@ -0,0 +1,300 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section FAQ] + +To set realistic expectations and prevent a litany of duplicate review +statements, these notes address the most common questions and comments +about Beast and other HTTP libraries that have gone through formal review. + +[variablelist +[[ + "Beast requires too much user code to do anything!" +][ + It is not the intention of the library to provide turn-key + solutions for specific HTTP or WebSocket use-cases. + Instead, it is a sensible protocol layering on top of + Boost.Asio which retains the Boost.Asio memory + management style and asynchronous model. +]] +[[ + "Beast does not offer an HTTP server?" +][ + 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. 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!" +][ + Many reviewers feel that HTTP/2 support is an essential feature of + a HTTP library. The authors agree that HTTP/2 is important but also + feel that the most sensible implementation is one that does not re-use + the same network reading and writing interface for 2 as that for 1.0 + and 1.1. + + The Beast HTTP message model was designed with the new protocol + in mind and should be evaluated in that context. There are plans + to add HTTP/2 in the future, but there is no rush to do so. + Users can work with HTTP/1 now; we should not deny them that + functionality today to wait for a newer protocol tomorrow. + It is the author's position that there is sufficient value in + Beast's HTTP/1-only implementation that the lack of HTTP/2 + should not be a barrier to acceptance. + + The Beast HTTP message model is suitable for HTTP/2 and can be re-used. + The IETF HTTP Working Group adopted message compatibility with HTTP/1.x + as an explicit goal. A parser can simply emit full headers after + decoding the compressed HTTP/2 headers. The stream ID is not logically + part of the message but rather message metadata and should be + communicated out-of-band (see below). HTTP/2 sessions begin with a + traditional HTTP/1.1 Upgrade similar in fashion to the WebSocket + upgrade. An HTTP/2 implementation can use existing Beast.HTTP primitives + to perform this handshake. +]] +[[ + "This should work with standalone-Asio!" +][ + 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 + [ + Boost library acceptance. + ][ + Port to the Boost.Asio version of Networking-TS (This has to wait + until Boost's version of Asio is updated). + ][ + Wait for Networking-TS to become an official part of C++. + ][ + Port to the standard library versions of networking (gcc, clang, msvc). + ][ + Develop proposed language (This can happen concurrently with steps 3 and 4) + ]] +]] +[[ + "You need benchmarks!" +][ + The energy invested in Beast went into the design of the interfaces, + not performance. That said, the most sensitive parts of Beast have + been optimized or designed with optimization in mind. The slow parts + of WebSocket processing have been optimized, and the HTTP parser design + is lifted from another extremely popular project which has performance + as a design goal (see [@https://github.com/h2o/picohttpparser]). + + From: [@http://www.boost.org/development/requirements.html] + + "Aim first for clarity and correctness; optimization should + be only a secondary concern in most Boost libraries." + + 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, as well as some + benchmarks which compare the performance of various Beast dynamic + buffer implementations against Asio's. +]] +[[ + "Beast is a terrible name!" +][ + The name "Boost.Http" or "Boost.WebSocket" would mislead users into + believing they could perform an HTTP request on a URL or put up a + WebSocket client or server in a couple of lines of code. Where + would the core utilities go? Very likely it would step on the + owner of Boost.Asio's toes to put things in the boost/asio + directory; at the very least, it would create unrequested, + additional work for the foreign repository. + + "Beast" is sufficiently vague as to not suggest any particular + functionality, while acting as a memorable umbrella term for a + family of low level containers and algorithms. People in the know + or with a need for low-level network protocol operations will + have no trouble finding it, and the chances of luring a novice + into a bad experience are greatly reduced. + There is precedent for proper names: "Hana", "Fusion", "Phoenix", + and "Spirit" come to mind. Is "Beast" really any worse than say, + "mp11" for example? + Beast also already has a growing body of users and attention from + the open source community, the name Beast comes up in reddit posts + and StackOverflow as the answer to questions about which HTTP or + WebSocket library to use. +]] + + + +[[ + "Some more advanced examples, e.g. including TLS with client/server + certificates would help." +][ + 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. +]] + +[[ + "A built-in HTTP router?" +][ + 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. 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 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 + allows HTTP requests to include arbitrary body types including those needed + to upload a file or fill out a form. +]] + +[[ + "...supporting TLS (is this a feature? If not this would be a show-stopper), + etc." +][ + Beast works with the Stream concept, so it automatically works with the + `boost::asio::ssl::stream` that you have already set up through Asio. +]] + +[[ + "There should also be more examples of how to integrate the http service + with getting files from the file system, generating responses CGI-style" +][ + The design goal for the library is to not try to invent a web server. + We feel that there is a strong need for a basic implementation that + models the HTTP message and provides functions to send and receive them + over Asio. Such an implementation should serve as a building block upon + which higher abstractions such as the aforementioned HTTP service or + cgi-gateway can be built. + + 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." +][ + 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. +]] + + + +[[ + "I would also like to see instances of this library being used + in production. That would give some evidence that the design + works in practice." +][ + 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. +]] + + + +[[ + What about WebSocket message compression? +][ + Beast WebSocket supports the permessage-deflate extension described in + [@https://tools.ietf.org/html/draft-ietf-hybi-permessage-compression-00 draft-ietf-hybi-permessage-compression-00]. + The library comes with a header-only, C++11 port of ZLib's "deflate" codec + used in the implementation of the permessage-deflate extension. +]] +[[ + Where is the WebSocket TLS/SSL interface? +][ + The `websocket::stream` wraps the socket or stream that you provide + (for example, a `boost::asio::ip::tcp::socket` or a + `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. + + The WebSocket implementation [*does] provide support for shutting down + the TLS connection through the use of the ADL compile-time virtual functions + [link beast.ref.boost__beast__websocket__teardown `teardown`] and + [link beast.ref.boost__beast__websocket__async_teardown `async_teardown`]. These will + properly close the connection as per rfc6455 and overloads are available + for TLS streams. Callers may provide their own overloads of these functions + for user-defined next layer types. +]] +[[ + Windows and OpenSSL: How do I install and build with OpenSSL on Microsoft Windows? +][ + An easy method is to use command-line package installers chocolatey or scoop. Examples: + "choco install -y openssl --x86 --version 1.1.1.700" or + "scoop install openssl@1.1.1g -a 32bit -g" + + If you've installed OpenSSL to a directory with spaces in the name, it's often + preferable to create a symbolic link so that you may use a simpler path, such as: + + mklink /D "OpenSSL" "Program Files (x86)\\OpenSSL-Win32" + + Set the environment variable OPENSSL_ROOT to the location of the new install: + + set OPENSSL_ROOT=C:/OpenSSL + + Then, proceed to build. Refer to beast/.dockers/windows-vs-32/Dockerfile for an example of building the test cases with OpenSSL. +]] +] + +[endsect] diff --git a/doc/qbk/08_design/_design_zh_Hans.qbk b/doc/qbk/08_design/_design_zh_Hans.qbk new file mode 100644 index 0000000..19d434c --- /dev/null +++ b/doc/qbk/08_design/_design_zh_Hans.qbk @@ -0,0 +1,75 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section Design Choices] + +The implementations were originally driven by business needs of cryptocurrency +server applications (e.g. [@https://github.com/ripple/rippled rippled]), +written in C++. These needs were not met by existing solutions so Beast +was written from scratch as a solution. Beast's design philosophy avoids +flaws exhibited by other libraries: + +* Don't try to do too much. + +* Don't sacrifice performance. + +* Mimic __Asio__; familiarity breeds confidence. + +* Role-symmetric interfaces; client and server the same (or close to it). + +* Leave important decisions, such as allocating memory or + managing flow control, to the user. + +Beast uses the __DynamicBuffer__ concept presented in the __NetTS__, +and relies heavily on the __ConstBufferSequence__ and +__MutableBufferSequence__ concepts for passing buffers to functions. +The authors have found the dynamic buffer and buffer sequence interfaces to +be optimal for interacting with Asio, and for other tasks such as incremental +parsing of data in buffers (for example, parsing websocket frames stored +in a [link beast.ref.boost__beast__static_buffer `static_buffer`]). + +During the development of Beast the authors have studied other software +packages and in particular the comments left during the Boost Review process +of other packages offering similar functionality. In this section and the +FAQs that follow we attempt to answer those questions that are also applicable +to Beast. + +For HTTP we model the message to maximize flexibility of implementation +strategies while allowing familiar verbs such as [*`read`] and [*`write`]. +The HTTP interface is further driven by the needs of the WebSocket module, +as a WebSocket session requires a HTTP Upgrade handshake exchange at the +start. Other design goals: + +* Keep it simple. + +* Stay low level; don't invent a whole web server or client. + +* Allow for customizations, if the user needs it. + +The following video presentation was delivered at +[@https://cppcon.org/ CppCon] +in 2016. It provides a light introduction to some of the earliest +interfaces of Beast (which have since changed). + +[/ "Introducing Beast..."] +[block''' + + + + + +'''] + +[include 1_http_message.qbk] +[include 2_http_comparison.qbk] +[include 3_websocket_zaphoyd.qbk] +[include 4_faq.qbk] + +[endsect] diff --git a/doc/qbk/main_zh_Hans.qbk b/doc/qbk/main_zh_Hans.qbk new file mode 100644 index 0000000..c0c7527 --- /dev/null +++ b/doc/qbk/main_zh_Hans.qbk @@ -0,0 +1,200 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[library Boost.Beast + [id beast] + [quickbook 1.6] + [copyright 2016 - 2019 Vinnie Falco] + [purpose Networking Protocol Library] + [license + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + [@http://www.boost.org/LICENSE_1_0.txt]) + ] + [authors [Falco, Vinnie]] + [category template] + [category generic] +] + +[template mdash[] '''— '''] +[template indexterm1[term1] ''''''[term1]''''''] +[template indexterm2[term1 term2] ''''''[term1]''''''[term2]''''''] + +[template path_link[path name] ''''''[name]''''''] +[template include_file[path][^<''''''[path]''''''>]] +[template issue[n] '''#'''[n]''''''] + +[def __N3747__ [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3747.pdf [*N3747]]] +[def __NetTS__ [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/n4771.pdf Networking TS]] +[def __rfc6455__ [@https://tools.ietf.org/html/rfc6455 rfc6455]] +[def __rfc7230__ [@https://tools.ietf.org/html/rfc7230 rfc7230]] +[def __Asio__ [@boost:/libs/asio/index.html Boost.Asio]] +[def __async_initfn__ [@boost:/doc/html/boost_asio/reference/asynchronous_operations.html initiating function]] + +[/ C++ Named Requirements ] + +[def __Allocator__ [@https://en.cppreference.com/w/cpp/named_req/Allocator ['Allocator]]] + +[/ Networking Identifiers ] + +[def __basic_stream_socket__ [@boost:/doc/html/boost_asio/reference/basic_stream_socket.html `basic_stream_socket`]] +[def __const_buffer__ [@boost:/doc/html/boost_asio/reference/const_buffer.html `const_buffer`]] +[def __deduced__ [@boost:/doc/html/boost_asio/reference/asynchronous_operations.html#boost_asio.reference.asynchronous_operations.automatic_deduction_of_initiating_function_return_type ['DEDUCED]]] +[def __executor_work_guard__ [@boost:/doc/html/boost_asio/reference/executor_work_guard.html `net::executor_work_guard`]] +[def __get_associated_allocator__ [@boost:/doc/html/boost_asio/reference/get_associated_allocator.html `net::get_associated_allocator`]] +[def __get_associated_executor__ [@boost:/doc/html/boost_asio/reference/get_associated_executor.html `net::get_associated_executor`]] +[def __io_context__ [@boost:/doc/html/boost_asio/reference/io_context.html `net::io_context`]] +[def __mutable_buffer__ [@boost:/doc/html/boost_asio/reference/mutable_buffer.html `mutable_buffer`]] +[def __post__ [@boost:/doc/html/boost_asio/reference/post.html `net::post`]] +[def __socket__ [@boost:/doc/html/boost_asio/reference/ip__tcp/socket.html `tcp::socket`]] +[def __strand__ [@boost:/doc/html/boost_asio/reference/strand.html `net::strand`]] +[def __ssl_context__ [@boost:/doc/html/boost_asio/reference/ssl__context.html `net::ssl::context`]] +[def __ssl_stream__ [@boost:/doc/html/boost_asio/reference/ssl__stream.html `net::ssl::stream`]] +[def __streambuf__ [@boost:/doc/html/boost_asio/reference/streambuf.html `net::streambuf`]] +[def __system_executor__ [@boost:/doc/html/boost_asio/reference/system_executor.html `net::system_executor`]] +[def __use_future__ [@boost:/doc/html/boost_asio/reference/use_future_t.html `net::use_future`]] +[def __yield_context__ [@boost:/doc/html/boost_asio/reference/yield_context.html `net::yield_context`]] + +[/ Networking Named Requirements] + +[def __AsyncReadStream__ [@boost:/doc/html/boost_asio/reference/AsyncReadStream.html ['AsyncReadStream]]] +[def __AsyncWriteStream__ [@boost:/doc/html/boost_asio/reference/AsyncWriteStream.html ['AsyncWriteStream]]] +[def __CompletionCondition__ [@boost:/doc/html/boost_asio/reference/CompletionCondition.html ['CompletionCondition]]] +[def __CompletionHandler__ [@boost:/doc/html/boost_asio/reference/CompletionHandler.html ['CompletionHandler]]] +[def __CompletionToken__ [@boost:/doc/html/boost_asio/reference/asynchronous_operations.html#boost_asio.reference.asynchronous_operations.completion_tokens_and_handlers ['CompletionToken]]] +[def __ConnectCondition__ [@boost:/doc/html/boost_asio/reference/ConnectCondition.html ['ConnectCondition]]] +[def __ConnectHandler__ [@boost:/doc/html/boost_asio/reference/ConnectHandler.html ['ConnectHandler]]] +[def __ConstBufferSequence__ [@boost:/doc/html/boost_asio/reference/ConstBufferSequence.html ['ConstBufferSequence]]] +[def __EndpointSequence__ [@boost:/doc/html/boost_asio/reference/EndpointSequence.html ['EndpointSequence]]] +[def __Executor__ [@boost:/doc/html/boost_asio/reference/Executor1.html ['Executor]]] +[def __Executor1__ [@boost:/doc/html/boost_asio/reference/Executor1.html ['Executor1]]] +[def __Executor2__ [@boost:/doc/html/boost_asio/reference/Executor1.html ['Executor2]]] +[def __ExecutionContext__ [@boost:/doc/html/boost_asio/reference/ExecutionContext.html ['ExecutionContext]]] +[def __Handler__ [@boost:/doc/html/boost_asio/reference/Handler.html ['Handler]]] +[def __IteratorConnectHandler__ [@boost:/doc/html/boost_asio/reference/IteratorConnectHandler.html ['IteratorConnectHandler]]] +[def __MutableBufferSequence__ [@boost:/doc/html/boost_asio/reference/MutableBufferSequence.html ['MutableBufferSequence]]] +[def __Protocol__ [@boost:/doc/html/boost_asio/reference/Protocol.html ['Protocol]]] +[def __RangeConnectHandler__ [@boost:/doc/html/boost_asio/reference/RangeConnectHandler.html ['RangeConnectHandler]]] +[def __ReadHandler__ [@boost:/doc/html/boost_asio/reference/ReadHandler.html ['ReadHandler]]] +[def __SyncReadStream__ [@boost:/doc/html/boost_asio/reference/SyncReadStream.html ['SyncReadStream]]] +[def __SyncWriteStream__ [@boost:/doc/html/boost_asio/reference/SyncWriteStream.html ['SyncWriteStream]]] +[def __WriteHandler__ [@boost:/doc/html/boost_asio/reference/WriteHandler.html ['WriteHandler]]] +[def __DynamicBuffer__v1__ [@boost:/doc/html/boost_asio/reference/DynamicBuffer_v1.html ['DynamicBuffer_v1']]] +[def __DynamicBuffer__v2__ [@boost:/doc/html/boost_asio/reference/DynamicBuffer_v2.html ['DynamicBuffer_v2']]] + +[/ Beast Named Requirements ] + +[def __AsyncStream__ [link beast.concepts.streams.AsyncStream ['AsyncStream]]] +[def __Body__ [link beast.concepts.Body ['Body]]] +[def __BodyReader__ [link beast.concepts.BodyReader ['BodyReader]]] +[def __BodyWriter__ [link beast.concepts.BodyWriter ['BodyWriter]]] +[def __BufferSequence__ [link beast.concepts.BufferSequence ['BufferSequence]]] +[def __BuffersGenerator__ [link beast.concepts.BufferSequence ['BuffersGenerator]]] +[def __DynamicBuffer__ [link beast.concepts.DynamicBuffer ['DynamicBuffer]]] +[def __Fields__ [link beast.concepts.Fields ['Fields]]] +[def __FieldsWriter__ [link beast.concepts.FieldsWriter ['FieldsWriter]]] +[def __File__ [link beast.concepts.File ['File]]] +[def __RatePolicy__ [link beast.concepts.RatePolicy ['RatePolicy]]] +[def __Stream__ [link beast.concepts.streams ['Stream]]] +[def __SyncStream__ [link beast.concepts.streams.SyncStream ['SyncStream]]] + +[/ Beast Identifiers ] + +[def __basic_fields__ [link beast.ref.boost__beast__http__basic_fields `basic_fields`]] +[def __basic_multi_buffer__ [link beast.ref.boost__beast__basic_multi_buffer `basic_multi_buffer`]] +[def __basic_parser__ [link beast.ref.boost__beast__http__basic_parser `basic_parser`]] +[def __bind_handler__ [link beast.ref.boost__beast__bind_handler `bind_handler`]] +[def __buffer_body__ [link beast.ref.boost__beast__http__buffer_body `buffer_body`]] +[def __fields__ [link beast.ref.boost__beast__http__fields `fields`]] +[def __flat_buffer__ [link beast.ref.boost__beast__flat_buffer `flat_buffer`]] +[def __header__ [link beast.ref.boost__beast__http__header `header`]] +[def __message__ [link beast.ref.boost__beast__http__message `message`]] +[def __multi_buffer__ [link beast.ref.boost__beast__multi_buffer `multi_buffer`]] +[def __parser__ [link beast.ref.boost__beast__http__parser `parser`]] +[def __serializer__ [link beast.ref.boost__beast__http__serializer `serializer`]] +[def __flat_static_buffer__ [link beast.ref.boost__beast__flat_static_buffer `flat_static_buffer`]] +[def __flat_static_buffer_base__ [link beast.ref.boost__beast__flat_static_buffer_base `flat_static_buffer_base`]] +[def __websocket_stream__ [link beast.ref.boost__beast__websocket__stream `websocket::stream`]] + +[/ Dingbat Legend] + +[def __new__ [role green \u2605]] +[def __example__ \U0001f4a1] +[def __video__ \U0001f3a6] +[def __report__ \U0001f4cb] +[def __star__ \u2b50] + +[/ + VFALCO unfortunately quickbook wants relative paths and we have no + variables so all of the .cpp and .hpp files are placed here to keep + the paths close to absolute. +] + +[import ../../example/doc/http_examples.hpp] +[import ../../example/echo-op/echo_op.cpp] +[import ../../example/http/client/sync/http_client_sync.cpp] +[import ../../example/websocket/client/sync/websocket_client_sync.cpp] + +[import ../../include/boost/beast/http/basic_file_body.hpp] +[import ../../include/boost/beast/websocket/stream_fwd.hpp] + +[import ../../test/doc/exemplars.cpp] +[import ../../test/doc/core_snippets.cpp] +[import ../../test/doc/http_snippets.cpp] + +[import ../../test/doc/core_1_refresher.cpp] +[import ../../test/doc/core_3_timeouts.cpp] +[import ../../test/doc/core_4_layers.cpp] +[import ../../test/doc/http_10_custom_parser.cpp] +[import ../../test/doc/websocket_common.ipp] +[import ../../test/doc/websocket.cpp] +[import ../../test/doc/websocket_1_connecting.cpp] +[import ../../test/doc/websocket_2_handshaking.cpp] +[import ../../test/doc/websocket_3_decorator.cpp] +[import ../../test/doc/websocket_4_messages.cpp] +[import ../../test/doc/websocket_5_control_frames.cpp] +[import ../../test/doc/websocket_6_timeouts.cpp] +[import ../../test/doc/websocket_7_teardown.cpp] +[import ../../test/doc/websocket_8_notes.cpp] + +[import ../../include/boost/beast/core/detect_ssl.hpp] +[import ../../include/boost/beast/version.hpp] +[import ../../test/beast/core/rate_policy.cpp] + +__new__ indicates a new or updated section in this version. + +__example__ contains example source code. + +__video__ contains video presentation content + +[section:quickref Reference] + +__new__ indicates an item that was recently added. + +[xinclude quickref.xml] +[endsect] +[block'''This Page Intentionally Left Blank 1/2'''] +[section:ref This Page Intentionally Left Blank 2/2] +[include reference.qbk] +[endsect] +[block''''''] + +[include release_notes.qbk] +[include version.qbk] + +[include 01_intro/_intro.qbk] +[include 02_examples/_examples.qbk] +[include 03_core/_core.qbk] +[include 04_http/_http.qbk] +[include 05_http_examples/_http_examples.qbk] +[include 06_websocket/_websocket.qbk] +[include 07_concepts/_concepts.qbk] +[include 08_design/_design.qbk] + +[xinclude index.xml] diff --git a/doc/qbk/release_notes_zh_Hans.qbk b/doc/qbk/release_notes_zh_Hans.qbk new file mode 100644 index 0000000..705cb88 --- /dev/null +++ b/doc/qbk/release_notes_zh_Hans.qbk @@ -0,0 +1,1302 @@ +[/ + Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section Release Notes] + +[/-----------------------------------------------------------------------------] + +[heading Boost 1.91] + +[*Fixes] + +* [issue 3066] Fixed typecast warnings in `inflate_with_eb` + +[*Improvements] + +* [issue 3077] Enforced 8KB sanity limit on chunk headers +* [issue 3085] Made OpenSSL an optional dependency for tests +* [issue 3074] Removed dependency on Boost.StaticAssert +* [issue 3091] Added `HTTP2-Settings` to HTTP field enum + +[heading Boost 1.90] + +[*API Changes] + +* [issue 3042] `http::parser` rejects non-standard trailer fields by default. + ['Actions Required]: + * If your code relies on a non-standard trailer field, consider setting + [link beast.ref.boost__beast__http__parser.merge_all_trailers.overload2 `http::parser::merge_all_trailers`] + after you have validated the `Trailer` header field in the header section of the message. +* [issue 3042] `http::basic_parser` uses a dedicated callback for trailer fields. + ['Actions Required]: + * Custom parsers derived from `http::basic_parser` must override the new virtual function + [link beast.ref.boost__beast__http__basic_parser.on_trailer_field_impl `http::basic_parser::on_trailer_field_impl`] + which is invoked for each field received while parsing the trailer section + of a chunked HTTP message. +* [issue 3042] `http::field` constants are updated. + ['Actions Required]: + * Most removed constants were unrelated to the HTTP protocol. If your code + used one of them, please use the corresponding string literal value. + +[*Fixes] + +* [issue 3034] Fixed allocator move/copy assignment in `flat_buffer` and `multi_buffer` +* [issue 3028] Fixed websocket permessage-deflate error on partial message consumption +* [issue 3032] `http::buffer_body` ignores empty chunks + +[*Improvements] + +* [issue 3039] Added `http::basic_fields::contains` member function +* [issue 3050] Removed dependency on Boost.Preprocessor +* [issue 3048] Removed dependency on Boost.StaticAssert + +[heading Boost 1.89] + +[*Fixes] + +* [issue 3002] Conditionally defined `immediate_executor_type` in `async_base` +* [issue 2999] Used `handshake_timeout` for closing handshake during read operations +* [issue 3003] Added missing `cstdint` header to `detail/cpu_info.hpp` +* [issue 3016] Fixed `std::is_trivial` deprecation warnings +* [issue 3019] Fixed `-Wmaybe-uninitialized` warnings + +[*Improvements] + +* [issue 3005] Replaced `detail/work_guard.hpp` with `net::executor_work_guard` +* [issue 3016] Fixed portability issues for building tests in MinGW + +[*Documentation] + +* [issue 3009] Removed moved sections from documentation +* [issue 3009] Removed superfluous log messages from tests + +[heading Boost 1.88] + +[*Fixes] + +* [issue 2962] Fixed out-of-bounds access in `iequals` function + +[*Improvements] + +* [issue 2974] Updated SSL examples to verify peer certificate hostname +* [issue 2954] Refactored CMakeLists +* [issue 2955] Removed Boost.Scope dependency from examples +* [issue 2716] WebSockets: Peer pings are counted as activity for `idle_timeout` + +[*Documentation] + +* [issue 2918] Added new examples for Unix domain sockets +* [issue 2910] Added SSL/TLS Certificate section to documentation +* [issue 2730] Improved documentation of `websocket::stream::async_close` + +[heading Boost 1.87] + +[*API Changes] + +* [issue 2920] Added `error_code` overload for `basic_fields::insert()` +* [issue 2911] Added overload for `websocket::stream::get_status` to query permessage-deflate status + +[*Fixes] + +* [issue 2926] Fixed use-after-move in calls to `net::dispatch` within `http::basic_stream`, which caused `bad_executor` exceptions on timeouts +* [issue 2915] Removed mutating operations in initiating functions +* [issue 2915] Fixed cancellation handling in `teardown_tcp_op` +* [issue 2920] Set `state_` in `basic_parser` before calling `on_finish_impl` +* [issue 2939] Removed static specifier from `clamp` functions +* [issue 2903] Addressed `-Wattributes` warnings in tests +* [issue 2944] Addressed unreachable code warning in tests + +[*Improvements] + +* [issue 2940] Added forward declaration headers for types in `beast::http` namespace +* [issue 2920] Enabled `http::parser` to use `basic_fields::insert()` with `error_code` overload +* [issue 2920] Applied `header_limit_` in `http::basic_parser` to trailer headers +* [issue 2920] Improved `http::basic_parser` to return `http::error::header_limit` earlier +* [issue 2905] Added support for modular boost build structure + +[heading Boost 1.86] + +[*API Changes] + +* [issue 2878] Added HTTP status code *418 I'm a teapot* + +[*Fixes] + +* [issue 2879] Narrowing conversion in `read_size_hint_db()` +* [issue 2893] Overloads that are ambiguous when using default completion tokens +* [issue 2517] Misplaced static_assert in `http::basic_fields` move-assignment operator +* [issue 2880] Underflow of `bytes_transferred` in WebSocket partial write operations +* [issue 2879] `websocket::stream::read_size_hint()` does not exceed `read_message_max` +* [issue 2877] Various warnings in tests +* [issue 2872] Error handling in SSL shutdown operations in examples +* [issue 2869] Annotate fallthrough case in zlib +* [issue 2866] Handling of expired timers in `basic_stream::ops::transfer_op` +* [issue 2864] Ambiguity in `test::basic_stream` constructor overloads +* [issue 2861] Partial parsing of the final chunk in `http::parser` + +[*Improvements] + +* [issue 2897] Graceful shutdown in `server_flex_awaitable` example +* [issue 2897] Simplified awaitable examples +* [issue 2888] Added fuzzing targets +* [issue 2875] Removed superfluous uses of `std::bind` in some examples +* [issue 2875] `ssl_stream` does not use `flat_stream` + +[*Documentation] + +* [issue 2875] `ssl_stream` and `flat_stream` marked as deprecated +* [issue 2875] `net::ssl::stream` is canonical in snippets and examples +* [issue 2872] Added `SSL/TLS Shutdown Procedure` section + +[heading Boost 1.85] + +[*API Changes] + +* [issue 2811] The status code list has been updated to conform with the IANA registry + +[*Fixes] + +* [issue 2803] Unreachable code warning in `buffers_cat.hpp` +* [issue 2778] Connection error handling in `websocker_server_awaitable` example +* [issue 2739] Concurrent calls to `async_write` in advanced server examples +* [issue 2810] zlib name conflicts with minizip +* [issue 2818] host string should be updated after `SSL_set_tlsext_host_name()` + +[*Improvements] + +* [issue 2782] `asio::associator` is specialized for `bind_wrapper` and `bind_front_wrapper` +* [issue 2646] Add non-allocating overload for error category message function + +[*Documentation] + +* [issue 2789] Specifies when calling `http::message::prepare_payload()` is optional +* [issue 2799] Operations affected by `basic_stream::expires_after()` +* [issue 2808] `teardown()` and `async_teardown()` are customization points +* [issue 2814] Moving or copying `http::serializer` after first usage is undefined behaviour +* [issue 2817] `websocket::permessage_deflate` should be configured before performing the WebSocket handshake +* [issue 2816] `bytes_transferred` in http reads operations reports the number of bytes consumed by the HTTP parser + +[heading Boost 1.84] + +[*API Changes] + +* Remove deprecated allocation and invocation hooks + +[*Features] + +* Support for `immediate_executor` + +[*Fixes] + +* [issue 2766] Use the explicit type std::size_t when completing transfer_op +* [issue 2727] Replaced `BOOST_ASIO_INITFN_RESULT_TYPE` with `BOOST_ASIO_INITFN_AUTO_RES` +* [issue 2715] `server-flex-awaitable` example resets parser + +[*Documentation] + +* [issue 2713] Corrected the `websocket::stream::async_ping/pong` handler requirement +* [issue 2755] Update documentation for `websocket::stream::async_write_some` + +[heading Boost 1.83] + +[*Fixes] + +* [issue 2680] aligned_storage unused for C+23 +* [issue 2653] MSVC literal `not` error +* [issue 2661] ssl_stream ambiguity error on clang +* [issue 2649] Jamefile uses openssl.jam + +[heading Boost 1.82] + +[*Features] + +* [issue 2475] Add `error_code`s use source_location + +[*Fixes] + +* [issue 2602] tcp_stream uses the correct executor of the timer. +* [issue 2638] `std::placeholders` ambiguity fix. + +[*Improvements] + +* error_categories use numeric ids +* `file_body` support seek + + +[heading Boost 1.81] + +[*Features] + +* Add `buffers_generator` +* Add [link beast.ref.boost__beast__http__message_generator `http::message_generator`] +* Add [link beast.ref.boost__beast__buffer_ref `buffer_ref`] +* Support for per-operation cancellation + +[*Fixes] + +* [issue 2439] Fix CVE-2018-25032 in zlib streams +* [issue 264] Websocket support continue in upgrade +* [issue 471] Unquote takes s by reference + +[*Improvements] + +* [issue 2104] C++20 awaitable examples. +* [issue 226], [issue 227] per-message compression options +* [issue 2449] websocket timeout option api +* [issue 2468] multiple content length error + +[*Miscellaneous] + +* Use `span` from Boost.Core +* Use `static_string` from Boost.StaticString +* `serializer::is_done` is `const` +* Support for default-completion and rebind +* [issue 2469] s390x architecture support + +[*Documentation] + +* [issue 891] Feature table for buffers +* [issue 516] Case-insensitivity for fields is stated +* [issue 298] api version is documented + + +[heading Boost 1.80] + +[*Miscellaneous] + +* [issue 2363] Remove `BOOST_BEAST_USE_STD_STRING_VIEW` +* [issue 2417] use boost::core::string_view. This improves inter-conversion between string_view implementations. Some observable differences for users: + * `core::string_view` no longer supports the `.to_string()` or `.clear()` extensions from Utility + * code that relied on `.max_size()` returning `.size(),` needs to be fixed to use `.size()` instead + * `remove_suffix()` and `remove_prefix()` were more lenient than the standard specs; be sure you don't rely on it clamping the argument to valid range + * `BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS` no longer suppresses conversions to `std::string` + + +[heading Boost 1.79] + +[*Fixes] + +* [issue 2391] Add missing include for file_body test. +* [issue 2364] Fix WebSocket handshake response on failure. +* [issue 2280] (related) Fix open append mode for file_posix. +* [issue 2280] Fix open append mode for file_win32. +* [issue 2280] Fix file open with append/append_existing flag on Windows +* [issue 2354] Fix clang-cl UTF8 path handling for `file_win32`. +* [issue 2354] Fix clang-cl UTF8 path handling for `file_stdio`. + +[*Miscellaneous] + +* [issue 2375] Add ARM64 builds to drone CI +* [issue 2217] Fix async_base documentation link +* [issue 2280] Add tests for file open in append/append_existing mode +* [issue 2351] Update CI to include gcc 11, clang 12, msvc 14.3 +* [issue 2350] Add individual tests to CMake workflow + +[heading Boost 1.78] + +[*Fixes] + +* Fix CVE-2016-9840 in zlib implementation. +* Fix TLS SNI handling in websocket_client_async_ssl example. +* [issue 2313] Fix reuse of sliding window in WebSocket permessage_deflate. +* Fix accept error handling in http_server_async example. + +[*Miscellaneous] + +* Remove test framework's dependency on RTTI. +* Move library-specific docca configuration to Beast. +* Remove dependency on RTTI in `test::stream`. +* Fix missing includes in test headers. + + + +[heading Boost 1.77] + +[*Fixes] + +* [issue 2233] Remove use of POSIX-only constant. + +[*Miscellaneous] + +* Fixes to tests. +* Improvements and fixes in Github and Drone CI. +* Accommodate Docca updates. +* Update example root certificates. +* Add example of reading large response body. +* Remove Travis CI. +* Update CMakeLists.txt + + +[heading Boost 1.76] + +[*Fixes] + +* [issue 2139] Add executor rebind to test::stream. +* Fix unused variable compiler warning in WebSocket async shutdown. + +[*Improvements] + +* [issue 2124] Floating point support no longer required to use Beast. +* Reduce size of websockety compiled code by using a common buffers type for all operations. +* HTTP Parser has improved detection of incorrect use. + + +[*Miscellaneous] + +* [issue 2140] Add cxxstd tag to library metadata. +* Move to Drone CI. +* Minor documentation formatting improvements. +* CML now finds required Boost::thread library during in-tree build. + + +[heading Boost 1.75] + +[*Fixes] + +* Eliminate spurious unused parameter warning in `detect_ssl`. +* Update Websocket examples to set the SNI for TLS connections. +* [issue 2023] websocket async_shutdown will now shutdown the underlying TLS transport. +* [issue 2011] File open with append_existing flag now works correctly in posix environments. +* [issue 2039] Windows builds now link to bcrypt as required by the filesystem library. +* [issue 2063] Logic error fixed in `advanced_server_flex` example. +* [issue 1582] Fix unreachable code error on MSVC. +* [issue 2070] Fix http body behaviour when body_limit it none. +* [issue 2065] Fix behaviour of `basic_stream` when a zero-length write is requested. +* [issue 2080] Add enums representing Sec-* HTTP headers. +* [issue 2085] Fix `nullptr` implicit cast on `fields::set()`. +* [issue 2029] Fix C++20 tests for `basic_stream`. + +[*Miscellaneous] + +* Add handler tracking to asynchronous operations: + * Define the preprocessor macro `BOOST_ASIO_ENABLE_HANDLER_TRACKING` to enable Asio handler + tracking in Boost.Beast asynchronous operations. Please see + [@boost:/doc/html/boost_asio/overview/core/handler_tracking.html asio handler tracking] + for details. +* Add Bishop-Fox 2020 Security Assessment. + +[heading Boost 1.74] + +[*API Changes] + +* The API to Asio has undergone changes. Please refer to the Asio release notes for details. + +* Beast has been updated to track and respect developer choices in the use of Asio. In particular: + * Define `BOOST_ASIO_NO_DEPRECATED` to disallow deprecated invocation hooks. + * Define `BOOST_ASIO_NO_TS_EXECUTORS` to ensure that executors conform to the + [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0443r11.html Standard Executors] proposal. + * Define `BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT` to select + [@https://cplusplus.github.io/networking-ts/draft.pdf Networking TS] style executors by default. + If this macro is not defined, Asio default executors will be the + [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0443r11.html Standard Executors] implementation. + +* [issue 1897] Parser `body_limit` is optional (API Change) + ['Actions Required] + * The signature of `basic_parser<>::body_limit(n)` has changed. It now accepts an + optional `std::uint64_t`. The caller may indicate that no body limit is required + by calling `body_limit(boost::none)`. The default limits remain in place in order + to maintain 'safe by default' behaviour. + +* [issue 1934] Remove deprecated interfaces (API Change) + ['Actions Required] + * The macro `BOOST_BEAST_NO_DEPRECATED` will no longer be noticed by Beast. The only way to + enable deprecated functionality is now the macro `BOOST_BEAST_ALLOW_DEPRECATED` which is + undefined by default. That is, all deprecated behaviour is disabled by default. + * The following deprecated functions have been removed: + * `websocket::async_accept_ex` + * `websocket::async_handshake_ex` + * `websocket::accept_ex` + * `websocket::handshake_ex` + Programs still using these names should be refactored to use the `decorator` feature and + the remaining handshake and accept functions. + * `websocket::role_type` has been removed. Users should use `beast::role_type` instead. + * `handler_ptr` has been removed. Users should use `net::bind_handler` and/or + `bind_front_handler` instead. + * Code that depends on `mutable_data_type` should be refactored to use + `mutable_buffers_type`. Classes affected are: + * `buffers_adaptor` + * `flat_buffer` + * `flat_static_buffer` + * `multi_buffer` + * `static_buffer` + * The `reset` function has been removed from `flat_static_buffer`. Use the + `clear` function instead. + * The `core/type_traits.hpp` public header has been removed and along with it + the type trait `is_completion_handler`. Beast uses the CompletionHandler correctness + checks provided by Asio. In a c++20 environment, these convert to concept checks. + * The error code enum `invalid_code_lenths` (sic) was a synonym of `invalid_code_lengths`. + Affected programs should be modified to use `invalid_code_lengths`. + * The file `core/buffers_adapter.hpp` has been removed along with the deprecated + alias typename `buffers_adapter`. Affected programs should use + ` core/buffers_adapator.hpp` and the type `buffers_adaptor`. + +* [issue 1956] Deprecate `string_param` (API Change) + ['Actions Required] + `string_param`, which was previously the argument type when setting field values + has been replaced by `string_view`. Because of this, it is no longer possible to + set message field values directly as integrals. + Users are requied to convert numeric arguments to a string type prior to calling + `fields::set` et. al. + Beast provides the non-allocating `to_static_string()` function for this purpose. + To set Content-Length field manually, call `message::content_length`. + +[*Fixes] + +* [issue 1913] Fix standalone compilation error with `std::string_view` +* [issue 1925] [issue 1916] Fix compile errors on Visual Studio with /std:c++latest +* [issue 1924] Fix c++20 deprecation warning in `span_body` +* [issue 1920] Fix use `buffered_read_stream` with `use_awaitable` +* [issue 1918] Fix `async_detect_ssl` with `use_awaitable` +* [issue 1944] Fix `FILE` namespace qualification +* [issue 1942] Fix http read `bytes_transferred` +* [issue 1943] Fix `basic_stream` `expires_after` +* [issue 1980] Fix `max` compile error +* [issue 1949] `iless` and `iequal` take part in Heterogeneous Lookup + +[*Miscellaneous] + +* [issue 1907] OpenSSL 1.0.2 or later is required when using SSL/TLS streams. + This is a requirement inherited from Boost.Asio. + +* Additional tests have been added to ensure correct integration with C++20 + coroutines when avaialable. + +[heading Boost 1.73] + +[*API Changes] + +* Nested `mutable_data_type` in Beast dynamic buffers is deprecated. Affected types: + * `buffers_adaptor` + * `flat_buffer` + * `flat_static_buffer` + * `multi_buffer` + * `static_buffer` + + +[*Changes Required] + +* Use nested `mutable_buffers_type` instead of `mutable_data_type`, + or define `BOOST_BEAST_ALLOW_DEPRECATED` + +[*Miscellaneous] + +* Update root certificates in examples + +[*Fixes] + +* [issue 1880] Fix Content-Length parsing +* [issue 1852] Fix examples to dispatch to strand +* [issue 1875] Ensure `basic_stream::close` will not throw +* [issue 1863] Field digest is endian-independent +* [issue 1853] Fix ostream flush +* [issue 1831] `flat_buffer::shrink_to_fit` is `noexcept` +* [issue 1828] Fix erase field +* [issue 1822] Examples use strands correctly +* [issue 1818] `file_body` returns `short_read` on eof during read +* [issue 1786] Fix bug in win32 `file_body` +* [issue 1260] Add accessor function to File member of `basic_file_body` +* [issue 793] `file_win32` supports UTF-8 paths +* [issue 793] `file_stdio` supports unicode paths +* [issue 1786] `file_win32` bodies respect `http::serializer::split` +* Correct `buffer_bytes` documentation +* Fix missing include in sha1.hpp +* Fix ostream warning +* Update broken links in README +* Translate some win32 errors to net error codes +* Moved-from dynamic buffers do not clear if different allocator +* Fix compilation macro documentation +* Clarify end-of-file behaviour in `File::read` docs +* ostream_buffer satisfies preconditions of DynamicBuffer_v1::commit +* Fix release build of docs +* Fix `echo-op` test +* Fix non-msvc cmake + +[heading Boost 1.72] + +[*Examples] + +* Add async-ssl-system-executor http client example + +* Add async-ssl-system-executor websocket client example + +[*Features] + +* Async init-fns use the executor's default token + +* Use automatically deduced return types for all async operations (since C++14) + +* Support Concepts for completion token params + +[*Fixes] + +* [issue 1664] Add default dtors to satisfy -Wnon-virtual-dtor + +* [issue 1682] Multiple I/O of the same type is not supported + +* [issue 1687] Fix signed/unsigned mismatch in file_stdio::seek + +* [issue 1688] basic_stream dtor cannot throw + +* [issue 1734] Fix leftovers in basic_parser corner case: + +* [issue 1751] https_get example sends the Host header + +* [issue 1754] Fix async_close error code when async_read times out + +* [issue 1782] root_certificates.hpp is not for production + +* Fix data race in websocket examples + +* Fix data race in http server examples + +* Squelch spurious websocket timer assert + +* Use the executor type in basic_stream timer + +[/-----------------------------------------------------------------------------] + +[heading Boost 1.71] + + + +[*Improvements] + +* [issue 1280] Add 1-element specialization for `buffers_cat` + +* [issue 1556] Set parser status and flags even if body limit has been reached + +* [issue 1567] Relax requirements for vector_body + +* [issue 1568] `detect_ssl` uses `bool` instead of `tribool` + +* [issue 1574] Replace `static_string` in HTTP parser + +* [issue 1606] Use `steady_timer` type + +* [issue 1611] Make chat websocket javascript client more user friendly + +* [issue 1613] Remove redundant use of `static_string` + +* [issue 1636] Improve performance of `http::string_to_verb` + +* Preserve `operation_aborted` on partial message + +* Remove unused `` + +* Reduce the number of instantiations of `filter_token_list` + +* Add idle ping suspend test + +* Remove the use of `bind_executor` in `basic_stream` + +* Remove redundant template in service_base + +* Remove the use of `static_string` from `http::fields` + +* Enable split compilation in http::basic_fields + +* Remove redundant instation of `static_string` in websocket + +* Remove redundant use of `asio::coroutine` in `flat_stream` + +* More split compilation in rfc7230.hpp + +* More split compilation in websocket/detail/mask.hpp + +* Simplify generation of sec-websocket-key + + + + +[*Fixes] + +* [issue 1332] `allocator_traits::construct` is used for user-defined types + +* [issue 1559] Member `get_executor` const-correctness + +* [issue 1569] Fix `async_detect_ssl` handler type + +* [issue 1570] Launder pointers + +* [issue 1578] Fix min/max on MSVC + +* [issue 1586] Fix uninitalized memory use in deflate_stream + +* [issue 1593] Fix UB in websocket close tests + +* [issue 1594] Fix data race in test stream + +* [issue 1599] Fix moved-from executor in idle ping timeout + +* [issue 1607] Remove uses of the deprecated `buffers` function + +* [issue 1612] Remove uses of deprecated methods in websocket tests + +* [issue 1620] Clean up typo in chat websocket javascript client + +* [issue 1621] Fix `flat_buffer` copy members + +* Silence gcc-8 warning + +* Fix `buffers_cat` iterator tests + +* Don't pessimize-move + +* Qualify calls to `beast::iequals` in basic_parser.ipp + +* Fix UB in websocket read tests + +* Simplify websocket::detail::prng + +* Don't over-allocate in http::basic_fields + + + +[*Documentation] + +* Documentation is built with SaxonHE instead of xsltproc + + + +[/-----------------------------------------------------------------------------] + +[heading Boost 1.70] + +[tip + The namespace alias `net` is used throughout for `boost::asio`. +] + +[*New Features] + +* All composed operations use the new + [@boost:/doc/html/boost_asio/reference/async_initiate.html `net::async_initiate`] + internally. + +* New `tcp_stream` and + `basic_stream` + support: + * Timeouts, + [link beast.ref.boost__beast__basic_stream.async_read_some `async_read_some`], + [link beast.ref.boost__beast__basic_stream.async_write_some `async_write_some`] + complete with + [link beast.ref.boost__beast__error `error::timeout`] + on expiration. + * Traffic-shaping policies + [link beast.ref.boost__beast__simple_rate_policy `simple`] and + [link beast.ref.boost__beast__unlimited_rate_policy `unlimited`], + or a user-defined + [link beast.concepts.RatePolicy ['RatePolicy]]. + * Supports + [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1322r0.html P1322R0]. + +* `websocket::stream` + supports + * Configurable handshake timeout + * Configurable idle timeout + * Automatic idle pings + +* [link beast.ref.boost__beast__ssl_stream `ssl_stream`] + is a public interface + +* ([issue 1305]) Better + `flat_buffer`, + `flat_static_buffer`, + `multi_buffer`, and + `static_buffer`: + * Revise all reference documentation + * Move construction does not always invalidate buffers + * non-const `data()` returns a mutable buffer sequence + * Add `cdata()` to also return constant readable bytes + * Eligible member functions are declared `noexcept` + +* ([issue 1345]) Better + `flat_buffer`, + `multi_buffer` + * Add `clear`, `reserve()`, `max_size()`, `shrink_to_fit()` + * Respect Allocator `max_size()` + * Specify exception safety + +* ([issue 1384]) New functions + `bind_front_handler` + +* Better + `static_buffer`, + `flat_static_buffer` + * Add `clear()` + * More members are `noexcept` + * Specify exception safety + +* Faster + `http::string_to_field` + +* Dynamic buffer `clear` operations perserve capacity. + +* New file + * New variadic `is_const_buffer_sequence` + * New variadic `is_mutable_buffer_sequence` + * New trait `buffers_iterator_type` + * New trait `buffers_type` + +* New classes + `async_base`, + `stable_async_base` + * Handle boilerplate for writing composed operations + * New + `allocate_stable` + is preferred over `handler_ptr` + +* New + `buffer_bytes` + replacement for `net::buffer_size` + +* New: + * `saved_handler` + * `buffers_range_ref` + * `executor_type` + * `get_lowest_layer`, + `lowest_layer_type` + * `close_socket`, + `beast_close_socket` + * `error`, + `condition` + +* These interfaces are now public (were experimental): + [link beast.ref.boost__beast__flat_stream `flat_stream`], + [link beast.ref.boost__beast__detect_ssl `detect_ssl`], + [link beast.ref.boost__beast__async_detect_ssl `async_detect_ssl`]. + +* Websocket streams use PCG as the fast random number generator, + for increased security. + + + +[*Documentation] + +* WebSocket reference documentation is revised + +* Updated [link beast.using_io.asio_refresher Networking Refresher] + +* Revised [link beast.using_io.writing_composed_operations.echo Asynchronous Echo] + +* Rewritten [link beast.using_io.writing_composed_operations.detect_ssl [*Detect SSL Handshake]] + + + +[*API Changes] + +* The __Fields__ concept is deprecated and will be removed + in a future version. ['Actions Required]: Do not rely on + the ['Fields] concept. + +* `handler_ptr` is deprecated. ['Actions Required]: Use + `stable_async_base` and + `allocate_stable` + instead. + +* On Windows, Visual Studio 2017 or later is required + +* OpenSSL is required to build the examples and tests + +* HTTP stream algorithms return the number of bytes transferred + from the stream. Previously, they returned the number of bytes + consumed by the parser. + ['Actions Required]: + * Callers depending on the return value of + `http::read` or + `http::async_read` + overloads should adjust the usage of + the returned value as needed. + +* Metafunctions + `has_get_executor`, + `is_sync_stream`, + `is_sync_read_stream`, + `is_sync_write_stream`, + `is_async_stream`, + `is_async_read_stream`, and + `is_async_write_stream` + are in stream_traits.hpp. + ['Actions Required]: Include stream_traits.hpp as needed. + +* `basic_parser` + is abstract. + ['Actions Required] + * Change uses of the `basic_parser` type to omit the `Derived` + template parameter + * Classes derived from `basic_parser` no longer need to friend + the base. + * Virtual functions in the derived class may be marked `override`. + +* Metafunction + `is_file` + is in file_base.hpp. + ['Actions Required]: Include file_base.hpp as needed. + +* `flat_static_buffer::reset()` + is deprecated. + ['Actions Required]: + * call + `clear()` instead. + +* `buffers_adapter` is spelled + `buffers_adaptor`. + ['Actions Required]: + * Replace `buffers_adapter` with + `buffers_adaptor`, + or define `BOOST_BEAST_ALLOW_DEPRECATED`. + +* `buffers` is spelled + `make_printable`. + ['Actions Required]: + * Replace `buffers` with + `make_printable`, + and include "make_printable.hpp" instead of "ostream.hpp". + +* `file_mode::append_new` is removed, as it makes no sense. + ['Actions Required]: + * Replace `file_mode::append_new` with either + `file_mode::append` or + `file_mode::append_existing` + as needed. + +* `role_type` is moved from `websocket` to `beast` + +* `buffers_range_ref` + is preferred to `std::reference_wrapper`. + ['Actions Required]: + * Call + `buffers_range_ref` + with the buffer, instead of calling + `buffers_range` + with a reference wrapper constructed from the buffer. + +* Nested `lowest_layer` and `lowest_layer_type` are removed. + ['Actions Required]: Use the free function + `get_lowest_layer` and the + type trait + `lowest_layer_type` instead. + +* WebSocket decorator is a socket option: + * Overloads of the following functions which accept a Decorator + are deprecated: + * `accept`, `accept_ex` + * `handshake`, `handshake_ex` + * `async_accept`, `async_accept_ex` + * `async_handshake`, `async_handshake_ex` + +* ([issue 1375]) The value returned from `basic_parser::content_length` + no longer changes as the body of the message is received. + ['Actions Required]: Call `basic_parser::content_length_remaining` instead + of `basic_parser::content_length` in order to determine the remaining + number of bytes in the body. + + +[*Examples] + +* All example programs are updated: + * Use + `tcp_stream` + with timeouts (HTTP) + * Use + `ssl_stream` + * Set timeouts for WebSocket streams. + * Use + `bind_front_handler` + +* ([issue 1100]) http-crawl clears the response before each read + +* ([issue 1347]) echo-op is rewritten + +* ([issue 1401]) Examples use + `flat_buffer` + +* Advanced servers use HTTP parser interfaces for reading + +* detect-ssl is rewritten + +* New example [path_link example/websocket/server/chat-multi example/websocket/server/chat-multi] + +* `async_echo` works with move-only handlers + +* cppcon2018 example is removed + + + +[*Fixes] + +* ([issue 38]) Better treatment of SSL short reads + +* ([issue 1223]) HTTP read counts bytes correctly when an error occurs + +* ([issue 1247]) Update `ssl_stream` + for Asio changes + +* ([issue 1279]) Enable explicit instantiations of + `websocket::stream` + +* ([issue 1290]) Don't use deprecated Asio interfaces + +* ([issue 1306]) `http::message` + is not-a `boost::empty_value` + +* ([issue 1306]) `test::stream` + has fewer dependencies + +* ([issue 1358]) Destroy abandoned websocket ops on shutdown + +* ([issue 1365]) Handler wrappers decay parameters sooner + +* ([issue 1408]) `session_alloc` + is thread-safe + +* ([issue 1414]) Boost.System is header-only + +* ([issue 1418]) `test::stream` + maintains a handler work guard + +* ([issue 1445]) Fix posix_file::close handling of EINTR + +* ([issue 1460]) Large WebSocket Upgrade response no longer overflows + +* Reusing an HTTP parser returns an error + +* Handler bind wrappers use the associated allocator + +* `buffers_cat` + correctly skips empty buffers when iterated + +* `ostream` + does not overflow or exceed the dynamic buffer's maximum size + +* Fixes to + `test::stream::async_read` + +* `file_mode::append_existing` + works correctly + +* A handler work guard is maintained on paused websocket operations + +* All behavior of default-constructed iterators is conforming + +[/-----------------------------------------------------------------------------] + +[heading Boost 1.69] + +[*New Videos] + +[block''' + + + + + +'''] + +[*New Features] + +* ([issue 1133]) Add `BOOST_BEAST_USE_STD_STRING_VIEW` + +[*Examples] + +* New WebSocket server and browser-based client: example/cppcon2018 + +[*Fixes] + +* ([issue 1245]) Fix a rare case of incorrect UTF8 validation + +* ([issue 1237]) Verify certificates in client examples + +* ([issue 1233]) Use [@boost:/doc/html/core/empty_value.html `boost::empty_value`] + +* ([issue 1091]) Fix timer on websocket upgrade in examples + +* ([issue 1270]) [link beast.ref.boost__beast__http__basic_fields `basic_fields`] uses intrusive base hooks + +* ([issue 1267]) Fix parsing of out-of-bounds hex values + +* ([issue 1263]) Fix uninitialized comparison in buffers iterator + +* ([issue 1288]) Remove extraneous strand from example + +* Workaround for http-server-fast and libstdc++ + +* Partial support for `BOOST_NO_EXCEPTIONS` + +[*Experimental] + +* Add `timeout_socket` + + + + +[heading Boost 1.68] + +This version fixes a missing executor work guard in all composed operations +used in the implementation. Users who are experiencing crashes related to +asynchronous completion handlers are encouraged to upgrade. Also included +is an improved mechanism for generating random numbers used to mask outgoing +websocket frames when operating in the client mode. This resolves a +vulnerability described in the Beast Hybrid Assessment Report from Bishop Fox. + +[*New Features] + +The include directory `` contains features which are not +part of the stable public interface but are available anyway. They may change +in future versions. + +* ([issue 1108]) New [link beast.ref.boost__beast__flat_stream `flat_stream`] for working around an SSL stream performance limitation + +* ([issue 1151], [issue 595]) New [link beast.ref.boost__beast__http__icy_stream `http::icy_stream`] stream filter allows parsing ICY HTTP response handshakes + +* New [link beast.ref.boost__beast__ssl_stream `ssl_stream`] for better SSL performance and move constructability + +* New + [link beast.ref.boost__beast__test__error `test::connect`], + [link beast.ref.boost__beast__test__error `test::error`], + [link beast.ref.boost__beast__test__error `test::fail_count`], and + [link beast.ref.boost__beast__test__error `test::stream`] utilities for writing unit tests. + +* New [link beast.ref.boost__beast__http__is_mutable_body_writer `http::is_mutable_body_writer`] metafunction + +* New [link beast.ref.boost__beast__websocket__seed_prng `websocket::seed_prng`] for manually providing entropy to the PRNG + +* New [link beast.ref.boost__beast__websocket__stream.secure_prng `websocket::stream::secure_prng`] to control whether the connection uses a secure PRNG + +[*Improvements] + +* Generated WebSocket masks use a secure PRNG by default + +* Improvements to [link beast.ref.boost__beast__buffers_adaptor `buffers_adaptor`] + +* ([issue 1188]) Set "/permissive-" for MSVC builds + +* ([issue 1109]) Use a shared string for example HTTP server doc roots + +* ([issue 1079]) Add `handler_ptr::has_value` + +[*Fixes] + +* ([issue 1073]) Fix race in advanced server examples + +* ([issue 1076]) Use executor_work_guard in composed operations + +* ([issue 1079]) Remove spurious assert + +* ([issue 1113]) Add `const` and non-`const` overloads for message based HTTP writes + +* ([issue 1119]) Fix unused variable warning + +* ([issue 1121]) Examples use the root certificate which matches the fingerprint + +* ([issue 1141]) Tidy up composed operation doc + +* ([issue 1186]) Check error in example set_option + +* ([issue 1210]) Fix http_server_stackless_ssl.cpp example + +* ([issue 1211]) Fix parse_dec algorithm + +* ([issue 1214]) Silence ubsan false positive + +* Tidy up websocket stream javadocs + +* Fix move-only arguments in [link beast.ref.boost__beast__bind_handler `bind_handler`] + +* Fix [link beast.ref.boost__beast__http__parser `http::parser`] constructor javadoc + +* Fix [link beast.ref.boost__beast__buffers_adaptor `buffers_adaptor`] iterator value type + +* Fix [link beast.ref.boost__beast__buffers_adaptor.max_size `buffers_adaptor::max_size`] + +* Fix [link beast.ref.boost__beast__buffers_prefix `buffers_prefix`] iterator decrement + +* Fix __Fields__, __FieldsWriter__ concept docs + +* Fix __BodyReader__ constructor requirements doc + +[*Breaking Changes] + +* Remove deprecated `serializer::reader_impl` + +* Remove deprecated __Body__ `reader` and `writer` ctor signatures + + + + + +[heading Boost 1.67] + +This version fixes significant defects in +[link beast.ref.boost__beast__websocket__stream `websocket::stream`] +which can lead to asserts or undefined behavior. Users are encouraged +to update to the latest Boost release. + +[*New Features] + +* Move-only completion handlers are supported throughout the library + +* ([issue 899]) Advanced server examples support idle websocket pings and timeouts + +* ([issue 849]) WebSocket permessage-deflate support is now a compile-time + feature. This adds an additional `bool` template parameter to + [link beast.ref.boost__beast__websocket__stream `websocket::stream`] + When `deflateSupported` is `true`, the stream will be capable of + negotiating the permessage-deflate websocket extension per the + configured run-time settings. + When `deflateSupported` is `false`, the stream will never negotiate + the permessage-deflate websocket extension. Furthermore, all of the + code necessary for implementing the permessage-deflate extension + will be excluded from function instantiations. Programs which set + `deflateSupported` to `false` when instantiating streams will be smaller. + +* ([issue 949]) WebSocket error codes are revised. New + [link beast.ref.boost__beast__websocket__error error codes] + are added for more fine-grained failure outcomes. Messages for error + codes are more verbose to help pinpoint the problem. Error codes are + now also mapped to newly added + [link beast.ref.boost__beast__websocket__condition error conditions] + to simplify comparisons. The error codes `websocket::error::failed` + and `websocket::error::handshake_failed` are removed. + Actions required: + Code which explicitly compares `error_code` values against + the constant `websocket::error::handshake_failed` should compare + against + [link beast.ref.boost__beast__websocket__condition `websocket::condition::handshake_failed`] + instead. + Code which explicitly compares error_code values against the + constant `websocket::error::failed` should compare + against + [link beast.ref.boost__beast__websocket__condition `websocket::condition::protocol_violation`] + instead. + +[*Improvements] + +* ([issue 857]) + [link beast.ref.boost__beast__http__basic_fields `http::basic_fields`] + uses less storage + +* ([issue 894]) + [link beast.ref.boost__beast__http__basic_fields `http::basic_fields`] + exception specifiers are provided + +* Implementation no longer uses deprecated `asio::null_buffers` + +* Add [include_file boost/beast/websocket/stream_fwd.hpp] + +* ([issue 955]) The asynchronous SSL detector example uses a stackless coroutine + +* [link beast.ref.boost__beast__bind_handler `bind_handler`] + works with boost placeholders + +* Examples set `reuse_address(true)` + +* ([issue 1026]) Advanced servers support clean shutdown via SIGINT or SIGTERM + +* Some basic_fields operations now give the strong exception guarantee + +[*Fixes] + +* Fix "warning: ‘const’ type qualifier on return type has no effect" + +* ([issue 916]) Tidy up `ssl_stream` special members + +* ([issue 918]) Calls to `` are protected from macros + +* ([issue 954]) The control callback is invoked on the proper executor + +* ([issue 994]) Fix iterator version of + [link beast.ref.boost__beast__http__basic_fields.erase.overload1 `http::basic_fields::erase`] + +* ([issue 992]) Fix use-after-move in example request handlers + +* ([issue 988]) Type check completion handlers + +* ([issue 985]) Tidy up + [link beast.ref.boost__beast__bind_handler `bind_handler`] + doc + +* Fix memory leak in advanced server examples + +* ([issue 1000]) Fix soft-mutex assert in websocket stream. + This resolves the assert `"ws_.wr_block_ == tok_"`. + +* ([issue 1019]) Fix fallthrough warnings + +* ([issue 1024]) Fix teardown for TIME_WAIT + +* ([issue 1030]) Fix big-endian websocket masking + +* Safe treatment of zero-length string arguments in basic_fields + +* ([issue 1043]) Examples clear the HTTP message before reading + +* ([issue 1012]) Add asio_handler_invoke overloads for stream algorithms + +* Add Access-Control-Expose-Headers field constant + +[*API Changes] + +* Remove unintended public members of + `handler_ptr`. + Actions required: don't call non-public members. + +* `handler_ptr` + is a move-only type, with `unique_ptr` semantics. + Actions required: user-defined composed operations using `handler_ptr` + to manage state can only be moved, not copied. + +* `handler_ptr` + gives the strong exception guarantee. The constructor signature + for managed objects constructed by `handler_ptr` now receives a + `const` reference to the handler. Actions required: Change the + constructor signature for state objects used with `handler_ptr` + to receive a `const` reference to the handler. + +* ([issue 896]) + [link beast.ref.boost__beast__http__basic_fields `http::basic_fields`] + does not support fancy pointers + +* [link beast.ref.boost__beast__http__parser `http::parser`] + is no longer [*MoveConstructible] + +* ([issue 930]) `http::serializer::reader_impl` is deprecated and will + be removed in the next release. Actions required: Call + [link beast.ref.boost__beast__http__serializer.writer_impl `http::serializer::writer_impl`] + instead of `serializer::reader_impl`. + +* ([issue 884]) The __BodyReader__ and __BodyWriter__ concept constructor + requirements have changed. They now require the header and body + elements to be passed as distinct + [link beast.ref.boost__beast__http__header `http::header`] + and `value_type` objects. This enables the composition of body types. + The previous single-argument constructors are deprecated and will be + removed in the next version. + Actions required: Change user-defined instances of __BodyReader__ or + __BodyWriter__ constructor signatures to the two-argument form. + Alternatively. define the macro `BOOST_BEAST_ALLOW_DEPRECATED` in + the project (which will cause both the new and the deprecated + signatures to be accepted). + +* [link beast.ref.boost__beast__websocket__stream.control_callback `websocket::stream::control_callback`] + now copies or moves the function object. + +* ([issue 1014]) DynamicBuffer input areas are not mutable. + Actions required: do not attempt to write to input areas of dynamic + buffers. + +* ([issue 941]) `get_lowest_layer` is now a type alias. + Actions required: Replace instances of `typename get_lowest_layer::type` + with `get_lowest_layer`. + +[heading Boost 1.66] + +* Initial release + +[endsect] diff --git a/doc/qbk/version_zh_Hans.qbk b/doc/qbk/version_zh_Hans.qbk new file mode 100644 index 0000000..29c9e9e --- /dev/null +++ b/doc/qbk/version_zh_Hans.qbk @@ -0,0 +1,21 @@ + [/ + Copyright (c) 2022 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + Official repository: https://github.com/boostorg/beast +] + +[section Beast API Version] + +Beast maintains it's own API version, which is more fine-grained than the +boost release. + +It can be obtained as a string from the `BOOST_BEAST_VERSION` macro +or a string through `BOOST_BEAST_VERSION_STRING`. + +[version] + + +[endsect]