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
00058 #define NPT_HTTP_LINE_TERMINATOR "\r\n"
00059
00060
00061
00062
00063 typedef unsigned int NPT_HttpStatusCode;
00064
00065
00066
00067
00068 class NPT_HttpProtocol
00069 {
00070 public:
00071
00072 const char* GetSatusCodeString(NPT_HttpStatusCode status_code);
00073 };
00074
00075
00076
00077
00078 class NPT_HttpUrlQuery
00079 {
00080 public:
00081
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
00090 NPT_HttpUrlQuery() {}
00091 NPT_HttpUrlQuery(const char* query);
00092
00093
00094 NPT_List<Field>& GetFields() { return m_Fields; }
00095
00096
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
00103 NPT_List<Field> m_Fields;
00104 };
00105
00106
00107
00108
00109 class NPT_HttpUrl : public NPT_Uri {
00110 public:
00111
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
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
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
00151
00152 class NPT_HttpHeader {
00153 public:
00154
00155 NPT_HttpHeader(const char* name, const char* value);
00156 ~NPT_HttpHeader();
00157
00158
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
00167 NPT_String m_Name;
00168 NPT_String m_Value;
00169 };
00170
00171
00172
00173
00174 class NPT_HttpHeaders {
00175 public:
00176
00177 NPT_HttpHeaders();
00178 ~NPT_HttpHeaders();
00179
00180
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
00190 NPT_List<NPT_HttpHeader*> m_Headers;
00191 };
00192
00193
00194
00195
00196 class NPT_HttpEntity {
00197 public:
00198
00199 NPT_HttpEntity();
00200 NPT_HttpEntity(const NPT_HttpHeaders& headers);
00201 virtual ~NPT_HttpEntity();
00202
00203
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
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
00223 NPT_InputStreamReference m_InputStream;
00224 NPT_Size m_ContentLength;
00225 NPT_String m_ContentType;
00226 NPT_String m_ContentEncoding;
00227 };
00228
00229
00230
00231
00232 class NPT_HttpMessage {
00233 public:
00234
00235 virtual ~NPT_HttpMessage();
00236
00237
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
00256 NPT_HttpMessage(const char* protocol);
00257
00258
00259 NPT_String m_Protocol;
00260 NPT_HttpHeaders m_Headers;
00261 NPT_HttpEntity* m_Entity;
00262 };
00263
00264
00265
00266
00267 class NPT_HttpRequest : public NPT_HttpMessage {
00268 public:
00269
00270 static NPT_Result Parse(NPT_BufferedInputStream& stream,
00271 const NPT_SocketAddress* endpoint,
00272 NPT_HttpRequest*& request);
00273
00274
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
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
00293 NPT_HttpUrl m_Url;
00294 NPT_String m_Method;
00295 };
00296
00297
00298
00299
00300 class NPT_HttpResponse : public NPT_HttpMessage {
00301 public:
00302
00303 static NPT_Result Parse(NPT_BufferedInputStream& stream,
00304 NPT_HttpResponse*& response);
00305
00306
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
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
00322 NPT_HttpStatusCode m_StatusCode;
00323 NPT_String m_ReasonPhrase;
00324 };
00325
00326
00327
00328
00329 class NPT_HttpClient {
00330 public:
00331
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
00343 NPT_HttpClient();
00344 virtual ~NPT_HttpClient();
00345
00346
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
00357 NPT_Result SendRequestOnce(NPT_HttpRequest& request,
00358 NPT_HttpResponse*& response);
00359
00360
00361 Config m_Config;
00362 };
00363
00364
00365
00366
00367 class NPT_HttpRequestHandler
00368 {
00369 public:
00370
00371 virtual ~NPT_HttpRequestHandler() {}
00372
00373
00374 virtual NPT_Result SetupResponse(NPT_HttpRequest& request,
00375 NPT_HttpResponse& response,
00376 bool headers_only) = 0;
00377 };
00378
00379
00380
00381
00382 class NPT_HttpStaticRequestHandler : public NPT_HttpRequestHandler
00383 {
00384 public:
00385
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
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
00406
00407 class NPT_HttpFileRequestHandler : public NPT_HttpRequestHandler
00408 {
00409 public:
00410
00411 NPT_HttpFileRequestHandler(const char* url_root,
00412 const char* file_root);
00413
00414
00415 virtual NPT_Result SetupResponse(NPT_HttpRequest& request,
00416 NPT_HttpResponse& response,
00417 bool headers_only);
00418
00419
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
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
00442
00443 class NPT_HttpServer {
00444 public:
00445
00446 struct Config {
00447 NPT_Timeout m_ConnectionTimeout;
00448 NPT_Timeout m_IoTimeout;
00449 NPT_UInt16 m_ListenPort;
00450 };
00451
00452
00453 NPT_HttpServer();
00454 virtual ~NPT_HttpServer();
00455
00456
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
00481 struct HandlerConfig {
00482 HandlerConfig(NPT_HttpRequestHandler* handler,
00483 const char* path,
00484 bool include_children);
00485 ~HandlerConfig();
00486
00487
00488 bool WillHandle(NPT_HttpRequest& request);
00489
00490
00491 NPT_HttpRequestHandler* m_Handler;
00492 NPT_String m_Path;
00493 bool m_IncludeChildren;
00494 };
00495
00496
00497 NPT_TcpServerSocket m_Socket;
00498 Config m_Config;
00499 NPT_List<HandlerConfig*> m_RequestHandlers;
00500 };
00501
00502
00503
00504
00505 class NPT_HttpResponder {
00506 public:
00507
00508 struct Config {
00509 NPT_Timeout m_IoTimeout;
00510 };
00511
00512
00513 NPT_HttpResponder(NPT_InputStreamReference& input,
00514 NPT_OutputStreamReference& output);
00515 virtual ~NPT_HttpResponder();
00516
00517
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
00527 Config m_Config;
00528 NPT_BufferedInputStreamReference m_Input;
00529 NPT_OutputStreamReference m_Output;
00530 };
00531
00532 #endif // _NPT_HTTP_H_