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