Skip to content

Commit 1014405

Browse files
committed
Final installment on the HTTP Server API Reference Manual.
1 parent 3adb166 commit 1014405

File tree

1 file changed

+275
-2
lines changed

1 file changed

+275
-2
lines changed

libs/network/doc/reference_http_server.rst

+275-2
Original file line numberDiff line numberDiff line change
@@ -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+
158167
Constructor
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

195311
API 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 the Boost.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 the Boost.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 a Boost.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

0 commit comments

Comments
 (0)