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 
00058 #define NPT_HTTP_LINE_TERMINATOR "\r\n"
00059 
00060 /*----------------------------------------------------------------------
00061 |   types
00062 +---------------------------------------------------------------------*/
00063 typedef unsigned int NPT_HttpStatusCode;
00064 
00065 /*----------------------------------------------------------------------
00066 |   NPT_HttpProtocol
00067 +---------------------------------------------------------------------*/
00068 class NPT_HttpProtocol
00069 {
00070 public:
00071     // class methods
00072     const char* GetSatusCodeString(NPT_HttpStatusCode status_code);
00073 };
00074 
00075 /*----------------------------------------------------------------------
00076 |   NPT_HttpUrlQuery
00077 +---------------------------------------------------------------------*/
00078 class NPT_HttpUrlQuery
00079 {
00080 public:
00081     // types
00082     struct Field {
00083         Field(const char* name, const char* value) :
00084             m_Name(name), m_Value(value) {}
00085         NPT_String m_Name;
00086         NPT_String m_Value;
00087     };
00088 
00089     // constructor
00090     NPT_HttpUrlQuery() {}
00091     NPT_HttpUrlQuery(const char* query);
00092 
00093     // accessors
00094     NPT_List<Field>& GetFields() { return m_Fields; }
00095 
00096     // methods
00097     NPT_Result  AddField(const char* name, const char* value);
00098     const char* GetField(const char* name);
00099     NPT_String  ToString();
00100 
00101 private:
00102     // members
00103     NPT_List<Field> m_Fields;
00104 };
00105 
00106 /*----------------------------------------------------------------------
00107 |   NPT_HttpUrl
00108 +---------------------------------------------------------------------*/
00109 class NPT_HttpUrl : public NPT_Uri {
00110 public:
00111     // constructors and destructor
00112     NPT_HttpUrl();
00113     NPT_HttpUrl(const char* url, bool ignore_scheme = false);
00114     NPT_HttpUrl(const char* host, 
00115                 NPT_UInt16  port, 
00116                 const char* path,
00117                 const char* query = NULL,
00118                 const char* fragment = NULL);
00119 
00120     // methods
00121     NPT_UInt16        GetPort() const     { return m_Port;     }
00122     const NPT_String& GetHost() const     { return m_Host;     }
00123     const NPT_String& GetPath() const     { return m_Path;     }
00124     const NPT_String& GetQuery() const    { return m_Query;    }
00125     const NPT_String& GetFragment() const { return m_Fragment; }
00126     bool              IsValid() const;
00127     bool              HasQuery()    const { return m_HasQuery;    } 
00128     bool              HasFragment() const { return m_HasFragment; }
00129     NPT_Result        SetHost(const char*  host);
00130     NPT_Result        SetPort(NPT_UInt16 port);
00131     NPT_Result        SetPath(const char*  path);
00132     NPT_Result        SetPathPlus(const char* path_plus);
00133     NPT_Result        SetQuery(const char* query);
00134     NPT_Result        SetFragment(const char* fragment);
00135     NPT_String        ToRequestString(bool with_fragment = false) const;
00136     NPT_String        ToString(bool with_fragment = true) const;
00137 
00138 private:
00139     // members
00140     NPT_String m_Host;
00141     NPT_UInt16 m_Port;
00142     NPT_String m_Path;
00143     bool       m_HasQuery;
00144     NPT_String m_Query;
00145     bool       m_HasFragment;
00146     NPT_String m_Fragment;
00147 };
00148 
00149 /*----------------------------------------------------------------------
00150 |   NPT_HttpHeader
00151 +---------------------------------------------------------------------*/
00152 class NPT_HttpHeader {
00153 public:
00154     // constructors and destructor
00155     NPT_HttpHeader(const char* name, const char* value);
00156     ~NPT_HttpHeader();
00157 
00158     // methods
00159     NPT_Result        Emit(NPT_OutputStream& stream) const;
00160     const NPT_String& GetName()  const { return m_Name;  }
00161     const NPT_String& GetValue() const { return m_Value; }
00162     NPT_Result        SetName(const char* name);
00163     NPT_Result        SetValue(const char* value);
00164 
00165 private:
00166     // members
00167     NPT_String m_Name;
00168     NPT_String m_Value;
00169 };
00170 
00171 /*----------------------------------------------------------------------
00172 |   NPT_HttpHeaders
00173 +---------------------------------------------------------------------*/
00174 class NPT_HttpHeaders {
00175 public:
00176     // constructors and destructor
00177      NPT_HttpHeaders();
00178     ~NPT_HttpHeaders();
00179 
00180     // methods
00181     NPT_Result Emit(NPT_OutputStream& stream) const;
00182     NPT_List<NPT_HttpHeader*>& GetHeaders() { return m_Headers; }
00183     NPT_HttpHeader* GetHeader(const char* name) const;
00184     NPT_Result SetHeader(const char* name, const char* value);
00185     NPT_Result GetHeaderValue(const char* name, NPT_String& value);
00186     NPT_Result AddHeader(const char* name, const char* value);
00187 
00188 private:
00189     // members
00190     NPT_List<NPT_HttpHeader*> m_Headers;
00191 };
00192 
00193 /*----------------------------------------------------------------------
00194 |   NPT_HttpEntity
00195 +---------------------------------------------------------------------*/
00196 class NPT_HttpEntity {
00197 public:
00198     // constructors and destructor
00199              NPT_HttpEntity();
00200              NPT_HttpEntity(const NPT_HttpHeaders& headers);
00201     virtual ~NPT_HttpEntity();
00202 
00203     // methods
00204     NPT_Result SetInputStream(const NPT_InputStreamReference& stream,
00205                               bool update_content_length = false);
00206     NPT_Result SetInputStream(const void* data, NPT_Size size);
00207     NPT_Result SetInputStream(const NPT_String& string);
00208     NPT_Result SetInputStream(const char* string);
00209     NPT_Result GetInputStream(NPT_InputStreamReference& stream);
00210     NPT_Result Load(NPT_DataBuffer& buffer);
00211     NPT_Result SetHeaders(const NPT_HttpHeaders& headers);
00212 
00213     // field access
00214     NPT_Result        SetContentType(const char* type);
00215     NPT_Result        SetContentEncoding(const char* encoding);
00216     NPT_Result        SetContentLength(NPT_Size length);
00217     NPT_Size          GetContentLength()   { return m_ContentLength;   }
00218     const NPT_String& GetContentType()     { return m_ContentType;     }
00219     const NPT_String& GetContentEncoding() { return m_ContentEncoding; }
00220 
00221 private:
00222     // members
00223     NPT_InputStreamReference m_InputStream;
00224     NPT_Size                 m_ContentLength;
00225     NPT_String               m_ContentType;
00226     NPT_String               m_ContentEncoding;
00227 };
00228 
00229 /*----------------------------------------------------------------------
00230 |   NPT_HttpMessage
00231 +---------------------------------------------------------------------*/
00232 class NPT_HttpMessage {
00233 public:
00234     // constructors and destructor
00235     virtual ~NPT_HttpMessage();
00236 
00237     // methods
00238     const NPT_String& GetProtocol() const { 
00239         return m_Protocol; 
00240     }
00241     NPT_Result SetProtocol(const char* protocol) {
00242         m_Protocol = protocol;
00243         return NPT_SUCCESS;
00244     }
00245     NPT_HttpHeaders& GetHeaders() { 
00246         return m_Headers;  
00247     }
00248     NPT_Result SetEntity(NPT_HttpEntity* entity);
00249     NPT_HttpEntity* GetEntity() {
00250         return m_Entity;
00251     }
00252     virtual NPT_Result ParseHeaders(NPT_BufferedInputStream& stream);
00253 
00254 protected:
00255     // constructors
00256     NPT_HttpMessage(const char* protocol);
00257 
00258     // members
00259     NPT_String      m_Protocol;
00260     NPT_HttpHeaders m_Headers;
00261     NPT_HttpEntity* m_Entity;
00262 };
00263 
00264 /*----------------------------------------------------------------------
00265 |   NPT_HttpRequest
00266 +---------------------------------------------------------------------*/
00267 class NPT_HttpRequest : public NPT_HttpMessage {
00268 public:
00269     // class methods
00270     static NPT_Result Parse(NPT_BufferedInputStream& stream, 
00271                             const NPT_SocketAddress* endpoint,
00272                             NPT_HttpRequest*&        request);
00273 
00274     // constructors and destructor
00275     NPT_HttpRequest(const NPT_HttpUrl& url,
00276                     const char*        method,
00277                     const char*        protocol = NPT_HTTP_PROTOCOL_1_0);
00278     NPT_HttpRequest(const char*        url,
00279                     const char*        method,
00280                     const char*        protocol = NPT_HTTP_PROTOCOL_1_0);
00281     virtual ~NPT_HttpRequest();
00282 
00283     // methods
00284     const NPT_HttpUrl& GetUrl() const { return m_Url; }
00285     NPT_HttpUrl&       GetUrl()       { return m_Url; }
00286     NPT_Result         SetUrl(const char* url);
00287     NPT_Result         SetUrl(const NPT_HttpUrl& url);
00288     const NPT_String&  GetMethod() const { return m_Method; }
00289     virtual NPT_Result Emit(NPT_OutputStream& stream, bool use_proxy=false) const;
00290     
00291 protected:
00292     // members
00293     NPT_HttpUrl m_Url;
00294     NPT_String  m_Method;
00295 };
00296 
00297 /*----------------------------------------------------------------------
00298 |   NPT_HttpResponse
00299 +---------------------------------------------------------------------*/
00300 class NPT_HttpResponse : public NPT_HttpMessage {
00301 public:
00302     // class methods
00303     static NPT_Result Parse(NPT_BufferedInputStream& stream, 
00304                             NPT_HttpResponse*&       response);
00305 
00306     // constructors and destructor
00307              NPT_HttpResponse(NPT_HttpStatusCode status_code,
00308                               const char*        reason_phrase,
00309                               const char*        protocol = NPT_HTTP_PROTOCOL_1_0);
00310     virtual ~NPT_HttpResponse();
00311 
00312     // methods
00313     NPT_Result         SetStatus(NPT_HttpStatusCode status_code,
00314                                  const char*        reason_phrase,
00315                                  const char*        protocol = NPT_HTTP_PROTOCOL_1_0);
00316     NPT_HttpStatusCode GetStatusCode()   { return m_StatusCode;   }
00317     NPT_String&        GetReasonPhrase() { return m_ReasonPhrase; }
00318     virtual NPT_Result Emit(NPT_OutputStream& stream) const;
00319 
00320 protected:
00321     // members
00322     NPT_HttpStatusCode m_StatusCode;
00323     NPT_String         m_ReasonPhrase;
00324 };
00325 
00326 /*----------------------------------------------------------------------
00327 |   NPT_HttpClient
00328 +---------------------------------------------------------------------*/
00329 class NPT_HttpClient {
00330 public:
00331     // types
00332     struct Config {
00333         NPT_Timeout m_ConnectionTimeout;
00334         NPT_Timeout m_IoTimeout;
00335         NPT_Timeout m_NameResolverTimeout;
00336         bool        m_UseProxy;
00337         NPT_String  m_ProxyHostname;
00338         NPT_UInt16  m_ProxyPort;
00339         bool        m_FollowRedirect;
00340     };
00341 
00342     // constructors and destructor
00343              NPT_HttpClient();
00344     virtual ~NPT_HttpClient();
00345 
00346     // methods
00347     NPT_Result SendRequest(NPT_HttpRequest&   request,
00348                            NPT_HttpResponse*& response);
00349     NPT_Result SetConfig(const Config& config);
00350     NPT_Result SetProxy(const char* hostname, NPT_UInt16 port);
00351     NPT_Result SetTimeouts(NPT_Timeout connection_timeout,
00352                            NPT_Timeout io_timeout,
00353                            NPT_Timeout name_resolver_timeout);
00354 
00355 protected:
00356     // methods
00357     NPT_Result SendRequestOnce(NPT_HttpRequest&   request,
00358                                NPT_HttpResponse*& response);
00359 
00360     // members
00361     Config m_Config;
00362 };
00363 
00364 /*----------------------------------------------------------------------
00365 |   NPT_HttpRequestHandler
00366 +---------------------------------------------------------------------*/
00367 class NPT_HttpRequestHandler 
00368 {
00369 public:
00370     // destructor
00371     virtual ~NPT_HttpRequestHandler() {}
00372 
00373     // methods
00374     virtual NPT_Result SetupResponse(NPT_HttpRequest&  request,
00375                                      NPT_HttpResponse& response,
00376                                      bool              headers_only) = 0;
00377 };
00378 
00379 /*----------------------------------------------------------------------
00380 |   NPT_HttpStaticRequestHandler
00381 +---------------------------------------------------------------------*/
00382 class NPT_HttpStaticRequestHandler : public NPT_HttpRequestHandler
00383 {
00384 public:
00385     // constructors
00386     NPT_HttpStaticRequestHandler(const char* document, 
00387                                  const char* mime_type,
00388                                  bool        copy = true);
00389     NPT_HttpStaticRequestHandler(const void* data,
00390                                  NPT_Size    size,
00391                                  const char* mime_type,
00392                                  bool        copy = true);
00393 
00394     // NPT_HttpRequetsHandler methods
00395     virtual NPT_Result SetupResponse(NPT_HttpRequest&  request, 
00396                                      NPT_HttpResponse& response,
00397                                      bool              headers_only);
00398 
00399 private:
00400     NPT_String     m_MimeType;
00401     NPT_DataBuffer m_Buffer;
00402 };
00403 
00404 /*----------------------------------------------------------------------
00405 |   NPT_HttpFileRequestHandler
00406 +---------------------------------------------------------------------*/
00407 class NPT_HttpFileRequestHandler : public NPT_HttpRequestHandler
00408 {
00409 public:
00410     // constructors
00411     NPT_HttpFileRequestHandler(const char* url_root,
00412                                const char* file_root);
00413 
00414     // NPT_HttpRequetsHandler methods
00415     virtual NPT_Result SetupResponse(NPT_HttpRequest&  request, 
00416                                      NPT_HttpResponse& response,
00417                                      bool              headers_only);
00418 
00419     // accessors
00420     NPT_Map<NPT_String,NPT_String>& GetFileTypeMap() { return m_FileTypeMap; }
00421     void SetDefaultMimeType(const char* mime_type) {
00422         m_DefaultMimeType = mime_type;
00423     }
00424     void SetUseDefaultFileTypeMap(bool use_default) {
00425         m_UseDefaultFileTypeMap = use_default;
00426     }
00427 
00428 protected:
00429     // methods
00430     const char* GetContentType(const NPT_String& filename);
00431 
00432 private:
00433     NPT_String                      m_UrlRoot;
00434     NPT_String                      m_FileRoot;
00435     NPT_Map<NPT_String, NPT_String> m_FileTypeMap;
00436     NPT_String                      m_DefaultMimeType;
00437     bool                            m_UseDefaultFileTypeMap;
00438 };
00439 
00440 /*----------------------------------------------------------------------
00441 |   NPT_HttpServer
00442 +---------------------------------------------------------------------*/
00443 class NPT_HttpServer {
00444 public:
00445     // types
00446     struct Config {
00447         NPT_Timeout m_ConnectionTimeout;
00448         NPT_Timeout m_IoTimeout;
00449         NPT_UInt16  m_ListenPort;
00450     };
00451 
00452     // constructors and destructor
00453     NPT_HttpServer();
00454     virtual ~NPT_HttpServer();
00455 
00456     // methods
00457     NPT_Result SetConfig(const Config& config);
00458     NPT_Result SetListenPort(NPT_UInt16 port);
00459     NPT_Result SetTimeouts(NPT_Timeout connection_timeout, NPT_Timeout io_timeout);
00460     NPT_Result WaitForNewClient(NPT_InputStreamReference&  input,
00461                                 NPT_OutputStreamReference& output,
00462                                 NPT_SocketAddress*         local_address  = NULL,
00463                                 NPT_SocketAddress*         remote_address = NULL);
00464     
00469     NPT_Result AddRequestHandler(NPT_HttpRequestHandler* handler, const char* path, bool include_children = false);
00470     NPT_HttpRequestHandler* FindRequestHandler(NPT_HttpRequest& request);
00471 
00475     NPT_Result RespondToClient(NPT_InputStreamReference&  input,
00476                                NPT_OutputStreamReference& output,
00477                                NPT_SocketAddress*         local_address = NULL);
00478 
00479 protected:
00480     // types
00481     struct HandlerConfig {
00482         HandlerConfig(NPT_HttpRequestHandler* handler,
00483                       const char*             path,
00484                       bool                    include_children);
00485         ~HandlerConfig();
00486 
00487         // methods
00488         bool WillHandle(NPT_HttpRequest& request);
00489 
00490         // members
00491         NPT_HttpRequestHandler* m_Handler;
00492         NPT_String              m_Path;
00493         bool                    m_IncludeChildren;
00494     };
00495 
00496     // members
00497     NPT_TcpServerSocket      m_Socket;
00498     Config                   m_Config;
00499     NPT_List<HandlerConfig*> m_RequestHandlers;
00500 };
00501 
00502 /*----------------------------------------------------------------------
00503 |   NPT_HttpResponder
00504 +---------------------------------------------------------------------*/
00505 class NPT_HttpResponder {
00506 public:
00507     // types
00508     struct Config {
00509         NPT_Timeout m_IoTimeout;
00510     };
00511 
00512     // constructors and destructor
00513     NPT_HttpResponder(NPT_InputStreamReference&  input,
00514                       NPT_OutputStreamReference& output);
00515     virtual ~NPT_HttpResponder();
00516 
00517     // methods
00518     NPT_Result SetConfig(const Config& config);
00519     NPT_Result SetTimeout(NPT_Timeout io_timeout);
00520     NPT_Result ParseRequest(NPT_HttpRequest*&  request,
00521                             NPT_SocketAddress* local_address = NULL);
00522     NPT_Result SendResponse(NPT_HttpResponse& response,
00523                             bool              headers_only = false);
00524 
00525 protected:
00526     // members
00527     Config                           m_Config;
00528     NPT_BufferedInputStreamReference m_Input;
00529     NPT_OutputStreamReference        m_Output;
00530 };
00531 
00532 #endif // _NPT_HTTP_H_