NptHttp.h

00001 /*****************************************************************
00002 |
00003 |   Neptune - HTTP Protocol
00004 |
00005 |   (c) 2001-2006 Gilles Boccon-Gibod
00006 |   Author: Gilles Boccon-Gibod (bok@bok.net)
00007 |
00008  ****************************************************************/
00009 
00010 #ifndef _NPT_HTTP_H_
00011 #define _NPT_HTTP_H_
00012 
00013 /*----------------------------------------------------------------------
00014 |   includes
00015 +---------------------------------------------------------------------*/
00016 #include "NptUri.h"
00017 #include "NptTypes.h"
00018 #include "NptList.h"
00019 #include "NptBufferedStreams.h"
00020 #include "NptSockets.h"
00021 #include "NptMap.h"
00022 
00023 /*----------------------------------------------------------------------
00024 |   constants
00025 +---------------------------------------------------------------------*/
00026 const unsigned int NPT_HTTP_DEFAULT_PORT = 80;
00027 const unsigned int NPT_HTTP_INVALID_PORT = 0;
00028 
00029 const NPT_Timeout NPT_HTTP_CLIENT_DEFAULT_CONNECTION_TIMEOUT    = 30000;
00030 const NPT_Timeout NPT_HTTP_CLIENT_DEFAULT_IO_TIMEOUT            = 30000;
00031 const NPT_Timeout NPT_HTTP_CLIENT_DEFAULT_NAME_RESOLVER_TIMEOUT = 60000;
00032 
00033 const NPT_Timeout NPT_HTTP_SERVER_DEFAULT_CONNECTION_TIMEOUT    = NPT_TIMEOUT_INFINITE;
00034 const NPT_Timeout NPT_HTTP_SERVER_DEFAULT_IO_TIMEOUT            = 60000;
00035 
00036 const int NPT_HTTP_PROTOCOL_MAX_LINE_LENGTH  = 8192;
00037 const int NPT_HTTP_PROTOCOL_MAX_HEADER_COUNT = 100;
00038 
00039 #define NPT_HTTP_PROTOCOL_1_0   "HTTP/1.0"
00040 #define NPT_HTTP_PROTOCOL_1_1   "HTTP/1.1"
00041 #define NPT_HTTP_METHOD_GET     "GET"
00042 #define NPT_HTTP_METHOD_HEAD    "HEAD"
00043 #define NPT_HTTP_METHOD_POST    "POST"
00044 
00045 #define NPT_HTTP_HEADER_HOST                "Host"
00046 #define NPT_HTTP_HEADER_CONNECTION          "Connection"
00047 #define NPT_HTTP_HEADER_USER_AGENT          "User-Agent"
00048 #define NPT_HTTP_HEADER_CONTENT_LENGTH      "Content-Length"
00049 #define NPT_HTTP_HEADER_CONTENT_TYPE        "Content-Type"
00050 #define NPT_HTTP_HEADER_CONTENT_ENCODING    "Content-Encoding"
00051 #define NPT_HTTP_HEADER_LOCATION            "Location"
00052 #define NPT_HTTP_HEADER_RANGE               "Range"
00053 #define NPT_HTTP_HEADER_CONTENT_RANGE       "Content-Range"
00054 
00055 const int NPT_ERROR_HTTP_INVALID_RESPONSE_LINE = NPT_ERROR_BASE_HTTP - 0;
00056 const int NPT_ERROR_HTTP_INVALID_REQUEST_LINE  = NPT_ERROR_BASE_HTTP - 1;
00057 const int NPT_ERROR_HTTP_NO_PROXY              = NPT_ERROR_BASE_HTTP - 2;
00058 
00059 #define NPT_HTTP_LINE_TERMINATOR "\r\n"
00060 
00061 /*----------------------------------------------------------------------
00062 |   types
00063 +---------------------------------------------------------------------*/
00064 typedef unsigned int NPT_HttpStatusCode;
00065 
00066 /*----------------------------------------------------------------------
00067 |   NPT_HttpUrl
00068 +---------------------------------------------------------------------*/
00069 class NPT_HttpUrl : public NPT_Url {
00070 public:
00071     // constructors
00072     NPT_HttpUrl() {}
00073     NPT_HttpUrl(const char* url, bool ignore_scheme = false);
00074 
00075     // methods
00076     virtual NPT_String ToString(bool with_fragment = true) const;
00077 };
00078 
00079 /*----------------------------------------------------------------------
00080 |   NPT_HttpProtocol
00081 +---------------------------------------------------------------------*/
00082 class NPT_HttpProtocol
00083 {
00084 public:
00085     // class methods
00086     const char* GetSatusCodeString(NPT_HttpStatusCode status_code);
00087 };
00088 
00089 /*----------------------------------------------------------------------
00090 |   NPT_HttpHeader
00091 +---------------------------------------------------------------------*/
00092 class NPT_HttpHeader {
00093 public:
00094     // constructors and destructor
00095     NPT_HttpHeader(const char* name, const char* value);
00096     ~NPT_HttpHeader();
00097 
00098     // methods
00099     NPT_Result        Emit(NPT_OutputStream& stream) const;
00100     const NPT_String& GetName()  const { return m_Name;  }
00101     const NPT_String& GetValue() const { return m_Value; }
00102     NPT_Result        SetName(const char* name);
00103     NPT_Result        SetValue(const char* value);
00104 
00105 private:
00106     // members
00107     NPT_String m_Name;
00108     NPT_String m_Value;
00109 };
00110 
00111 /*----------------------------------------------------------------------
00112 |   NPT_HttpHeaders
00113 +---------------------------------------------------------------------*/
00114 class NPT_HttpHeaders {
00115 public:
00116     // constructors and destructor
00117      NPT_HttpHeaders();
00118     ~NPT_HttpHeaders();
00119 
00120     // methods
00121     NPT_Result Emit(NPT_OutputStream& stream) const;
00122     NPT_List<NPT_HttpHeader*>& GetHeaders() { return m_Headers; }
00123     NPT_HttpHeader* GetHeader(const char* name) const;
00124     NPT_Result SetHeader(const char* name, const char* value);
00125     NPT_Result GetHeaderValue(const char* name, NPT_String& value);
00126     NPT_Result AddHeader(const char* name, const char* value);
00127 
00128 private:
00129     // members
00130     NPT_List<NPT_HttpHeader*> m_Headers;
00131 };
00132 
00133 /*----------------------------------------------------------------------
00134 |   NPT_HttpEntity
00135 +---------------------------------------------------------------------*/
00136 class NPT_HttpEntity {
00137 public:
00138     // constructors and destructor
00139              NPT_HttpEntity();
00140              NPT_HttpEntity(const NPT_HttpHeaders& headers);
00141     virtual ~NPT_HttpEntity();
00142 
00143     // methods
00144     NPT_Result SetInputStream(const NPT_InputStreamReference& stream,
00145                               bool update_content_length = false);
00146     NPT_Result SetInputStream(const void* data, NPT_Size size);
00147     NPT_Result SetInputStream(const NPT_String& string);
00148     NPT_Result SetInputStream(const char* string);
00149     NPT_Result GetInputStream(NPT_InputStreamReference& stream);
00150     NPT_Result Load(NPT_DataBuffer& buffer);
00151     NPT_Result SetHeaders(const NPT_HttpHeaders& headers);
00152 
00153     // field access
00154     NPT_Result        SetContentType(const char* type);
00155     NPT_Result        SetContentEncoding(const char* encoding);
00156     NPT_Result        SetContentLength(NPT_Size length);
00157     NPT_Size          GetContentLength()   { return m_ContentLength;   }
00158     const NPT_String& GetContentType()     { return m_ContentType;     }
00159     const NPT_String& GetContentEncoding() { return m_ContentEncoding; }
00160 
00161 private:
00162     // members
00163     NPT_InputStreamReference m_InputStream;
00164     NPT_Size                 m_ContentLength;
00165     NPT_String               m_ContentType;
00166     NPT_String               m_ContentEncoding;
00167 };
00168 
00169 /*----------------------------------------------------------------------
00170 |   NPT_HttpMessage
00171 +---------------------------------------------------------------------*/
00172 class NPT_HttpMessage {
00173 public:
00174     // constructors and destructor
00175     virtual ~NPT_HttpMessage();
00176 
00177     // methods
00178     const NPT_String& GetProtocol() const { 
00179         return m_Protocol; 
00180     }
00181     NPT_Result SetProtocol(const char* protocol) {
00182         m_Protocol = protocol;
00183         return NPT_SUCCESS;
00184     }
00185     NPT_HttpHeaders& GetHeaders() { 
00186         return m_Headers;  
00187     }
00188     NPT_Result SetEntity(NPT_HttpEntity* entity);
00189     NPT_HttpEntity* GetEntity() {
00190         return m_Entity;
00191     }
00192     virtual NPT_Result ParseHeaders(NPT_BufferedInputStream& stream);
00193 
00194 protected:
00195     // constructors
00196     NPT_HttpMessage(const char* protocol);
00197 
00198     // members
00199     NPT_String      m_Protocol;
00200     NPT_HttpHeaders m_Headers;
00201     NPT_HttpEntity* m_Entity;
00202 };
00203 
00204 /*----------------------------------------------------------------------
00205 |   NPT_HttpRequest
00206 +---------------------------------------------------------------------*/
00207 class NPT_HttpRequest : public NPT_HttpMessage {
00208 public:
00209     // class methods
00210     static NPT_Result Parse(NPT_BufferedInputStream& stream, 
00211                             const NPT_SocketAddress* endpoint,
00212                             NPT_HttpRequest*&        request);
00213 
00214     // constructors and destructor
00215     NPT_HttpRequest(const NPT_HttpUrl& url,
00216                     const char*        method,
00217                     const char*        protocol = NPT_HTTP_PROTOCOL_1_0);
00218     NPT_HttpRequest(const char*        url,
00219                     const char*        method,
00220                     const char*        protocol = NPT_HTTP_PROTOCOL_1_0);
00221     virtual ~NPT_HttpRequest();
00222 
00223     // methods
00224     const NPT_HttpUrl& GetUrl() const { return m_Url; }
00225     NPT_HttpUrl&       GetUrl()       { return m_Url; }
00226     NPT_Result         SetUrl(const char* url);
00227     NPT_Result         SetUrl(const NPT_HttpUrl& url);
00228     const NPT_String&  GetMethod() const { return m_Method; }
00229     virtual NPT_Result Emit(NPT_OutputStream& stream, bool use_proxy=false) const;
00230     
00231 protected:
00232     // members
00233     NPT_HttpUrl m_Url;
00234     NPT_String  m_Method;
00235 };
00236 
00237 /*----------------------------------------------------------------------
00238 |   NPT_HttpResponse
00239 +---------------------------------------------------------------------*/
00240 class NPT_HttpResponse : public NPT_HttpMessage {
00241 public:
00242     // class methods
00243     static NPT_Result Parse(NPT_BufferedInputStream& stream, 
00244                             NPT_HttpResponse*&       response);
00245 
00246     // constructors and destructor
00247              NPT_HttpResponse(NPT_HttpStatusCode status_code,
00248                               const char*        reason_phrase,
00249                               const char*        protocol = NPT_HTTP_PROTOCOL_1_0);
00250     virtual ~NPT_HttpResponse();
00251 
00252     // methods
00253     NPT_Result         SetStatus(NPT_HttpStatusCode status_code,
00254                                  const char*        reason_phrase,
00255                                  const char*        protocol = NPT_HTTP_PROTOCOL_1_0);
00256     NPT_HttpStatusCode GetStatusCode()   { return m_StatusCode;   }
00257     NPT_String&        GetReasonPhrase() { return m_ReasonPhrase; }
00258     virtual NPT_Result Emit(NPT_OutputStream& stream) const;
00259 
00260 protected:
00261     // members
00262     NPT_HttpStatusCode m_StatusCode;
00263     NPT_String         m_ReasonPhrase;
00264 };
00265 
00266 /*----------------------------------------------------------------------
00267 |   NPT_HttpProxyAddress
00268 +---------------------------------------------------------------------*/
00269 class NPT_HttpProxyAddress
00270 {
00271 public:
00272     NPT_HttpProxyAddress() : m_Port(NPT_HTTP_INVALID_PORT) {}
00273     NPT_HttpProxyAddress(const char* hostname, NPT_UInt16 port) :
00274         m_HostName(hostname), m_Port(port) {}
00275 
00276     const NPT_String& GetHostName() const { return m_HostName; } 
00277     void              SetHostName(const char* hostname) { m_HostName = hostname; }
00278     NPT_UInt16        GetPort() const { return m_Port; }
00279     void              SetPort(NPT_UInt16 port) { m_Port = port; }
00280 
00281 private:
00282     NPT_String m_HostName;
00283     NPT_UInt16 m_Port;
00284 };
00285 
00286 /*----------------------------------------------------------------------
00287 |   NPT_HttpProxySelector
00288 +---------------------------------------------------------------------*/
00289 class NPT_HttpProxySelector
00290 {
00291 public:
00292     // class methods
00293     static NPT_HttpProxySelector* GetSystemDefault();
00294 
00295     // methods
00296     virtual ~NPT_HttpProxySelector() {};
00297     virtual NPT_Result GetProxyForUrl(const NPT_HttpUrl& url, NPT_HttpProxyAddress& proxy) = 0;
00298 };
00299 
00300 /*----------------------------------------------------------------------
00301 |   NPT_HttpClient
00302 +---------------------------------------------------------------------*/
00303 class NPT_HttpClient {
00304 public:
00305     // types
00306     struct Config {
00307         NPT_Timeout m_ConnectionTimeout;
00308         NPT_Timeout m_IoTimeout;
00309         NPT_Timeout m_NameResolverTimeout;
00310         bool        m_FollowRedirect;
00311     };
00312 
00313     class Connector {
00314     public:
00315         virtual ~Connector() {}
00316 
00317         virtual NPT_Result Connect(const char*                hostname, 
00318                                    NPT_UInt16                 port, 
00319                                    NPT_Timeout                connection_timeout,
00320                                    NPT_Timeout                io_timeout,
00321                                    NPT_Timeout                name_resolver_timeout,
00322                                    NPT_InputStreamReference&  input_stream,
00323                                    NPT_OutputStreamReference& output_stream) = 0;
00324 
00325     };
00326 
00331     NPT_HttpClient(Connector* connector = NULL);
00332 
00333     virtual ~NPT_HttpClient();
00334 
00335     // methods
00336     NPT_Result SendRequest(NPT_HttpRequest&   request,
00337                            NPT_HttpResponse*& response);
00338     NPT_Result SetConfig(const Config& config);
00339     NPT_Result SetProxy(const char* hostname, NPT_UInt16 port);
00340     NPT_Result SetProxySelector(NPT_HttpProxySelector* selector);
00341     NPT_Result SetTimeouts(NPT_Timeout connection_timeout,
00342                            NPT_Timeout io_timeout,
00343                            NPT_Timeout name_resolver_timeout);
00344 
00345 protected:
00346     // methods
00347     NPT_Result SendRequestOnce(NPT_HttpRequest&   request,
00348                                NPT_HttpResponse*& response);
00349 
00350     // members
00351     Config                 m_Config;
00352     NPT_HttpProxySelector* m_ProxySelector;
00353     bool                   m_ProxySelectorIsOwned;
00354     Connector*             m_Connector;
00355 };
00356 
00357 /*----------------------------------------------------------------------
00358 |   NPT_HttpRequestHandler
00359 +---------------------------------------------------------------------*/
00360 class NPT_HttpRequestHandler 
00361 {
00362 public:
00363     // destructor
00364     virtual ~NPT_HttpRequestHandler() {}
00365 
00366     // methods
00367     virtual NPT_Result SetupResponse(NPT_HttpRequest&  request,
00368                                      NPT_HttpResponse& response) = 0;
00369 };
00370 
00371 /*----------------------------------------------------------------------
00372 |   NPT_HttpStaticRequestHandler
00373 +---------------------------------------------------------------------*/
00374 class NPT_HttpStaticRequestHandler : public NPT_HttpRequestHandler
00375 {
00376 public:
00377     // constructors
00378     NPT_HttpStaticRequestHandler(const char* document, 
00379                                  const char* mime_type,
00380                                  bool        copy = true);
00381     NPT_HttpStaticRequestHandler(const void* data,
00382                                  NPT_Size    size,
00383                                  const char* mime_type,
00384                                  bool        copy = true);
00385 
00386     // NPT_HttpRequetsHandler methods
00387     virtual NPT_Result SetupResponse(NPT_HttpRequest&  request, 
00388                                      NPT_HttpResponse& response);
00389 
00390 private:
00391     NPT_String     m_MimeType;
00392     NPT_DataBuffer m_Buffer;
00393 };
00394 
00395 /*----------------------------------------------------------------------
00396 |   NPT_HttpFileRequestHandler
00397 +---------------------------------------------------------------------*/
00398 class NPT_HttpFileRequestHandler : public NPT_HttpRequestHandler
00399 {
00400 public:
00401     // constructors
00402     NPT_HttpFileRequestHandler(const char* url_root,
00403                                const char* file_root);
00404 
00405     // NPT_HttpRequetsHandler methods
00406     virtual NPT_Result SetupResponse(NPT_HttpRequest&  request, 
00407                                      NPT_HttpResponse& response);
00408 
00409     // accessors
00410     NPT_Map<NPT_String,NPT_String>& GetFileTypeMap() { return m_FileTypeMap; }
00411     void SetDefaultMimeType(const char* mime_type) {
00412         m_DefaultMimeType = mime_type;
00413     }
00414     void SetUseDefaultFileTypeMap(bool use_default) {
00415         m_UseDefaultFileTypeMap = use_default;
00416     }
00417 
00418 protected:
00419     // methods
00420     const char* GetContentType(const NPT_String& filename);
00421 
00422 private:
00423     NPT_String                      m_UrlRoot;
00424     NPT_String                      m_FileRoot;
00425     NPT_Map<NPT_String, NPT_String> m_FileTypeMap;
00426     NPT_String                      m_DefaultMimeType;
00427     bool                            m_UseDefaultFileTypeMap;
00428 };
00429 
00430 /*----------------------------------------------------------------------
00431 |   NPT_HttpServer
00432 +---------------------------------------------------------------------*/
00433 class NPT_HttpServer {
00434 public:
00435     // types
00436     struct Config {
00437         NPT_Timeout m_ConnectionTimeout;
00438         NPT_Timeout m_IoTimeout;
00439         NPT_UInt16  m_ListenPort;
00440     };
00441 
00442     // constructors and destructor
00443     NPT_HttpServer(NPT_UInt16 listen_port = NPT_HTTP_DEFAULT_PORT);
00444     virtual ~NPT_HttpServer();
00445 
00446     // methods
00447     NPT_Result SetConfig(const Config& config);
00448     NPT_Result SetListenPort(NPT_UInt16 port);
00449     NPT_Result SetTimeouts(NPT_Timeout connection_timeout, NPT_Timeout io_timeout);
00450     NPT_Result WaitForNewClient(NPT_InputStreamReference&  input,
00451                                 NPT_OutputStreamReference& output,
00452                                 NPT_SocketAddress*         local_address  = NULL,
00453                                 NPT_SocketAddress*         remote_address = NULL);
00454     
00459     NPT_Result AddRequestHandler(NPT_HttpRequestHandler* handler, const char* path, bool include_children = false);
00460     NPT_HttpRequestHandler* FindRequestHandler(NPT_HttpRequest& request);
00461 
00465     NPT_Result RespondToClient(NPT_InputStreamReference&  input,
00466                                NPT_OutputStreamReference& output,
00467                                NPT_SocketAddress*         local_address = NULL);
00468 
00469 protected:
00470     // types
00471     struct HandlerConfig {
00472         HandlerConfig(NPT_HttpRequestHandler* handler,
00473                       const char*             path,
00474                       bool                    include_children);
00475         ~HandlerConfig();
00476 
00477         // methods
00478         bool WillHandle(NPT_HttpRequest& request);
00479 
00480         // members
00481         NPT_HttpRequestHandler* m_Handler;
00482         NPT_String              m_Path;
00483         bool                    m_IncludeChildren;
00484     };
00485 
00486     // methods
00487     NPT_Result Bind();
00488 
00489     // members
00490     NPT_TcpServerSocket      m_Socket;
00491     NPT_UInt16               m_BoundPort;
00492     Config                   m_Config;
00493     NPT_List<HandlerConfig*> m_RequestHandlers;
00494 };
00495 
00496 /*----------------------------------------------------------------------
00497 |   NPT_HttpResponder
00498 +---------------------------------------------------------------------*/
00499 class NPT_HttpResponder {
00500 public:
00501     // types
00502     struct Config {
00503         NPT_Timeout m_IoTimeout;
00504     };
00505 
00506     // constructors and destructor
00507     NPT_HttpResponder(NPT_InputStreamReference&  input,
00508                       NPT_OutputStreamReference& output);
00509     virtual ~NPT_HttpResponder();
00510 
00511     // methods
00512     NPT_Result SetConfig(const Config& config);
00513     NPT_Result SetTimeout(NPT_Timeout io_timeout);
00514     NPT_Result ParseRequest(NPT_HttpRequest*&  request,
00515                             NPT_SocketAddress* local_address = NULL);
00516     NPT_Result SendResponse(NPT_HttpResponse& response,
00517                             bool              headers_only = false);
00518 
00519 protected:
00520     // members
00521     Config                           m_Config;
00522     NPT_BufferedInputStreamReference m_Input;
00523     NPT_OutputStreamReference        m_Output;
00524 };
00525 
00526 #endif // _NPT_HTTP_H_
00527