@@ -4,49 +4,128 @@ HTTP implementation
4
4
HTTP client
5
5
```````````
6
6
7
- The cpp-netlib HTTP client is composed of three template classes:
7
+ At the heart of the HTTP client implementation is a single class aptly named
8
+ ``basic_client ``, which is also a template. The template ``basic_client `` takes
9
+ three template parameters:
8
10
9
11
.. code-block :: c++
10
12
11
- namespace http {
12
- template <class Tag> basic_request;
13
- template <class Tag> basic_response;
14
- template <class Tag> basic_client;
15
- typedef basic_request<default _> request;
16
- typedef basic_response<default _> response;
17
- typedef basic_client<default _> client;
18
- }
13
+ namespace boost { namespace http {
14
+
15
+ template <class Tag, unsigned version_major, unsigned version_minor>
16
+ struct basic_client;
17
+
18
+ } // namespace http
19
+
20
+ } // namespace boost
21
+
22
+ The ``Tag `` template parameter follows the same tag-dispatch mechanism to
23
+ determine the behavior of the ``basic_client ``. The interface of
24
+ ``basic_client `` may change depending on certain properties defined for the tag
25
+ you provide. Below is a table of predefined supported tags you can use in your
26
+ overload of the ``basic_client ``:
27
+
28
+
29
+ +---------------------------------+---------------------------------------------+
30
+ | Tag | Description |
31
+ +=================================+=============================================+
32
+ | http_default_8bit_tcp_resolve | This is the default HTTP implementation tag |
33
+ | | that resolves addresses with a TCP resolver |
34
+ | | and provides a synchronous/blocking HTTP |
35
+ | | client interface. |
36
+ +---------------------------------+---------------------------------------------+
37
+ | http_default_8bit_udp_resolve | This is similar to the above tag except that|
38
+ | | it specifies the HTTP client to use a UDP |
39
+ | | resolver. It also provides a synchronous/ |
40
+ | | blocking HTTP client interface. |
41
+ +---------------------------------+---------------------------------------------+
42
+ | http_keepalive_8bit_tcp_resolve | This tag specifies that the HTTP client by |
43
+ | | default will keep connections to the server |
44
+ | | alive. It only makes sense if the |
45
+ | | ``version_major `` and ``version_minor `` are |
46
+ | | both ``1 ``, to indicate HTTP 1.1. This tag |
47
+ | | causes the HTTP client to resolve using a |
48
+ | | TCP resolver and provides a synchronous/ |
49
+ | | blocking HTTP client interface. |
50
+ +---------------------------------+---------------------------------------------+
51
+ | http_keepalive_8bit_udp_resolve | This is similar to the above tag except that|
52
+ | | it specifies the HTTP client to use a UDP |
53
+ | | resolver. It also provides a synchronous/ |
54
+ | | blocking HTTP client interface. |
55
+ +---------------------------------+---------------------------------------------+
56
+ | http_async_8bit_tcp_resolve | This tag provides an active HTTP client |
57
+ | | object implementation that uses a TCP |
58
+ | | resolver. Response objects returned will |
59
+ | | encapsulate a number of Boost.Thread _ |
60
+ | | shared futures to hold values. Users don't |
61
+ | | have to see this as they are implementation |
62
+ | | details. |
63
+ +---------------------------------+---------------------------------------------+
64
+ | http_async_8bit_udp_resolve | This is similar to the above tag except that|
65
+ | | specifies the HTTP client to use a UDP |
66
+ | | resolver. |
67
+ +---------------------------------+---------------------------------------------+
68
+
69
+ .. _Boost.Thread : http://www.boost.org/libs/thread
70
+
71
+
72
+ The default typedef for the HTTP client that is provided uses the
73
+ ``http_default_8bit_udp_resolve `` tag, and implements HTTP 1.0. The exact
74
+ typedef is in the ``boost::network::http `` namespace as the following:
75
+
76
+ .. code-block :: c++
77
+
78
+ namespace boost { namespace network { namespace http {
79
+
80
+ typedef basic_client<tags::http_default_8bit_udp_resolve, 1, 0>
81
+ client;
82
+
83
+ }}}
84
+
85
+
86
+ This type has nested typedefs for the correct types for the ``basic_request ``
87
+ and ``basic_response `` templates. To use the correct types for ``basic_request ``
88
+ or ``basic_response `` you can use these nested typedefs like so:
89
+
90
+
91
+ .. code-block :: c++
92
+
93
+ boost::network::http::client: :request request;
94
+ boost::network::http::client: :response response;
95
+
96
+ // or...
97
+ using namespace boost::network;
98
+ http::client: :request request;
99
+ http::client: :response response;
100
+
19
101
102
+ Typical use cases for the HTTP client would look something like the following:
20
103
21
- Each of these use again the tag-based static polymorphism that was
22
- described in previous sections. A default, human-readable typedef is
23
- provided for each one of the ``basic_request ``, ``basic_response `` and
24
- ``basic_client ``. ``basic_request `` and ``basic_response `` each model
25
- the message concept. They make use of directives to set and get HTTP
26
- headers, body etc. The code snippet below shows how to set the HTTP
27
- header field "Connection" with the option "close" using the DSEL
28
- described in the directives section:
29
104
30
105
.. code-block :: c++
31
106
32
107
using namespace boost::network;
33
108
http::request request("http://www.boost.org/");
34
109
request << header("Connection", "close");
35
110
111
+
36
112
The ``basic_client `` implements all HTTP methods as member functions
37
113
(HEAD, GET, POST, PUT, DELETE). Therefore, the code to make an HTTP
38
114
request looks trivially simple:
39
115
116
+
40
117
.. code-block :: c++
41
118
42
119
using namespace boost::network;
43
120
http::client client;
44
121
http::client: :request request("http://www.boost.org/");
45
122
http::client: :response response = client.get(request);
46
123
47
- Accessing data from ``http::response `` is also done using directives.
48
- To get the response headers, we use the ``headers `` directive which
49
- returns, in the default case, a map of strings to strings:
124
+
125
+ Accessing data from ``http::response `` is done using wrappers.
126
+ To get the response headers, we use the ``headers `` wrapper which
127
+ returns, in the default case, a multimap of strings to strings:
128
+
50
129
51
130
.. code-block :: c++
52
131
@@ -60,18 +139,23 @@ returns, in the default case, a map of strings to strings:
60
139
}
61
140
std::cout << std::endl;
62
141
142
+
63
143
HTTP server
64
144
```````````
65
145
66
146
As with the HTTP client, the HTTP server that is provided with
67
147
cpp-netlib is extensible through the tag mechanism and is embeddable.
68
148
The template class declaration of ``basic_server `` is given below:
69
149
150
+
70
151
.. code-block :: c++
71
152
72
- namespace http {
73
- template <class Tag, class RequestHandler> basic_server;
74
- }
153
+ namespace boost { namespace network { namespace http {
154
+
155
+ template <class Tag, class RequestHandler> basic_server;
156
+
157
+ }}}
158
+
75
159
76
160
The second template argument is used to specify the request handler
77
161
type. The request handler type is a functor type which should overload
@@ -95,18 +179,19 @@ implementation while the user-visible implementation is the
95
179
96
180
.. code-block :: c++
97
181
98
- namespace http {
99
- template <
100
- class RequestHandler
101
- >
102
- class server
103
- : public basic_server< default _, RequestHandler> {};
104
- }
182
+ namespace boost { namespace network { namespace http {
183
+
184
+ template < class RequestHandler>
185
+ class server :
186
+ public basic_server< default _, RequestHandler> {};
187
+
188
+ }}}
105
189
106
190
To use the forwarding server type you just supply the request handler
107
191
implementation as the parameter. For example, an "echo" server example
108
192
might look something like this:
109
193
194
+
110
195
.. code-block :: c++
111
196
112
197
using namespace boost::network;
@@ -116,15 +201,20 @@ might look something like this:
116
201
struct echo {
117
202
void operator () (const echo_server::request &request,
118
203
echo_server::response &response) const {
204
+ std::string ip = source(request);
119
205
response = echo_server::response: :stock_reply(
120
206
echo_server::response: :ok,
121
207
body(request));
208
+ std::cerr << "[" << ip << "]: " << request.uri <<
209
+ " status = " << echo_server::response: :ok << '\n ';
122
210
}
123
211
};
124
212
125
213
126
214
Here, all we're doing is returning the original request body with an
127
- HTTP OK response (200).
215
+ HTTP OK response (200). We are also printing the IP address from where the
216
+ request came from. Notice that we are using a wrapper to access the source of
217
+ the request.
128
218
129
219
HTTP URI
130
220
````````
0 commit comments