pion-net  4.0.9
net/include/pion/net/HTTPServer.hpp
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