pion-net
4.0.9
|
00001 // ------------------------------------------------------------------ 00002 // pion-net: a C++ framework for building lightweight HTTP interfaces 00003 // ------------------------------------------------------------------ 00004 // Copyright (C) 2007-2008 Atomic Labs, Inc. (http://www.atomiclabs.com) 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_HTTPSERVER_HEADER__ 00011 #define __PION_HTTPSERVER_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/PionConfig.hpp> 00022 #include <pion/net/TCPServer.hpp> 00023 #include <pion/net/TCPConnection.hpp> 00024 #include <pion/net/HTTPRequest.hpp> 00025 #include <pion/net/HTTPAuth.hpp> 00026 #include <pion/net/HTTPParser.hpp> 00027 00028 00029 namespace pion { // begin namespace pion 00030 namespace net { // begin namespace net (Pion Network Library) 00031 00035 class PION_NET_API HTTPServer : 00036 public TCPServer 00037 { 00038 00039 public: 00040 00042 typedef boost::function2<void, HTTPRequestPtr&, TCPConnectionPtr&> RequestHandler; 00043 00045 typedef boost::function3<void, HTTPRequestPtr&, TCPConnectionPtr&, 00046 const std::string&> ServerErrorHandler; 00047 00048 00050 virtual ~HTTPServer() { if (isListening()) stop(); } 00051 00057 explicit HTTPServer(const unsigned int tcp_port = 0) 00058 : TCPServer(tcp_port), 00059 m_bad_request_handler(HTTPServer::handleBadRequest), 00060 m_not_found_handler(HTTPServer::handleNotFoundRequest), 00061 m_server_error_handler(HTTPServer::handleServerError), 00062 m_max_content_length(HTTPParser::DEFAULT_CONTENT_MAX) 00063 { 00064 setLogger(PION_GET_LOGGER("pion.net.HTTPServer")); 00065 } 00066 00072 explicit HTTPServer(const boost::asio::ip::tcp::endpoint& endpoint) 00073 : TCPServer(endpoint), 00074 m_bad_request_handler(HTTPServer::handleBadRequest), 00075 m_not_found_handler(HTTPServer::handleNotFoundRequest), 00076 m_server_error_handler(HTTPServer::handleServerError), 00077 m_max_content_length(HTTPParser::DEFAULT_CONTENT_MAX) 00078 { 00079 setLogger(PION_GET_LOGGER("pion.net.HTTPServer")); 00080 } 00081 00088 explicit HTTPServer(PionScheduler& scheduler, const unsigned int tcp_port = 0) 00089 : TCPServer(scheduler, tcp_port), 00090 m_bad_request_handler(HTTPServer::handleBadRequest), 00091 m_not_found_handler(HTTPServer::handleNotFoundRequest), 00092 m_server_error_handler(HTTPServer::handleServerError), 00093 m_max_content_length(HTTPParser::DEFAULT_CONTENT_MAX) 00094 { 00095 setLogger(PION_GET_LOGGER("pion.net.HTTPServer")); 00096 } 00097 00104 HTTPServer(PionScheduler& scheduler, const boost::asio::ip::tcp::endpoint& endpoint) 00105 : TCPServer(scheduler, endpoint), 00106 m_bad_request_handler(HTTPServer::handleBadRequest), 00107 m_not_found_handler(HTTPServer::handleNotFoundRequest), 00108 m_server_error_handler(HTTPServer::handleServerError), 00109 m_max_content_length(HTTPParser::DEFAULT_CONTENT_MAX) 00110 { 00111 setLogger(PION_GET_LOGGER("pion.net.HTTPServer")); 00112 } 00113 00120 void addResource(const std::string& resource, RequestHandler request_handler); 00121 00127 void removeResource(const std::string& resource); 00128 00135 void addRedirect(const std::string& requested_resource, const std::string& new_resource); 00136 00138 inline void setBadRequestHandler(RequestHandler h) { m_bad_request_handler = h; } 00139 00141 inline void setNotFoundHandler(RequestHandler h) { m_not_found_handler = h; } 00142 00144 inline void setServerErrorHandler(ServerErrorHandler h) { m_server_error_handler = h; } 00145 00147 virtual void clear(void) { 00148 if (isListening()) stop(); 00149 boost::mutex::scoped_lock resource_lock(m_resource_mutex); 00150 m_resources.clear(); 00151 } 00152 00159 static inline std::string stripTrailingSlash(const std::string& str) { 00160 std::string result(str); 00161 if (!result.empty() && result[result.size()-1]=='/') 00162 result.resize(result.size() - 1); 00163 return result; 00164 } 00165 00172 static void handleBadRequest(HTTPRequestPtr& http_request, 00173 TCPConnectionPtr& tcp_conn); 00174 00181 static void handleNotFoundRequest(HTTPRequestPtr& http_request, 00182 TCPConnectionPtr& tcp_conn); 00183 00191 static void handleServerError(HTTPRequestPtr& http_request, 00192 TCPConnectionPtr& tcp_conn, 00193 const std::string& error_msg); 00194 00202 static void handleForbiddenRequest(HTTPRequestPtr& http_request, 00203 TCPConnectionPtr& tcp_conn, 00204 const std::string& error_msg); 00205 00213 static void handleMethodNotAllowed(HTTPRequestPtr& http_request, 00214 TCPConnectionPtr& tcp_conn, 00215 const std::string& allowed_methods = ""); 00216 00220 inline void setAuthentication(HTTPAuthPtr auth) { m_auth = auth; } 00221 00223 inline void setMaxContentLength(std::size_t n) { m_max_content_length = n; } 00224 00225 protected: 00226 00232 virtual void handleConnection(TCPConnectionPtr& tcp_conn); 00233 00241 virtual void handleRequest(HTTPRequestPtr& http_request, 00242 TCPConnectionPtr& tcp_conn, const boost::system::error_code& ec); 00243 00250 virtual bool findRequestHandler(const std::string& resource, 00251 RequestHandler& request_handler) const; 00252 00253 00254 private: 00255 00257 static const unsigned int MAX_REDIRECTS; 00258 00260 typedef std::map<std::string, RequestHandler> ResourceMap; 00261 00263 typedef std::map<std::string, std::string> RedirectMap; 00264 00265 00267 ResourceMap m_resources; 00268 00270 RedirectMap m_redirects; 00271 00273 RequestHandler m_bad_request_handler; 00274 00276 RequestHandler m_not_found_handler; 00277 00279 ServerErrorHandler m_server_error_handler; 00280 00282 mutable boost::mutex m_resource_mutex; 00283 00285 HTTPAuthPtr m_auth; 00286 00288 std::size_t m_max_content_length; 00289 }; 00290 00291 00293 typedef boost::shared_ptr<HTTPServer> HTTPServerPtr; 00294 00295 00296 } // end namespace net 00297 } // end namespace pion 00298 00299 #endif