@@ -21,7 +21,6 @@ struct file_server;
2121typedef http::server<file_server> server;
2222
2323struct file_cache {
24-
2524typedef std::map<std::string, std::pair<void *, std::size_t > > region_map;
2625typedef 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)));
6867static 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 {
9191static std::vector<server::response_header> empty_vector;
9292auto headers = file_headers.find (doc_root_ + path);
9393if (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 ();
9695return boost::make_iterator_range (begin, end);
9796 }else
9897return boost::make_iterator_range (empty_vector);
@@ -138,22 +137,75 @@ struct connection_handler : std::enable_shared_from_this<connection_handler> {
138137asio::const_buffers_1 (
139138static_cast <char const *>(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
146145void handle_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 );
150149if (!ec &&static_cast <std::size_t >(offset) < mmaped_region.second )
151150send_file (mmaped_region, offset, connection);
152151 }
153152
154153 file_cache &file_cache_;
155154};
156155
156+ struct input_consumer :public std ::enable_shared_from_this<input_consumer> {
157+ // Maximum size for incoming request bodies.
158+ static constexpr std::size_t MAX_INPUT_BODY_SIZE =2 <<16 ;
159+
160+ explicit input_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 (const auto &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+ void operator ()(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+
157209struct file_server {
158210explicit file_server (file_cache &cache) : cache_(cache) {}
159211
@@ -165,6 +217,14 @@ struct file_server {
165217 }else if (request.method ==" GET" ) {
166218 std::shared_ptr<connection_handler>h (new connection_handler (cache_));
167219 (*h)(request.destination , connection,true );
220+ }else if (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 {
169229static 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}