http_request_handler.cpp
Go to the documentation of this file.
00001 #include <boost/regex.hpp>
00002 #include <boost/noncopyable.hpp>
00003 #include <boost/shared_ptr.hpp>
00004 #include <boost/bind.hpp>
00005 #include <boost/enable_shared_from_this.hpp>
00006 #include "async_web_server_cpp/http_request_handler.hpp"
00007 #include "async_web_server_cpp/http_connection.hpp"
00008 #include "async_web_server_cpp/http_reply.hpp"
00009 
00010 namespace async_web_server_cpp
00011 {
00012 
00013 HttpRequestHandlerGroup::HttpRequestHandlerGroup(HttpServerRequestHandler default_handler)
00014   : default_handler_(default_handler)
00015 {
00016 }
00017 
00018 class PathMatcher
00019 {
00020 public:
00021   explicit PathMatcher(const std::string &path_regex_string)
00022     : path_regex_(boost::regex(path_regex_string))
00023   {
00024   }
00025 
00026   bool operator()(const HttpRequest &request)
00027   {
00028     return regex_match(request.path, path_regex_);
00029   }
00030 
00031 private:
00032   const boost::regex path_regex_;
00033 };
00034 
00035 void HttpRequestHandlerGroup::addHandlerForPath(const std::string &path_regex, HttpServerRequestHandler handler)
00036 {
00037   addHandler(PathMatcher(path_regex), handler);
00038 }
00039 
00040 void HttpRequestHandlerGroup::addHandler(HandlerPredicate predicate, HttpServerRequestHandler handler)
00041 {
00042   handlers_.push_back(std::make_pair(predicate, handler));
00043 }
00044 
00045 
00046 bool HttpRequestHandlerGroup::operator()(const HttpRequest &request, boost::shared_ptr<HttpConnection> connection, const char* begin, const char* end)
00047 {
00048   for (int i = 0; i < handlers_.size(); ++i)
00049   {
00050     std::pair<HandlerPredicate, HttpServerRequestHandler> &handler = handlers_[i];
00051     if (handler.first(request))
00052     {
00053       if(handler.second(request, connection, begin, end))
00054         return true;
00055     }
00056   }
00057   return default_handler_(request, connection, begin, end);
00058 }
00059 
00060 class BodyCollectingConnection;
00061 typedef boost::shared_ptr<BodyCollectingConnection> BodyCollectingConnectionPtr;
00062 typedef boost::weak_ptr<BodyCollectingConnection> BodyCollectingConnectionWeakPtr;
00063 class BodyCollectingConnection : public boost::enable_shared_from_this<BodyCollectingConnection>,
00064                                  private boost::noncopyable
00065 {
00066 public:
00067   BodyCollectingConnection(HttpRequestBodyCollector::Handler handler, const HttpRequest &request, boost::shared_ptr<HttpConnection> connection)
00068     : handler_(handler), request_(request), connection_(connection), received_length_(0) {
00069     std::string length_str = request_.get_header_value_or_default("Content-Length", "");
00070     try {
00071       length_ = boost::lexical_cast<ssize_t>(length_str);
00072     }
00073     catch(const boost::bad_lexical_cast &) {
00074       length_ = -1; //indicate error
00075     }
00076   }
00077 
00078   static void static_handle_read(BodyCollectingConnectionPtr _this, const char* begin, const char* end) {
00079     _this->handle_read(begin, end);
00080   }
00081   void handle_read(const char* begin, const char* end) {
00082     if(length_ < 0) {
00083       HttpReply::builder(HttpReply::bad_request).write(connection_);
00084       connection_->write("No Content-Length header");
00085       return;
00086     }
00087     std::string chunk(begin, end-begin);
00088     body_stream_ << chunk;
00089     received_length_ += chunk.length();
00090     if(received_length_ >= length_) {
00091       handler_(request_, connection_, body_stream_.str().substr(0, length_));
00092     }
00093     else {
00094       connection_->async_read(boost::bind(&BodyCollectingConnection::static_handle_read, shared_from_this(), _1, _2));
00095     }
00096   }
00097 
00098 private:
00099   HttpRequestBodyCollector::Handler handler_;
00100   const HttpRequest request_;
00101   boost::shared_ptr<HttpConnection> connection_;
00102   std::stringstream body_stream_;
00103   ssize_t length_;
00104   size_t received_length_;
00105 };
00106 
00107 HttpRequestBodyCollector::HttpRequestBodyCollector(Handler handler)
00108   : handler_(handler) {}
00109 
00110 bool HttpRequestBodyCollector::operator()(const HttpRequest &request, boost::shared_ptr<HttpConnection> connection, const char* begin, const char* end)
00111 {
00112   BodyCollectingConnectionPtr collecting_connection(new BodyCollectingConnection(handler_, request, connection));
00113   collecting_connection->handle_read(begin, end);
00114   return true;
00115 }
00116 
00117 }


async_web_server_cpp
Author(s): Mitchell Wills
autogenerated on Sat Jun 8 2019 18:56:50