Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit79aaa62

Browse files
committed
Fixes#635 - bug in async server's connection read
This changes the example file server to use the read handler forPOST/PUT requests. This currently assumes that there's a content-lengthheader (not much error handling is happening here, but it's meant as aproof of concept anyway).Using this code path in an example should be good enough for the momentuntil we have better tests and a better API for this functionality.
1 parent89f9768 commit79aaa62

File tree

2 files changed

+76
-16
lines changed

2 files changed

+76
-16
lines changed

‎boost/network/protocol/http/server/async_connection.hpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ struct async_connection
378378
boost::throw_exception(std::system_error(*error_encountered));
379379
if (new_start != read_buffer_.begin()) {
380380
input_range input =
381-
boost::make_iterator_range(new_start,read_buffer_.end());
381+
boost::make_iterator_range(new_start,data_end);
382382
buffer_type::iterator start_tmp = new_start;
383383
new_start = read_buffer_.begin();
384384
auto self =this->shared_from_this();
@@ -389,11 +389,12 @@ struct async_connection
389389
}
390390

391391
auto self =this->shared_from_this();
392-
socket().async_read_some(asio::buffer(read_buffer_),
393-
strand.wrap([this, self, callback](
394-
std::error_code ec,size_t bytes_transferred) {
395-
callback(ec, bytes_transferred);
396-
}));
392+
socket().async_read_some(
393+
asio::buffer(read_buffer_),
394+
strand.wrap([this, self, callback](std::error_code ec,
395+
size_t bytes_transferred) {
396+
this->wrap_read_handler(callback, ec, bytes_transferred);
397+
}));
397398
}
398399

399400
/// Returns a reference to the underlying socket.

‎libs/network/example/http/fileserver.cpp

Lines changed: 69 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ struct file_server;
2121
typedef http::server<file_server> server;
2222

2323
structfile_cache {
24-
2524
typedef std::map<std::string, std::pair<void *, std::size_t> > region_map;
2625
typedef std::map<std::string, std::vector<server::response_header> > meta_map;
2726

@@ -66,7 +65,8 @@ struct file_cache {
6665

6766
regions.insert(std::make_pair(real_filename,std::make_pair(region, size)));
6867
static server::response_header common_headers[] = {
69-
{"Connection","close"}, {"Content-Type","x-application/octet-stream"},
68+
{"Connection","close"},
69+
{"Content-Type","x-application/octet-stream"},
7070
{"Content-Length","0"}};
7171
std::vector<server::response_header>headers(common_headers,
7272
common_headers +3);
@@ -91,8 +91,7 @@ struct file_cache {
9191
static std::vector<server::response_header> empty_vector;
9292
auto headers = file_headers.find(doc_root_ + path);
9393
if (headers != file_headers.end()) {
94-
auto begin = headers->second.begin(),
95-
end = headers->second.end();
94+
auto begin = headers->second.begin(), end = headers->second.end();
9695
returnboost::make_iterator_range(begin, end);
9796
}else
9897
returnboost::make_iterator_range(empty_vector);
@@ -138,22 +137,75 @@ struct connection_handler : std::enable_shared_from_this<connection_handler> {
138137
asio::const_buffers_1(
139138
static_cast<charconst *>(mmaped_region.first) + offset,
140139
rightmost_bound - offset),
141-
[=](std::error_codeconst &ec) {
140+
[=](std::error_codeconst &ec) {
142141
self->handle_chunk(mmaped_region, rightmost_bound, connection, ec);
143142
});
144143
}
145144

146145
voidhandle_chunk(std::pair<void *, std::size_t> mmaped_region,off_t offset,
147146
server::connection_ptr connection,
148147
std::error_codeconst &ec) {
149-
assert(offset>=0);
148+
assert(offset >=0);
150149
if (!ec &&static_cast<std::size_t>(offset) < mmaped_region.second)
151150
send_file(mmaped_region, offset, connection);
152151
}
153152

154153
file_cache &file_cache_;
155154
};
156155

156+
structinput_consumer :publicstd::enable_shared_from_this<input_consumer> {
157+
// Maximum size for incoming request bodies.
158+
staticconstexpr std::size_t MAX_INPUT_BODY_SIZE =2 <<16;
159+
160+
explicitinput_consumer(std::shared_ptr<connection_handler> h,
161+
server::request r)
162+
: request_(std::move(r)), handler_(std::move(h)), content_length_{0} {
163+
for (constauto &header : request_.headers) {
164+
if (boost::iequals(header.name,"content-length")) {
165+
content_length_ =std::stoul(header.value);
166+
std::cerr <<"Content length:" << content_length_ <<'\n';
167+
break;
168+
}
169+
}
170+
}
171+
172+
voidoperator()(server::connection::input_range input, std::error_code ec,
173+
std::size_t bytes_transferred,
174+
server::connection_ptr connection) {
175+
std::cerr <<"Callback:" << bytes_transferred <<"; ec =" << ec <<'\n';
176+
if (ec == asio::error::eof)return;
177+
if (!ec) {
178+
if (empty(input))
179+
return (*handler_)(request_.destination, connection,true);
180+
request_.body.insert(request_.body.end(),boost::begin(input),
181+
boost::end(input));
182+
if (request_.body.size() > MAX_INPUT_BODY_SIZE) {
183+
connection->set_status(server::connection::bad_request);
184+
static server::response_header error_headers[] = {
185+
{"Connection","close"}};
186+
connection->set_headers(
187+
boost::make_iterator_range(error_headers, error_headers +1));
188+
connection->write("Body too large.");
189+
return;
190+
}
191+
std::cerr <<"Body:" << request_.body <<'\n';
192+
if (request_.body.size() == content_length_)
193+
return (*handler_)(request_.destination, connection,true);
194+
std::cerr <<"Scheduling another read...\n";
195+
auto self =this->shared_from_this();
196+
connection->read([self](server::connection::input_range input,
197+
std::error_code ec, std::size_t bytes_transferred,
198+
server::connection_ptr connection) {
199+
(*self)(input, ec, bytes_transferred, connection);
200+
});
201+
}
202+
}
203+
204+
server::request request_;
205+
std::shared_ptr<connection_handler> handler_;
206+
size_t content_length_;
207+
};
208+
157209
structfile_server {
158210
explicitfile_server(file_cache &cache) : cache_(cache) {}
159211

@@ -165,6 +217,14 @@ struct file_server {
165217
}elseif (request.method =="GET") {
166218
std::shared_ptr<connection_handler>h(newconnection_handler(cache_));
167219
(*h)(request.destination, connection,true);
220+
}elseif (request.method =="PUT" || request.method =="POST") {
221+
auto h = std::make_shared<connection_handler>(cache_);
222+
auto c = std::make_shared<input_consumer>(h, request);
223+
connection->read([c](server::connection::input_range input,
224+
std::error_code ec, std::size_t bytes_transferred,
225+
server::connection_ptr connection) {
226+
(*c)(input, ec, bytes_transferred, connection);
227+
});
168228
}else {
169229
static server::response_header error_headers[] = {
170230
{"Connection","close"}};
@@ -184,11 +244,10 @@ int main(int, char *[]) {
184244
file_serverhandler(cache);
185245
server::optionsoptions(handler);
186246
serverinstance(options.thread_pool(std::make_shared<utils::thread_pool>(4))
187-
.address("0.0.0.0")
188-
.port("8000"));
247+
.address("0.0.0.0")
248+
.port("8000"));
189249
instance.run();
190-
}
191-
catch (std::exception &e) {
250+
}catch (std::exception &e) {
192251
std::cerr << e.what() << std::endl;
193252
}
194253
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp