00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef _NPT_HTTP_H_
00011 #define _NPT_HTTP_H_
00012
00013
00014
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
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
00063
00064 typedef unsigned int NPT_HttpStatusCode;
00065
00066
00067
00068
00069 class NPT_HttpUrl : public NPT_Url {
00070 public:
00071
00072 NPT_HttpUrl() {}
00073 NPT_HttpUrl(const char* url, bool ignore_scheme = false);
00074
00075
00076 virtual NPT_String ToString(bool with_fragment = true) const;
00077 };
00078
00079
00080
00081
00082 class NPT_HttpProtocol
00083 {
00084 public:
00085
00086 const char* GetSatusCodeString(NPT_HttpStatusCode status_code);
00087 };
00088
00089
00090
00091
00092 class NPT_HttpHeader {
00093 public:
00094
00095 NPT_HttpHeader(const char* name, const char* value);
00096 ~NPT_HttpHeader();
00097
00098
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
00107 NPT_String m_Name;
00108 NPT_String m_Value;
00109 };
00110
00111
00112
00113
00114 class NPT_HttpHeaders {
00115 public:
00116
00117 NPT_HttpHeaders();
00118 ~NPT_HttpHeaders();
00119
00120
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
00130 NPT_List<NPT_HttpHeader*> m_Headers;
00131 };
00132
00133
00134
00135
00136 class NPT_HttpEntity {
00137 public:
00138
00139 NPT_HttpEntity();
00140 NPT_HttpEntity(const NPT_HttpHeaders& headers);
00141 virtual ~NPT_HttpEntity();
00142
00143
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
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
00163 NPT_InputStreamReference m_InputStream;
00164 NPT_Size m_ContentLength;
00165 NPT_String m_ContentType;
00166 NPT_String m_ContentEncoding;
00167 };
00168
00169
00170
00171
00172 class NPT_HttpMessage {
00173 public:
00174
00175 virtual ~NPT_HttpMessage();
00176
00177
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
00196 NPT_HttpMessage(const char* protocol);
00197
00198
00199 NPT_String m_Protocol;
00200 NPT_HttpHeaders m_Headers;
00201 NPT_HttpEntity* m_Entity;
00202 };
00203
00204
00205
00206
00207 class NPT_HttpRequest : public NPT_HttpMessage {
00208 public:
00209
00210 static NPT_Result Parse(NPT_BufferedInputStream& stream,
00211 const NPT_SocketAddress* endpoint,
00212 NPT_HttpRequest*& request);
00213
00214
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
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
00233 NPT_HttpUrl m_Url;
00234 NPT_String m_Method;
00235 };
00236
00237
00238
00239
00240 class NPT_HttpResponse : public NPT_HttpMessage {
00241 public:
00242
00243 static NPT_Result Parse(NPT_BufferedInputStream& stream,
00244 NPT_HttpResponse*& response);
00245
00246
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
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
00262 NPT_HttpStatusCode m_StatusCode;
00263 NPT_String m_ReasonPhrase;
00264 };
00265
00266
00267
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
00288
00289 class NPT_HttpProxySelector
00290 {
00291 public:
00292
00293 static NPT_HttpProxySelector* GetSystemDefault();
00294
00295
00296 virtual ~NPT_HttpProxySelector() {};
00297 virtual NPT_Result GetProxyForUrl(const NPT_HttpUrl& url, NPT_HttpProxyAddress& proxy) = 0;
00298 };
00299
00300
00301
00302
00303 class NPT_HttpClient {
00304 public:
00305
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
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
00347 NPT_Result SendRequestOnce(NPT_HttpRequest& request,
00348 NPT_HttpResponse*& response);
00349
00350
00351 Config m_Config;
00352 NPT_HttpProxySelector* m_ProxySelector;
00353 bool m_ProxySelectorIsOwned;
00354 Connector* m_Connector;
00355 };
00356
00357
00358
00359
00360 class NPT_HttpRequestHandler
00361 {
00362 public:
00363
00364 virtual ~NPT_HttpRequestHandler() {}
00365
00366
00367 virtual NPT_Result SetupResponse(NPT_HttpRequest& request,
00368 NPT_HttpResponse& response) = 0;
00369 };
00370
00371
00372
00373
00374 class NPT_HttpStaticRequestHandler : public NPT_HttpRequestHandler
00375 {
00376 public:
00377
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
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
00397
00398 class NPT_HttpFileRequestHandler : public NPT_HttpRequestHandler
00399 {
00400 public:
00401
00402 NPT_HttpFileRequestHandler(const char* url_root,
00403 const char* file_root);
00404
00405
00406 virtual NPT_Result SetupResponse(NPT_HttpRequest& request,
00407 NPT_HttpResponse& response);
00408
00409
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
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
00432
00433 class NPT_HttpServer {
00434 public:
00435
00436 struct Config {
00437 NPT_Timeout m_ConnectionTimeout;
00438 NPT_Timeout m_IoTimeout;
00439 NPT_UInt16 m_ListenPort;
00440 };
00441
00442
00443 NPT_HttpServer(NPT_UInt16 listen_port = NPT_HTTP_DEFAULT_PORT);
00444 virtual ~NPT_HttpServer();
00445
00446
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
00471 struct HandlerConfig {
00472 HandlerConfig(NPT_HttpRequestHandler* handler,
00473 const char* path,
00474 bool include_children);
00475 ~HandlerConfig();
00476
00477
00478 bool WillHandle(NPT_HttpRequest& request);
00479
00480
00481 NPT_HttpRequestHandler* m_Handler;
00482 NPT_String m_Path;
00483 bool m_IncludeChildren;
00484 };
00485
00486
00487 NPT_Result Bind();
00488
00489
00490 NPT_TcpServerSocket m_Socket;
00491 NPT_UInt16 m_BoundPort;
00492 Config m_Config;
00493 NPT_List<HandlerConfig*> m_RequestHandlers;
00494 };
00495
00496
00497
00498
00499 class NPT_HttpResponder {
00500 public:
00501
00502 struct Config {
00503 NPT_Timeout m_IoTimeout;
00504 };
00505
00506
00507 NPT_HttpResponder(NPT_InputStreamReference& input,
00508 NPT_OutputStreamReference& output);
00509 virtual ~NPT_HttpResponder();
00510
00511
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
00521 Config m_Config;
00522 NPT_BufferedInputStreamReference m_Input;
00523 NPT_OutputStreamReference m_Output;
00524 };
00525
00526 #endif // _NPT_HTTP_H_
00527