13 #include <boost/algorithm/string.hpp> 14 #include <boost/lexical_cast.hpp> 21 namespace status_strings
25 const std::string
ok =
"HTTP/1.0 200 OK\r\n";
26 const std::string
created =
"HTTP/1.0 201 Created\r\n";
27 const std::string
accepted =
"HTTP/1.0 202 Accepted\r\n";
28 const std::string
no_content =
"HTTP/1.0 204 No Content\r\n";
33 const std::string
bad_request =
"HTTP/1.0 400 Bad Request\r\n";
35 const std::string
forbidden =
"HTTP/1.0 403 Forbidden\r\n";
36 const std::string
not_found =
"HTTP/1.0 404 Not Found\r\n";
38 "HTTP/1.0 500 Internal Server Error\r\n";
40 const std::string
bad_gateway =
"HTTP/1.0 502 Bad Gateway\r\n";
48 return boost::asio::buffer(switching_protocols);
50 return boost::asio::buffer(ok);
52 return boost::asio::buffer(created);
54 return boost::asio::buffer(accepted);
56 return boost::asio::buffer(no_content);
58 return boost::asio::buffer(multiple_choices);
60 return boost::asio::buffer(moved_permanently);
62 return boost::asio::buffer(moved_temporarily);
64 return boost::asio::buffer(not_modified);
66 return boost::asio::buffer(bad_request);
68 return boost::asio::buffer(unauthorized);
70 return boost::asio::buffer(forbidden);
72 return boost::asio::buffer(not_found);
74 return boost::asio::buffer(internal_server_error);
76 return boost::asio::buffer(not_implemented);
78 return boost::asio::buffer(bad_gateway);
80 return boost::asio::buffer(service_unavailable);
82 return boost::asio::buffer(internal_server_error);
88 namespace misc_strings
92 const char crlf[] = {
'\r',
'\n'};
96 namespace stock_replies
102 "<head><title>Created</title></head>" 103 "<body><h1>201 Created</h1></body>" 107 "<head><title>Accepted</title></head>" 108 "<body><h1>202 Accepted</h1></body>" 112 "<head><title>No Content</title></head>" 113 "<body><h1>204 Content</h1></body>" 117 "<head><title>Multiple Choices</title></head>" 118 "<body><h1>300 Multiple Choices</h1></body>" 122 "<head><title>Moved Permanently</title></head>" 123 "<body><h1>301 Moved Permanently</h1></body>" 127 "<head><title>Moved Temporarily</title></head>" 128 "<body><h1>302 Moved Temporarily</h1></body>" 132 "<head><title>Not Modified</title></head>" 133 "<body><h1>304 Not Modified</h1></body>" 137 "<head><title>Bad Request</title></head>" 138 "<body><h1>400 Bad Request</h1></body>" 142 "<head><title>Unauthorized</title></head>" 143 "<body><h1>401 Unauthorized</h1></body>" 147 "<head><title>Forbidden</title></head>" 148 "<body><h1>403 Forbidden</h1></body>" 152 "<head><title>Not Found</title></head>" 153 "<body><h1>404 Not Found</h1></body>" 157 "<head><title>Internal Server Error</title></head>" 158 "<body><h1>500 Internal Server Error</h1></body>" 162 "<head><title>Not Implemented</title></head>" 163 "<body><h1>501 Not Implemented</h1></body>" 167 "<head><title>Bad Gateway</title></head>" 168 "<body><h1>502 Bad Gateway</h1></body>" 172 "<head><title>Service Unavailable</title></head>" 173 "<body><h1>503 Service Unavailable</h1></body>" 219 std::vector<boost::asio::const_buffer>
222 std::vector<boost::asio::const_buffer> buffers;
223 for (std::size_t i = 0; i < headers.size(); ++i)
226 buffers.push_back(boost::asio::buffer(h.
name));
229 buffers.push_back(boost::asio::buffer(h.
value));
238 const std::string& content_type,
239 const std::string& filename,
240 const std::vector<HttpHeader>& additional_headers)
242 std::vector<HttpHeader> headers;
243 headers.push_back(
HttpHeader(
"Content-Type", content_type));
244 std::copy(additional_headers.begin(), additional_headers.end(),
251 const std::vector<HttpHeader>& headers)
252 : status_(status), headers_(headers), filename_(filename)
258 for (
const auto& h : headers)
260 if (boost::iequals(h.name,
"content-type"))
268 if (boost::algorithm::ends_with(filename,
".js"))
269 return "application/javascript";
270 if (boost::algorithm::ends_with(filename,
".htm"))
272 if (boost::algorithm::ends_with(filename,
".html"))
274 if (boost::algorithm::ends_with(filename,
".css"))
276 if (boost::algorithm::ends_with(filename,
".png"))
278 if (boost::algorithm::ends_with(filename,
".jpg"))
280 if (boost::algorithm::ends_with(filename,
".jpeg"))
282 if (boost::algorithm::ends_with(filename,
".gif"))
284 return "application/octet-stream";
288 const std::string& filename,
289 const std::vector<HttpHeader>& headers,
290 boost::shared_ptr<HttpConnection> connection)
292 std::ifstream file_stream(filename.c_str());
293 std::stringstream file_buffer;
294 file_buffer << file_stream.rdbuf();
295 std::string content = file_buffer.str();
298 reply_builder_.
headers(headers);
301 reply_builder_.
header(
"Content-Length",
302 boost::lexical_cast<std::string>(content.size()));
303 reply_builder_.
write(connection);
304 connection->write(content);
308 const HttpRequest& request, boost::shared_ptr<HttpConnection> connection,
309 const char* begin,
const char* end)
316 const std::string& filesystem_root,
bool list_directories,
317 const std::vector<HttpHeader>& additional_headers)
320 list_directories, additional_headers);
324 const std::string& filesystem_root,
bool list_directories,
325 const std::vector<HttpHeader>& headers)
327 filesystem_root_(filesystem_root), list_directories_(list_directories)
332 const HttpRequest& request, boost::shared_ptr<HttpConnection> connection,
333 const char* begin,
const char* end)
338 if (rel_path.find_first_of(
'/') == 0)
340 rel_path = rel_path.substr(1);
345 if (boost::filesystem::exists(requested_path))
347 if (boost::filesystem::is_directory(requested_path))
351 std::stringstream content;
352 content <<
"<html><body>";
353 content <<
"<h1> Directory Listing: " << request.
path 355 boost::filesystem::directory_iterator end_itr;
356 for (boost::filesystem::directory_iterator itr(
358 itr != end_itr; ++itr)
360 if (boost::filesystem::is_directory(itr->status()))
362 content <<
"<a href=\"" 363 << itr->path().leaf().generic_string()
365 content << itr->path().leaf().generic_string()
369 else if (boost::filesystem::is_regular_file(
372 content <<
"<a href=\"" 373 << itr->path().leaf().generic_string()
375 content << itr->path().leaf().generic_string();
380 content <<
"</body></html>";
383 request, connection, begin, end);
388 request, connection, begin, end);
392 else if (boost::filesystem::is_regular_file(requested_path))
417 const std::string& content_type,
418 const std::string& content,
419 const std::vector<HttpHeader>& additional_headers)
421 std::vector<HttpHeader> headers;
423 "Content-Length", boost::lexical_cast<std::string>(content.size())));
424 headers.push_back(
HttpHeader(
"Content-Type", content_type));
425 std::copy(additional_headers.begin(), additional_headers.end(),
432 const std::string& content)
433 : reply_builder_(status), content_string_(content)
439 const HttpRequest& request, boost::shared_ptr<HttpConnection> connection,
440 const char* begin,
const char* end)
453 : status_(status), headers_(new std::vector<
HttpHeader>())
458 const std::string& value)
ReplyBuilder reply_builder_
const std::string unauthorized
std::vector< HttpHeader > headers_
static bool serveFromFile(HttpReply::status_type status, const std::string &filename, const std::vector< HttpHeader > &headers, boost::shared_ptr< HttpConnection > connection)
static HttpServerRequestHandler static_reply(status_type status, const std::string &content_type, const std::string &content, const std::vector< HttpHeader > &additional_headers=std::vector< HttpHeader >())
const std::string switching_protocols
static std::string sniffContentType(const std::string &filename)
static ReplyBuilder builder(status_type status)
static HttpServerRequestHandler from_file(HttpReply::status_type status, const std::string &content_type, const std::string &filename, const std::vector< HttpHeader > &additional_headers=std::vector< HttpHeader >())
ReplyBuilder(HttpReply::status_type status)
FileHttpRequestHandler(HttpReply::status_type status, const std::string &filename, const std::vector< HttpHeader > &headers)
std::vector< HttpHeader > headers_
bool operator()(const HttpRequest &, boost::shared_ptr< HttpConnection >, const char *begin, const char *end)
const std::string service_unavailable
ReplyBuilder & headers(const std::vector< HttpHeader > &headers)
const std::string no_content
bool operator()(const HttpRequest &, boost::shared_ptr< HttpConnection >, const char *begin, const char *end)
static HttpServerRequestHandler from_filesystem(HttpReply::status_type status, const std::string &path_root, const std::string &filesystem_root, bool list_directories, const std::vector< HttpHeader > &additional_headers=std::vector< HttpHeader >())
const std::string created
boost::shared_ptr< HttpConnection > HttpConnectionPtr
const std::string accepted
HttpReply::status_type status_
const std::string multiple_choices
static bool hasContentType(const std::vector< HttpHeader > &headers)
const std::string forbidden
const std::string bad_request
boost::shared_ptr< std::vector< HttpHeader > > headers_
const std::string moved_temporarily
HttpReply::status_type status_
void write(HttpConnectionPtr connection)
const std::string not_modified
const std::string not_found
const std::string internal_server_error
boost::function< bool(const HttpRequest &, boost::shared_ptr< HttpConnection >, const char *begin, const char *end)> HttpServerRequestHandler
static HttpServerRequestHandler stock_reply(status_type status)
bool operator()(const HttpRequest &, boost::shared_ptr< HttpConnection >, const char *begin, const char *end)
FilesystemHttpRequestHandler(HttpReply::status_type status, const std::string &path_root, const std::string &filesystem_root, bool list_directories, const std::vector< HttpHeader > &headers)
boost::asio::const_buffer to_buffer(HttpReply::status_type status)
ReplyBuilder & header(const std::string &name, const std::string &value)
static std::vector< boost::asio::const_buffer > to_buffers(const std::vector< HttpHeader > &headers)
const std::string content_string_
StaticHttpRequestHandler(HttpReply::status_type status, const std::vector< HttpHeader > &headers, const std::string &content)
boost::shared_ptr< const void > ResourcePtr
const char name_value_separator[]
boost::filesystem::path filesystem_root_
const std::string bad_gateway
const std::string not_implemented
HttpReply::status_type status_
std::string to_string(HttpReply::status_type status)
const std::string moved_permanently