pion
5.0.6
|
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