1
1
#include " server/connection.hpp"
2
2
#include " server/request_handler.hpp"
3
- #include " server/request_parser.hpp"
4
3
5
4
#include < boost/algorithm/string/predicate.hpp>
6
5
#include < boost/bind.hpp>
7
6
#include < boost/iostreams/filter/gzip.hpp>
8
7
#include < boost/iostreams/filtering_stream.hpp>
9
-
10
8
#include < vector>
11
9
12
10
namespace osrm
@@ -16,12 +14,32 @@ namespace server
16
14
17
15
Connection::Connection (boost::asio::io_context &io_context, RequestHandler &handler)
18
16
: strand(boost::asio::make_strand(io_context)), TCP_socket(strand), timer(strand),
19
- request_handler (handler)
17
+ request_handler (handler), http_request_parser(std::make_optional<RequestParser>())
20
18
{
21
19
}
22
20
23
21
boost::asio::ip::tcp::socket &Connection::socket () { return TCP_socket; }
24
22
23
+ namespace
24
+ {
25
+
26
+ http::compression_type select_compression (const boost::beast::http::fields &fields)
27
+ {
28
+ const auto header_value = fields[boost::beast::http::field::accept_encoding];
29
+ /* giving gzip precedence over deflate */
30
+ if (boost::icontains (header_value, " deflate" ))
31
+ {
32
+ return http::deflate_rfc1951;
33
+ }
34
+ if (boost::icontains (header_value, " gzip" ))
35
+ {
36
+ return http::gzip_rfc1952;
37
+ }
38
+ return http::no_compression;
39
+ }
40
+
41
+ } // namespace
42
+
25
43
// / Start the first asynchronous operation for the connection.
26
44
void Connection::start ()
27
45
{
@@ -60,20 +78,45 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t
60
78
timer.expires_from_now (boost::posix_time::seconds (0 ));
61
79
}
62
80
81
+ boost::beast::error_code ec;
82
+ http_request_parser->put (boost::asio::buffer (incoming_data_buffer, bytes_transferred), ec);
63
83
// no error detected, let's parse the request
64
84
http::compression_type compression_type (http::no_compression);
65
- RequestParser::RequestStatus result;
66
- std::tie (result, compression_type) =
67
- request_parser.parse (current_request,
68
- incoming_data_buffer.data (),
69
- incoming_data_buffer.data () + bytes_transferred);
70
-
71
- // the request has been parsed
72
- if (result == RequestParser::RequestStatus::valid)
85
+
86
+ if (ec)
87
+ {
88
+ if (ec == boost::beast::http::error::need_more)
89
+ {
90
+ // we don't have a result yet, so continue reading
91
+ TCP_socket.async_read_some (boost::asio::buffer (incoming_data_buffer),
92
+ boost::bind (&Connection::handle_read,
93
+ this ->shared_from_this (),
94
+ boost::asio::placeholders::error,
95
+ boost::asio::placeholders::bytes_transferred));
96
+ }
97
+ else
98
+ {
99
+ // request is not parseable
100
+ current_reply = http::reply::stock_reply (http::reply::bad_request);
101
+
102
+ boost::asio::async_write (TCP_socket,
103
+ current_reply.to_buffers (),
104
+ boost::bind (&Connection::handle_write,
105
+ this ->shared_from_this (),
106
+ boost::asio::placeholders::error));
107
+ }
108
+ }
109
+ else
73
110
{
111
+ // the request has been parsed
112
+ const auto &message = http_request_parser->get ();
113
+ compression_type = select_compression (message);
114
+
115
+ fill_request (message, current_request);
74
116
75
117
boost::system::error_code ec;
76
118
current_request.endpoint = TCP_socket.remote_endpoint (ec).address ();
119
+
77
120
if (ec)
78
121
{
79
122
util::Log (logDEBUG) << " Socket remote endpoint error: " << ec.message ();
@@ -127,25 +170,6 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t
127
170
this ->shared_from_this (),
128
171
boost::asio::placeholders::error));
129
172
}
130
- else if (result == RequestParser::RequestStatus::invalid)
131
- { // request is not parseable
132
- current_reply = http::reply::stock_reply (http::reply::bad_request);
133
-
134
- boost::asio::async_write (TCP_socket,
135
- current_reply.to_buffers (),
136
- boost::bind (&Connection::handle_write,
137
- this ->shared_from_this (),
138
- boost::asio::placeholders::error));
139
- }
140
- else
141
- {
142
- // we don't have a result yet, so continue reading
143
- TCP_socket.async_read_some (boost::asio::buffer (incoming_data_buffer),
144
- boost::bind (&Connection::handle_read,
145
- this ->shared_from_this (),
146
- boost::asio::placeholders::error,
147
- boost::asio::placeholders::bytes_transferred));
148
- }
149
173
}
150
174
151
175
// / Handle completion of a write operation.
@@ -158,7 +182,7 @@ void Connection::handle_write(const boost::system::error_code &error)
158
182
--processed_requests;
159
183
current_request = http::request ();
160
184
current_reply = http::reply ();
161
- request_parser = RequestParser ();
185
+ http_request_parser. emplace ();
162
186
incoming_data_buffer = boost::array<char , 8192 >();
163
187
output_buffer.clear ();
164
188
this ->start ();
@@ -220,5 +244,15 @@ std::vector<char> Connection::compress_buffers(const std::vector<char> &uncompre
220
244
221
245
return compressed_data;
222
246
}
247
+
248
+ void Connection::fill_request (const RequestParser::value_type &http_message,
249
+ http::request ¤t_request)
250
+ {
251
+ current_request.uri = http_message.target ().to_string ();
252
+ current_request.agent = http_message[boost::beast::http::field::user_agent].to_string ();
253
+ current_request.referrer = http_message[boost::beast::http::field::referer].to_string ();
254
+ current_request.connection = http_message[boost::beast::http::field::connection].to_string ();
255
+ }
256
+
223
257
} // namespace server
224
258
} // namespace osrm
0 commit comments