# 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