1[/ 2 Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) 3 4 Distributed under the Boost Software License, Version 1.0. (See accompanying 5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 7 Official repository: https://github.com/boostorg/beast 8] 9 10[section Custom Body Types] 11[block'''<?dbhtml stop-chunking?>'''] 12 13User-defined types are possible for the message body, where the type meets the 14__Body__ requirements. This simplified class declaration 15shows the customization points available to user-defined body types: 16``` 17/// Defines a Body type 18struct body 19{ 20 /// This determines the return type of the `message::body` member function 21 using value_type = ...; 22 23 /// An optional function, returns the body's payload size (which may be zero) 24 static 25 std::uint64_t 26 size(value_type const& v); 27 28 /// The algorithm used for extracting buffers 29 class reader; 30 31 /// The algorithm used for inserting buffers 32 class writer; 33} 34``` 35 36The meaning of the nested types is as follows 37 38[table Body Type Members 39[[Name][Description]] 40[ 41 [`value_type`] 42 [ 43 Determines the type of the 44 [link beast.ref.boost__beast__http__message.body `message::body`] 45 member. 46 ] 47][ 48 [`reader`] 49 [ 50 An optional nested type meeting the requirements of __BodyReader__, 51 which provides the algorithm for storing a forward range of buffer 52 sequences in the body representation. 53 If present, this body type may be used with a __parser__. 54 ] 55][ 56 [`writer`] 57 [ 58 An optional nested type meeting the requirements of __BodyWriter__, 59 which provides the algorithm for converting the body representation 60 to a forward range of buffer sequences. 61 If present this body type may be used with a __serializer__. 62 ] 63] 64] 65 66[heading Value Type] 67 68The `value_type` nested type allows the body to define the declaration of 69the body type as it appears in the message. This can be any type. For 70example, a body's value type may specify `std::vector<char>` or 71`std::list<std::string>`. A custom body may even set the value type to 72something that is not a container for body octets, such as a 73[@boost:/libs/filesystem/doc/reference.html#class-path `boost::filesystem::path`]. 74Or, a more structured container may be chosen. This declares a body's 75value type as a JSON tree structure produced from a 76[@boost:/doc/html/property_tree/parsers.html#property_tree.parsers.json_parser `boost::property_tree::json_parser`]: 77``` 78#include <boost/property_tree/ptree.hpp> 79#include <boost/property_tree/json_parser.hpp> 80 81struct Body 82{ 83 using value_type = boost::property_tree::ptree; 84 85 class reader 86 class writer; 87}; 88``` 89 90As long as a suitable reader or writer is available to provide the 91algorithm for transferring buffers in and out of the value type, 92those bodies may be parsed or serialized. 93 94 95 96[section:file_body File Body __example__] 97 98Use of the flexible __Body__ concept customization point enables authors to 99preserve the self-contained nature of the __message__ object while allowing 100domain specific behaviors. Common operations for HTTP servers include sending 101responses which deliver file contents, and allowing for file uploads. In this 102example we build the 103[link beast.ref.boost__beast__http__basic_file_body `basic_file_body`] 104type which supports both reading and 105writing to a file on the file system. The interface is a class templated 106on the type of file used to access the file system, which must meet the 107requirements of __File__. 108 109First we declare the type with its nested types: 110 111[example_http_file_body_1] 112 113We will start with the definition of the `value_type`. Our strategy 114will be to store the file object directly in the message container 115through the `value_type` field. To use this body it will be necessary 116to call `msg.body.file().open()` first with the required information 117such as the path and open mode. This ensures that the file exists 118throughout the operation and prevent the race condition where the 119file is removed from the file system in between calls. 120 121[example_http_file_body_2] 122 123Our implementation of __BodyWriter__ will contain a small buffer 124from which the file contents are read. The buffer is provided to 125the implementation on each call until everything has been read in. 126 127[example_http_file_body_3] 128 129And here are the definitions for the functions we have declared: 130 131[example_http_file_body_4] 132 133Files can be read now, and the next step is to allow writing to files 134by implementing the __BodyReader__. The style is similar to the writer, 135except that buffers are incoming instead of outgoing. Here's the 136declaration: 137 138[example_http_file_body_5] 139 140Finally, here is the implementation of the reader member functions: 141 142[example_http_file_body_6] 143 144We have created a full featured body type capable of reading and 145writing files on the filesystem, integrating seamlessly with the 146HTTP algorithms and message container. The body type works with 147any file implementation meeting the requirements of __File__ so 148it may be transparently used with solutions optimized for particular 149platforms. Example HTTP servers which use file bodies are available 150in the example directory. 151 152[endsect] 153 154 155 156[endsect] 157