pion  5.0.6
include/pion/http/server.hpp
00001 // ---------------------------------------------------------------------
00002 // pion:  a Boost C++ framework for building lightweight HTTP interfaces
00003 // ---------------------------------------------------------------------
00004 // Copyright (C) 2007-2014 Splunk Inc.  (https://github.com/splunk/pion)
00005 //
00006 // Distributed under the Boost Software License, Version 1.0.
00007 // See http://www.boost.org/LICENSE_1_0.txt
00008 //
00009 
00010 #ifndef __PION_HTTP_SERVER_HEADER__
00011 #define __PION_HTTP_SERVER_HEADER__
00012 
00013 #include <map>
00014 #include <string>
00015 #include <boost/asio.hpp>
00016 #include <boost/function.hpp>
00017 #include <boost/function/function2.hpp>
00018 #include <boost/function/function3.hpp>
00019 #include <boost/shared_ptr.hpp>
00020 #include <boost/thread/mutex.hpp>
00021 #include <pion/config.hpp>
00022 #include <pion/tcp/server.hpp>
00023 #include <pion/tcp/connection.hpp>
00024 #include <pion/http/request.hpp>
00025 #include <pion/http/auth.hpp>
00026 #include <pion/http/parser.hpp>
00027 
00028 
00029 namespace pion {    // begin namespace pion
00030 namespace http {    // begin namespace http
00031 
00032 
00036 class PION_API server :
00037     public tcp::server
00038 {
00039 
00040 public:
00041 
00043     typedef boost::function2<void, http::request_ptr&, tcp::connection_ptr&>  request_handler_t;
00044 
00046     typedef boost::function3<void, http::request_ptr&, tcp::connection_ptr&,
00047         const std::string&> error_handler_t;
00048 
00049 
00051     virtual ~server() { if (is_listening()) stop(); }
00052 
00058     explicit server(const unsigned int tcp_port = 0)
00059         : tcp::server(tcp_port),
00060         m_bad_request_handler(server::handle_bad_request),
00061         m_not_found_handler(server::handle_not_found_request),
00062         m_server_error_handler(server::handle_server_error),
00063         m_max_content_length(http::parser::DEFAULT_CONTENT_MAX)
00064     { 
00065         set_logger(PION_GET_LOGGER("pion.http.server"));
00066     }
00067 
00073     explicit server(const boost::asio::ip::tcp::endpoint& endpoint)
00074         : tcp::server(endpoint),
00075         m_bad_request_handler(server::handle_bad_request),
00076         m_not_found_handler(server::handle_not_found_request),
00077         m_server_error_handler(server::handle_server_error),
00078         m_max_content_length(http::parser::DEFAULT_CONTENT_MAX)
00079     { 
00080         set_logger(PION_GET_LOGGER("pion.http.server"));
00081     }
00082 
00089     explicit server(scheduler& sched, const unsigned int tcp_port = 0)
00090         : tcp::server(sched, tcp_port),
00091         m_bad_request_handler(server::handle_bad_request),
00092         m_not_found_handler(server::handle_not_found_request),
00093         m_server_error_handler(server::handle_server_error),
00094         m_max_content_length(http::parser::DEFAULT_CONTENT_MAX)
00095     { 
00096         set_logger(PION_GET_LOGGER("pion.http.server"));
00097     }
00098 
00105     server(scheduler& sched, const boost::asio::ip::tcp::endpoint& endpoint)
00106         : tcp::server(sched, endpoint),
00107         m_bad_request_handler(server::handle_bad_request),
00108         m_not_found_handler(server::handle_not_found_request),
00109         m_server_error_handler(server::handle_server_error),
00110         m_max_content_length(http::parser::DEFAULT_CONTENT_MAX)
00111     { 
00112         set_logger(PION_GET_LOGGER("pion.http.server"));
00113     }
00114 
00121     void add_resource(const std::string& resource, request_handler_t request_handler);
00122 
00128     void remove_resource(const std::string& resource);
00129 
00136     void add_redirect(const std::string& requested_resource, const std::string& new_resource);
00137 
00139     inline void set_bad_request_handler(request_handler_t h) { m_bad_request_handler = h; }
00140 
00142     inline void set_not_found_handler(request_handler_t h) { m_not_found_handler = h; }
00143 
00145     inline void set_error_handler(error_handler_t h) { m_server_error_handler = h; }
00146 
00148     virtual void clear(void) {
00149         if (is_listening()) stop();
00150         boost::mutex::scoped_lock resource_lock(m_resource_mutex);
00151         m_resources.clear();
00152     }
00153 
00160     static inline std::string strip_trailing_slash(const std::string& str) {
00161         std::string result(str);
00162         if (!result.empty() && result[result.size()-1]=='/')
00163             result.resize(result.size() - 1);
00164         return result;
00165     }
00166 
00173     static void handle_bad_request(http::request_ptr& http_request_ptr,
00174                                  tcp::connection_ptr& tcp_conn);
00175 
00182     static void handle_not_found_request(http::request_ptr& http_request_ptr,
00183                                       tcp::connection_ptr& tcp_conn);
00184 
00192     static void handle_server_error(http::request_ptr& http_request_ptr,
00193                                   tcp::connection_ptr& tcp_conn,
00194                                   const std::string& error_msg);
00195 
00203     static void handle_forbidden_request(http::request_ptr& http_request_ptr,
00204                                        tcp::connection_ptr& tcp_conn,
00205                                        const std::string& error_msg);
00206 
00214     static void handle_method_not_allowed(http::request_ptr& http_request_ptr,
00215                                        tcp::connection_ptr& tcp_conn,
00216                                        const std::string& allowed_methods = "");
00217 
00221     inline void set_authentication(http::auth_ptr auth) { m_auth_ptr = auth; }
00222 
00224     inline void set_max_content_length(std::size_t n) { m_max_content_length = n; }
00225 
00226 protected:
00227 
00233     virtual void handle_connection(tcp::connection_ptr& tcp_conn);
00234 
00242     virtual void handle_request(http::request_ptr& http_request_ptr,
00243                                 tcp::connection_ptr& tcp_conn, const boost::system::error_code& ec);
00244 
00251     virtual bool find_request_handler(const std::string& resource,
00252                                       request_handler_t& request_handler) const;
00253 
00254 
00255 private:
00256 
00258     static const unsigned int   MAX_REDIRECTS;
00259 
00261     typedef std::map<std::string, request_handler_t>    resource_map_t;
00262 
00264     typedef std::map<std::string, std::string>          redirect_map_t;
00265 
00266 
00268     resource_map_t              m_resources;
00269 
00271     redirect_map_t              m_redirects;
00272 
00274     request_handler_t           m_bad_request_handler;
00275 
00277     request_handler_t           m_not_found_handler;
00278 
00280     error_handler_t             m_server_error_handler;
00281 
00283     mutable boost::mutex        m_resource_mutex;
00284 
00286     http::auth_ptr              m_auth_ptr;
00287 
00289     std::size_t                 m_max_content_length;
00290 };
00291 
00292 
00294 typedef boost::shared_ptr<server>   server_ptr;
00295 
00296 
00297 }   // end namespace http
00298 }   // end namespace pion
00299 
00300 #endif