00001
00002
00003
00004
00005
00006
00007
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 {
00030 namespace net {
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 }
00273 }
00274
00275 #endif