@@ -155,6 +155,15 @@ And that the following typedef's have been put in place:
155
155
struct handler_type;
156
156
typedef boost::network::http: :server<handler_type> http_server;
157
157
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
+
158
167
Constructor
159
168
```````````
160
169
@@ -183,17 +192,281 @@ instance has been constructed in the following manner:
183
192
boost::thread t1(boost::bind(&http_server::run, &server));
184
193
boost::thread t2(boost::bind(&http_server::run, &server));
185
194
server.run();
195
+ t1.join();
196
+ t2.join();
186
197
187
198
``server.stop() ``
188
199
Stop the HTTP Server acceptor and wait for all pending requests to finish.
189
200
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
+
190
255
Asynchronous Servers
191
256
--------------------
192
257
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
+ };
194
310
195
311
API Documentation
196
312
~~~~~~~~~~~~~~~~~
197
313
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
+
199
470
471
+ .. _Boost.Range : http://www.boost.org/libs/range
472
+ .. _Boost.Function : http://www.boost.org/libs/function
0 commit comments