Skip to content

Commit fa0a950

Browse files
author
mikhail_beris
committed
Merging http-server branch to trunk.
1 parent a7056e9 commit fa0a950

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+1571
-208
lines changed

CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
cmake_minimum_required(VERSION 2.6)
2+
project(CPP-NETLIB)
3+
find_package( Boost 1.41.0 )
4+
if (Boost_FOUND)
5+
set(Boost_USE_STATIC_LIBS ON)
6+
set(Boost_USE_MULTI_THREADED ON)
7+
include_directories(${Boost_INCLUDE_DIRS})
8+
endif()
9+
enable_testing()
10+
add_subdirectory(libs/network/test)

boost/network/protocol/http/client.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#define BOOST_NETLIB_VERSION "0.3"
1212
#endif
1313

14+
#include <boost/network/traits/ostringstream.hpp>
1415
#include <boost/network/protocol/http/message.hpp>
1516
#include <boost/network/protocol/http/response.hpp>
1617
#include <boost/network/protocol/http/request.hpp>
@@ -42,7 +43,7 @@ namespace boost { namespace network { namespace http {
4243
boost::asio::ip::tcp::resolver::iterator
4344
> resolver_iterator_pair;
4445

45-
typedef typename string_traits<tag>::type string_type;
46+
typedef typename string<tag>::type string_type;
4647

4748
typedef std::map<string_type, resolver_iterator_pair> resolved_cache;
4849
resolved_cache endpoint_cache_;
@@ -200,7 +201,7 @@ namespace boost { namespace network { namespace http {
200201
};
201202

202203
void read_body(basic_response<tag> & response_, boost::asio::ip::tcp::socket & socket, boost::asio::streambuf & response_buffer) const {
203-
typename ostringstream_traits<tag>::type body_stream;
204+
typename ostringstream<tag>::type body_stream;
204205

205206
if (response_buffer.size() > 0)
206207
body_stream << &response_buffer;
@@ -333,7 +334,7 @@ namespace boost { namespace network { namespace http {
333334

334335
};
335336

336-
typedef basic_client<http::message_tag, 1, 0> client;
337+
typedef basic_client<tags::http, 1, 0> client;
337338

338339
} // namespace http
339340

boost/network/protocol/http/client_fwd.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@
1111
#define BOOST_NETLIB_VERSION "0.3"
1212
#endif
1313

14-
#include <boost/network/protocol/http/tags.hpp>
14+
#include <boost/network/tags.hpp>
1515

1616
namespace boost { namespace network { namespace http {
1717

1818
//! Forward declaration of basic_client template.
1919
template <class tag, unsigned version_major, unsigned version_minor>
2020
class basic_client;
2121

22-
typedef basic_client<http::message_tag, 1, 0> client;
22+
typedef basic_client<tags::http, 1, 0> client;
2323

2424
} // namespace http
2525

Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
// Copyright 2009 (c) Dean Michael Berris <mikhailberis@gmail.com>
2+
// Copyright 2009 (c) Tarroo, Inc.
3+
// Adapted from Christopher Kholhoff's Boost.Asio Example, released under
4+
// the Boost Software License, Version 1.0. (See acccompanying file LICENSE_1_0.txt
5+
// or copy at http://www.boost.org/LICENSE_1_0.txt)
6+
//
7+
// =====================================================================================
8+
//
9+
// Filename: connection.hpp
10+
//
11+
// Description: Connection handler for the HTTP requests.
12+
//
13+
// Version: 1.1
14+
// Created: Sunday, 15 November, 2009 07:46:40 PHT
15+
//
16+
// Author: Dean Michael Berris (dmb), mikhailberis@gmail.com
17+
//
18+
// =====================================================================================
19+
//
20+
21+
#ifndef BOOST_NETWORK_HTTP_CONNECTION_HPP_
22+
#define BOOST_NETWORK_HTTP_CONNECTION_HPP_
23+
24+
#include <boost/enable_shared_from_this.hpp>
25+
#include <boost/network/protocol/http/request_parser.hpp>
26+
#include <boost/network/protocol/http/request.hpp>
27+
#include <boost/network/protocol/http/header.hpp>
28+
#include <boost/network/protocol/http/reply.hpp>
29+
#include <boost/asio.hpp>
30+
#include <boost/array.hpp>
31+
#include <boost/lexical_cast.hpp>
32+
#include <boost/algorithm/string/case_conv.hpp>
33+
#include <boost/bind.hpp>
34+
35+
namespace boost { namespace network { namespace http {
36+
37+
using boost::asio::io_service;
38+
namespace system = boost::system;
39+
using boost::asio::ip::tcp;
40+
using boost::array;
41+
using boost::tribool;
42+
using boost::tuple;
43+
namespace tuples = boost::tuples;
44+
using boost::tuples::tie;
45+
using boost::bind;
46+
using boost::to_lower_copy;
47+
48+
template <class Handler>
49+
struct connection : boost::enable_shared_from_this<connection<Handler> > {
50+
51+
connection(io_service & service, Handler & handler)
52+
: service_(service)
53+
, handler_(handler)
54+
, socket_(service_)
55+
, wrapper_(service_)
56+
{
57+
try {
58+
socket_.set_option(tcp::no_delay(true)); // Don't delay writing
59+
} catch (system::system_error & e) {
60+
handler_.log(e.what());
61+
}
62+
}
63+
64+
tcp::socket & socket() {
65+
return socket_;
66+
}
67+
68+
void start() {
69+
// This is HTTP so we really want to just
70+
// read and parse a request that's incoming
71+
// and then pass that request object to the
72+
// handler_ instance.
73+
//
74+
socket_.async_read_some(
75+
boost::asio::buffer(buffer_),
76+
wrapper_.wrap(
77+
bind(
78+
&connection<Handler>::handle_read_headers,
79+
connection<Handler>::shared_from_this(),
80+
boost::asio::placeholders::error,
81+
boost::asio::placeholders::bytes_transferred
82+
)
83+
)
84+
);
85+
}
86+
87+
private:
88+
89+
struct is_content_length {
90+
template <class Header>
91+
bool operator()(Header const & header) {
92+
return to_lower_copy(header.name) == "content-length";
93+
}
94+
};
95+
96+
void handle_read_headers(system::error_code const &ec, size_t bytes_transferred) {
97+
if (!ec) {
98+
tribool done;
99+
tie(done,tuples::ignore) = parser_.parse_headers(request_, buffer_.data(), buffer_.data() + bytes_transferred);
100+
if (done) {
101+
if (request_.method[0] == 'P') {
102+
// look for the content-length header
103+
std::vector<request_header>::iterator it =
104+
find_if(
105+
request_.headers.begin(),
106+
request_.headers.end(),
107+
is_content_length()
108+
);
109+
if (it == request_.headers.end()) {
110+
reply_= reply::stock_reply(reply::bad_request);
111+
boost::asio::async_write(
112+
socket_,
113+
reply_.to_buffers(),
114+
wrapper_.wrap(
115+
bind(
116+
&connection<Handler>::handle_write,
117+
connection<Handler>::shared_from_this(),
118+
boost::asio::placeholders::error
119+
)
120+
)
121+
);
122+
return;
123+
}
124+
125+
size_t content_length = 0;
126+
127+
try {
128+
content_length = boost::lexical_cast<size_t>(it->value);
129+
} catch (...) {
130+
reply_= reply::stock_reply(reply::bad_request);
131+
boost::asio::async_write(
132+
socket_,
133+
reply_.to_buffers(),
134+
wrapper_.wrap(
135+
bind(
136+
&connection<Handler>::handle_write,
137+
connection<Handler>::shared_from_this(),
138+
boost::asio::placeholders::error
139+
)
140+
)
141+
);
142+
return;
143+
}
144+
145+
if (content_length != 0) {
146+
async_read(
147+
socket_,
148+
boost::asio::buffer(buffer_),
149+
boost::asio::transfer_at_least(content_length),
150+
wrapper_.wrap(
151+
bind(
152+
&connection<Handler>::handle_read_body_contents,
153+
connection<Handler>::shared_from_this(),
154+
boost::asio::placeholders::error,
155+
content_length,
156+
boost::asio::placeholders::bytes_transferred
157+
)
158+
)
159+
);
160+
return;
161+
}
162+
163+
handler_(request_, reply_);
164+
boost::asio::async_write(
165+
socket_,
166+
reply_.to_buffers(),
167+
wrapper_.wrap(
168+
bind(
169+
&connection<Handler>::handle_write,
170+
connection<Handler>::shared_from_this(),
171+
boost::asio::placeholders::error
172+
)
173+
)
174+
);
175+
} else {
176+
handler_(request_, reply_);
177+
boost::asio::async_write(
178+
socket_,
179+
reply_.to_buffers(),
180+
wrapper_.wrap(
181+
bind(
182+
&connection<Handler>::handle_write,
183+
connection<Handler>::shared_from_this(),
184+
boost::asio::placeholders::error
185+
)
186+
)
187+
);
188+
}
189+
} else if (!done) {
190+
reply_= reply::stock_reply(reply::bad_request);
191+
boost::asio::async_write(
192+
socket_,
193+
reply_.to_buffers(),
194+
wrapper_.wrap(
195+
bind(
196+
&connection<Handler>::handle_write,
197+
connection<Handler>::shared_from_this(),
198+
boost::asio::placeholders::error
199+
)
200+
)
201+
);
202+
} else {
203+
socket_.async_read_some(
204+
boost::asio::buffer(buffer_),
205+
wrapper_.wrap(
206+
bind(
207+
&connection<Handler>::handle_read_headers,
208+
connection<Handler>::shared_from_this(),
209+
boost::asio::placeholders::error,
210+
boost::asio::placeholders::bytes_transferred
211+
)
212+
)
213+
);
214+
}
215+
}
216+
// TODO Log the error?
217+
}
218+
219+
void handle_read_body_contents(boost::system::error_code const & ec, size_t bytes_to_read, size_t bytes_transferred) {
220+
if (!ec) {
221+
size_t difference = bytes_to_read - bytes_transferred;
222+
request_.body.append(buffer_.begin(), buffer_.end());
223+
if (difference == 0) {
224+
handler_(request_, reply_);
225+
boost::asio::async_write(
226+
socket_,
227+
reply_.to_buffers(),
228+
wrapper_.wrap(
229+
bind(
230+
&connection<Handler>::handle_write,
231+
connection<Handler>::shared_from_this(),
232+
boost::asio::placeholders::error
233+
)
234+
)
235+
);
236+
} else {
237+
socket_.async_read_some(
238+
boost::asio::buffer(buffer_),
239+
wrapper_.wrap(
240+
bind(
241+
&connection<Handler>::handle_read_body_contents,
242+
connection<Handler>::shared_from_this(),
243+
boost::asio::placeholders::error,
244+
difference,
245+
boost::asio::placeholders::bytes_transferred
246+
)
247+
)
248+
);
249+
}
250+
}
251+
// TODO Log the error?
252+
}
253+
254+
void handle_write(boost::system::error_code const & ec) {
255+
if (!ec) {
256+
boost::system::error_code ignored_ec;
257+
socket_.shutdown(tcp::socket::shutdown_both, ignored_ec);
258+
}
259+
}
260+
261+
io_service & service_;
262+
Handler & handler_;
263+
tcp::socket socket_;
264+
io_service::strand wrapper_;
265+
array<char,4096> buffer_;
266+
request_parser parser_;
267+
request_pod request_;
268+
reply reply_;
269+
};
270+
271+
272+
} // namespace http
273+
274+
} // namespace network
275+
276+
} // namespace boost
277+
278+
#endif // BOOST_NETWORK_HTTP_CONNECTION_HPP_
279+

boost/network/protocol/http/errors.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
namespace boost { namespace network { namespace http { namespace errors {
1414

15-
template <class Tag=http::message_tag>
15+
template <class Tag=tags::http>
1616
struct connection_timeout_exception :
1717
std::runtime_error
1818
{
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//
2+
// header.hpp
3+
// ~~~~~~~~~~
4+
//
5+
// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6+
// Copyright (c) 2009 Dean Michael Berris (mikhailberis@gmail.com)
7+
// Copyright (c) 2009 Tarroo, Inc.
8+
//
9+
// Distributed under the Boost Software License, Version 1.0. (See accompanying
10+
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11+
//
12+
13+
#ifndef HTTP_SERVER3_HEADER_HPP
14+
#define HTTP_SERVER3_HEADER_HPP
15+
16+
#include <string>
17+
18+
namespace boost { namespace network { namespace http {
19+
20+
struct request_header
21+
{
22+
std::string name;
23+
std::string value;
24+
};
25+
26+
inline void swap(request_header & l, request_header & r) {
27+
swap(l.name, r.name);
28+
swap(l.value, r.value);
29+
}
30+
31+
} // namespace http
32+
33+
} // namespace network
34+
35+
} // namespace boost
36+
37+
#endif // HTTP_SERVER3_HEADER_HPP

0 commit comments

Comments
 (0)