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 
00198     inline void setAuthentication(HTTPAuthPtr auth) { m_auth = auth; }
00199 
00201     inline void setMaxContentLength(std::size_t n) { m_max_content_length = n; }
00202 
00203 protected:
00204 
00210     virtual void handleConnection(TCPConnectionPtr& tcp_conn);
00211 
00218     void handleRequest(HTTPRequestPtr& http_request, TCPConnectionPtr& tcp_conn);
00219 
00226     bool findRequestHandler(const std::string& resource,
00227                             RequestHandler& request_handler) const;
00228 
00229 
00230 private:
00231 
00233     static const unsigned int   MAX_REDIRECTS;
00234 
00236     typedef std::map<std::string, RequestHandler>   ResourceMap;
00237 
00239     typedef std::map<std::string, std::string>      RedirectMap;
00240 
00241 
00243     ResourceMap                 m_resources;
00244 
00246     RedirectMap                 m_redirects;
00247 
00249     RequestHandler              m_bad_request_handler;
00250 
00252     RequestHandler              m_not_found_handler;
00253 
00255     ServerErrorHandler          m_server_error_handler;
00256 
00258     mutable boost::mutex        m_resource_mutex;
00259 
00261     HTTPAuthPtr                 m_auth;
00262 
00264     std::size_t                 m_max_content_length;
00265 };
00266 
00267 
00269 typedef boost::shared_ptr<HTTPServer>       HTTPServerPtr;
00270 
00271 
00272 }   // end namespace net
00273 }   // end namespace pion
00274 
00275 #endif

Generated on Fri Apr 30 14:48:53 2010 for pion-net by  doxygen 1.4.7