@@ -155,6 +155,15 @@ And that the following typedef's have been put in place:
155155 struct handler_type;
156156 typedef boost::network::http: :server<handler_type> http_server;
157157
158+ struct handler_type {
159+ void operator()(
160+ http_server::request const & request,
161+ http_server::response & response
162+ ) {
163+ // do something here
164+ }
165+ };
166+
158167Constructor
159168```````````
160169
@@ -183,17 +192,281 @@ instance has been constructed in the following manner:
183192 boost::thread t1(boost::bind(&http_server::run, &server));
184193 boost::thread t2(boost::bind(&http_server::run, &server));
185194 server.run();
195+ t1.join();
196+ t2.join();
186197
187198``server.stop() ``
188199 Stop the HTTP Server acceptor and wait for all pending requests to finish.
189200
201+ Response Object
202+ ```````````````
203+
204+ The response object has its own public member functions which can be very
205+ helpful in certain simple situations.
206+
207+ ``response = http_server::response::stock_reply(status, body) ``
208+ Code like the above should go inside the handler's ``operator() `` overload.
209+ The body parameter is an ``std::string ``. The status parameter is any of
210+ the following values from the ``http_server::response `` enum
211+ ``status_type ``:
212+
213+ ..code-block ::c++
214+
215+ enum status_type {
216+ ok = 200,
217+ created = 201,
218+ accepted = 202,
219+ no_content = 204,
220+ multiple_choices = 300,
221+ moved_permanently = 301,
222+ moved_temporarily = 302,
223+ not_modified = 304,
224+ bad_request = 400,
225+ unauthorized = 401,
226+ forbidden = 403,
227+ not_found = 404,
228+ not_supported = 405,
229+ not_acceptable = 406,
230+ internal_server_error = 500,
231+ not_implemented = 501,
232+ bad_gateway = 502,
233+ service_unavailable = 503
234+ };
235+
236+ The response object also has the following publicly accessible member values
237+ which can be directly manipulated by the handler.
238+
239+ +------------------+----------------------+------------------------------------+
240+ | Member Name| Type| Description|
241+ +==================+======================+====================================+
242+ | status| ``status_type ``| The HTTP status of the response.|
243+ +------------------+----------------------+------------------------------------+
244+ | headers| ``vector<header> ``| Vector of headers. [# ]_|
245+ +------------------+----------------------+------------------------------------+
246+ | content| ``string_type `` [# ]_| The contents of the response.|
247+ +------------------+----------------------+------------------------------------+
248+
249+ .. [# ]A header is a struct of type
250+ ``response_header<http::tags::http_server> ``. An instance always has the
251+ members ``name `` and ``value `` both of which are of type ``string_type ``.
252+ .. [# ]``string_type `` is
253+ ``boost::network::string<http::tags::http_server>::type ``.
254+
190255 Asynchronous Servers
191256--------------------
192257
193- .. FIXME show the table of tags that enable the asynchronous implementation.
258+ The asynchronous server implementation is significantly different to the
259+ synchronous server implementation in three ways:
260+
261+ #. **The Handler instance is invoked asynchronously **. This means the I/O
262+ thread used to handle network-related events are free to handle only the
263+ I/O related events. This enables the server to scale better as to the
264+ number of concurrent connections it can handle.
265+ #. **The Handler is able to schedule asynchronous actions on the thread pool
266+ associated with the server. ** This allows handlers to perform multiple
267+ asynchronous computations that later on perform writes to the connection.
268+ #. **The Handler is able to control the (asynchronous) writes to and reads from
269+ the HTTP connection. ** Because the connection is available to the Handler,
270+ that means it can write out chunks of data at a time or stream data through
271+ the connection continuously.
272+
273+ The asynchronous server is meant to allow for better scalability in terms of the
274+ number of concurrent connections and for performing asynchronous actions within
275+ the handlers. If your applacation does not need to write out information
276+ asynchronously or perform potentially long computations, then the synchronous
277+ server gives a generally better performance profile than the asynchronous
278+ server.
279+
280+ The asynchronous server implementation is available from a single user-facing
281+ template named ``async_server ``. This template takes in a single template
282+ parameter which is the type of the Handler to be called once a request has been
283+ parsed from a connection.
284+
285+ An instance of Handler is taken as a reference to the constructor similar to the
286+ synchronous server implementation.
287+
288+ ..warning ::The asynchronous server implementation, like the synchronous server
289+ implementation, does not perform any synchronization on the calls to the
290+ Handler invocation. This means if your handler contains or maintains internal
291+ state, you are responsible for implementing your own synchronization on
292+ accesses to the internal state of the Handler.
293+
294+ The general pattern for using the ``async_server `` template is shown below:
295+
296+ ..code-block ::c++
297+
298+ struct handler;
299+ typedef boost::network::http: :async_server<handler> http_server;
300+
301+ struct handler {
302+ void operator()(
303+ http_server::request const & req,
304+ http_server::connection_ptr connection
305+ ) {
306+ // handle the request here, and use the connection to
307+ // either read more data or write data out to the client
308+ }
309+ };
194310
195311API Documentation
196312~~~~~~~~~~~~~~~~~
197313
198- .. FIXME show the table of publicly-accessible member functions.
314+ The following sections assume that the following file has been included:
315+
316+ ..code-block ::c++
317+
318+ #include <boost/network/include/http/server.hpp>
319+ #include <boost/network/utils/thread_pool.hpp>
320+
321+ And that the following typedef's have been put in place:
322+
323+ ..code-block ::c++
324+
325+ struct handler_type;
326+ typedef boost::network::http: :server<handler_type> http_server;
327+
328+ struct handler_type {
329+ void operator()(
330+ http_server::request const & request,
331+ http_server::connection_ptr connection
332+ ) {
333+ // do something here
334+ }
335+ };
336+
337+ Constructor
338+ ```````````
339+
340+ ``http_server(address, port, handler, thread_pool) ``
341+ Construct an HTTP Server instance, passing in the address and port as
342+ ``std::string const & `` and handler being of type ``handler_type `` but
343+ passed in as an lvalue reference. The ``thread_pool `` parameter is an
344+ instance of ``boost::network::utils::thread_pool `` that has been previously
345+ instantiated.
346+
347+ ..note ::The ``boost::network::utils::thread_pool`` has a single constructor
348+ parameter which is the number of threads to run the thread pool.
349+
350+ Public Members
351+ ``````````````
352+
353+ The following definitions assume that a properly constructed ``http_server ``
354+ instance has been constructed in the following manner:
355+
356+ ..code-block ::c++
357+
358+ handler_type handler;
359+ boost::network::utils: :thread_pool thread_pool(2);
360+ http_server server("127.0.0.1", "8000", handler, thread_pool);
361+
362+ ``server.run() ``
363+ Run the HTTP Server event loop. This function can be run on multiple threads
364+ following the example:
365+
366+ ..code-block ::c++
367+
368+ boost::thread t1(boost::bind(&http_server::run, &server));
369+ boost::thread t2(boost::bind(&http_server::run, &server));
370+ server.run();
371+ t1.join();
372+ t2.join();
373+
374+ ``server.stop() ``
375+ Stop the HTTP Server acceptor and wait for all pending requests to finish.
376+
377+ Connection Object
378+ `````````````````
379+
380+ The connection object has its own public member functions which will be the
381+ primary means for reading from and writing to the connection.
382+
383+ ``template <class Range> write(Range range) ``
384+ The connection object exposes a function ``write `` that can be given a
385+ parameter that adheres to theBoost.Range _ ``Single Pass Range `` Concept.
386+ The write function, although it looks synchronous, starts of a series of
387+ asynchronous writes to the connection as soon as the range is serialized to
388+ appropriately sized buffers.
389+
390+ To use this in your handler, it would look something like this:
391+
392+ ..code-block ::c++
393+
394+ connection->write("Hello, world!");
395+ std::string sample = "I have a string!";
396+ connection->write(sample);
397+
398+ ``template <class Range, class Callback> void write(Range range, Callback callback) ``
399+ The connection object also exposes a function ``write `` that can be given a
400+ parameter that adheres to theBoost.Range _ ``Single Pass Range `` Concept, as
401+ well as a Callback function that returns ``void `` and takes a
402+ ``boost::system::error_code `` as a parameter. This overload of ``write `` is
403+ useful for writing streaming applications that send out chunks of data at a
404+ time, or for writing data that may not all fit in memory right away.
405+
406+ ``template <class ReadCallback> void read(ReadCallback callback) ``
407+ The connection object has a function ``read `` which can be used to read more
408+ information from the connection. This ``read `` function takes in a callback
409+ that can be assigned to aBoost.Function _ with the signature
410+ ``void(input_range,error_code,size_t,connection_ptr) ``. The following list
411+ shows what the types actually mean:
412+
413+ * **input_range ** -- ``boost::iterator_range<char const *> `` : The range
414+ that denotes the data read from the connection.
415+ * **error_code ** -- ``boost::system::error_code `` : The error code if
416+ there were any errors encountered from the read.
417+ * **size_t ** -- ``std::size_t `` : The number of bytes transferred.
418+ * **connection_ptr ** -- ``http_server::connection_ptr `` : A handle to the
419+ current connection, so that it is kept alive at the time of the read
420+ callback invocation.
421+
422+ This interface is useful when doing reads of uploaded data that can be
423+ potentially large and may not fit in memory. The read handler is then
424+ responsible for dealing with the chunks of data available from the
425+ connection.
426+
427+ ``void set_status(status_t new_status) ``
428+ The ``set_status `` function takes a parameter of type ``status_t `` which is
429+ an enum type nested in ``http_status::connection `` which is given in the
430+ following code listing.
431+
432+ ..code-block ::c++
433+
434+ enum status_t {
435+ ok = 200
436+ , created = 201
437+ , accepted = 202
438+ , no_content = 204
439+ , multiple_choices = 300
440+ , moved_permanently = 301
441+ , moved_temporarily = 302
442+ , not_modified = 304
443+ , bad_request = 400
444+ , unauthorized = 401
445+ , forbidden = 403
446+ , not_found = 404
447+ , not_supported = 405
448+ , not_acceptable = 406
449+ , internal_server_error = 500
450+ , not_implemented = 501
451+ , bad_gateway = 502
452+ , service_unavailable = 503
453+ };
454+
455+ ..note ::You may set and re-set the status several times as long as you have
456+ not set the headers or sent data through the connection. If you do this after
457+ data has already been set, the function will throw an instance of
458+ ``std::logic_error ``.
459+
460+ ``template <class Range> void set_headers(Range range) ``
461+ The ``set_headers `` function takes a Single Pass Range of
462+ ``boost::network::http::response_header<http::tags::http_async_server> ``
463+ instances and linearizes them to a buffer with at most
464+ ``BOOST_NETWORK_HTTP_SERVER_CONNECTION_HEADER_BUFFER_MAX_SIZE `` and
465+ immediately schedules an asynchronous write once that is done.
466+
467+ The function throws an instance of ``std::logic_error `` if you try to set
468+ the headers for a connection more than once.
469+
199470
471+ .. _Boost.Range :http://www.boost.org/libs/range
472+ .. _Boost.Function :http://www.boost.org/libs/function