httpheader.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. #pragma once
  2. #include "exthttpcodes.h"
  3. #include <library/cpp/mime/types/mime.h>
  4. #include <util/system/defaults.h>
  5. #include <util/system/compat.h>
  6. #include <util/generic/string.h>
  7. #include <util/generic/ylimits.h>
  8. #include <util/system/maxlen.h>
  9. #include <ctime>
  10. #include <cstdio>
  11. #include <cstdlib>
  12. #include <cstring>
  13. #include <algorithm>
  14. // This is ugly solution but here a lot of work to do it the right way.
  15. #define FETCHER_URL_MAX 8192
  16. extern const i64 DEFAULT_RETRY_AFTER; /// == -1
  17. extern const i64 DEFAULT_IF_MODIFIED_SINCE; /// == -1
  18. extern const i32 DEFAULT_MAX_AGE; /// == -1
  19. extern const i8 DEFAULT_REQUEST_PRIORITY; /// == -1
  20. extern const i32 DEFAULT_RESPONSE_TIMEOUT; /// == -1
  21. #define HTTP_PREFIX "http://"
  22. #define MAX_LANGREGION_LEN 4
  23. #define MAXWORD_LEN 55
  24. enum HTTP_COMPRESSION {
  25. HTTP_COMPRESSION_UNSET = 0,
  26. HTTP_COMPRESSION_ERROR = 1,
  27. HTTP_COMPRESSION_IDENTITY = 2,
  28. HTTP_COMPRESSION_GZIP = 3,
  29. HTTP_COMPRESSION_DEFLATE = 4,
  30. HTTP_COMPRESSION_COMPRESS = 5,
  31. HTTP_COMPRESSION_MAX = 6
  32. };
  33. enum HTTP_METHOD {
  34. HTTP_METHOD_UNDEFINED = -1,
  35. HTTP_METHOD_OPTIONS,
  36. HTTP_METHOD_GET,
  37. HTTP_METHOD_HEAD,
  38. HTTP_METHOD_POST,
  39. HTTP_METHOD_PUT,
  40. HTTP_METHOD_DELETE,
  41. HTTP_METHOD_TRACE,
  42. HTTP_METHOD_CONNECT,
  43. HTTP_METHOD_EXTENSION
  44. };
  45. enum HTTP_CONNECTION {
  46. HTTP_CONNECTION_UNDEFINED = -1,
  47. HTTP_CONNECTION_KEEP_ALIVE = 0,
  48. HTTP_CONNECTION_CLOSE = 1
  49. };
  50. /// Class represents general http header fields.
  51. struct THttpBaseHeader {
  52. public:
  53. i16 error;
  54. i32 header_size;
  55. i32 entity_size;
  56. i64 content_length;
  57. i64 http_time; // seconds since epoch
  58. i64 content_range_start; // Content-Range: first-byte-pos
  59. i64 content_range_end; // Content-Range: last-byte-pos
  60. i64 content_range_entity_length; // Content-Range: entity-length
  61. i8 http_minor;
  62. i8 mime_type;
  63. i8 charset;
  64. i8 compression_method;
  65. i8 transfer_chunked;
  66. i8 connection_closed;
  67. TString base;
  68. public:
  69. void Init() {
  70. error = 0;
  71. header_size = 0;
  72. entity_size = 0;
  73. content_length = -1;
  74. http_time = -1;
  75. http_minor = -1;
  76. mime_type = -1;
  77. charset = -1;
  78. compression_method = HTTP_COMPRESSION_UNSET;
  79. transfer_chunked = -1;
  80. connection_closed = HTTP_CONNECTION_UNDEFINED;
  81. content_range_start = -1;
  82. content_range_end = -1;
  83. content_range_entity_length = -1;
  84. base.clear();
  85. }
  86. void Print() const {
  87. printf("content_length: %" PRIi64 "\n", content_length);
  88. printf("http_time: %" PRIi64 "\n", http_time);
  89. printf("http_minor: %" PRIi8 "\n", http_minor);
  90. printf("mime_type: %" PRIi8 "\n", mime_type);
  91. printf("charset: %" PRIi8 "\n", charset);
  92. printf("compression_method: %" PRIi8 "\n", compression_method);
  93. printf("transfer_chunked: %" PRIi8 "\n", transfer_chunked);
  94. printf("connection_closed: %" PRIi8 "\n", connection_closed);
  95. printf("content_range_start: %" PRIi64 "\n", content_range_start);
  96. printf("content_range_end: %" PRIi64 "\n", content_range_end);
  97. printf("content_range_entity_length: %" PRIi64 "\n", content_range_entity_length);
  98. printf("base: \"%s\"\n", base.c_str());
  99. printf("error: %" PRIi16 "\n", error);
  100. }
  101. int SetBase(const char* path,
  102. const char* hostNamePtr = nullptr,
  103. int hostNameLength = 0) {
  104. if (*path == '/') {
  105. base = "http://";
  106. base += TStringBuf(hostNamePtr, hostNameLength);
  107. base += path;
  108. } else {
  109. base = path;
  110. }
  111. return error;
  112. }
  113. };
  114. enum { HREFLANG_MAX = FETCHER_URL_MAX * 2 };
  115. /// Class represents Http Response Header.
  116. struct THttpHeader: public THttpBaseHeader {
  117. public:
  118. i8 accept_ranges;
  119. i8 squid_error;
  120. i8 x_robots_tag; // deprecated, use x_robots_state instead
  121. i16 http_status;
  122. TString location;
  123. TString rel_canonical;
  124. char hreflangs[HREFLANG_MAX];
  125. i64 retry_after;
  126. TString x_robots_state; // 'xxxxx' format, see `library/html/zoneconf/parsefunc.cpp`
  127. public:
  128. void Init() {
  129. THttpBaseHeader::Init();
  130. accept_ranges = -1;
  131. squid_error = 0;
  132. x_robots_tag = 0;
  133. rel_canonical.clear();
  134. http_status = -1;
  135. location.clear();
  136. hreflangs[0] = 0;
  137. retry_after = DEFAULT_RETRY_AFTER;
  138. x_robots_state = "xxxxx";
  139. }
  140. void Print() const {
  141. THttpBaseHeader::Print();
  142. printf("http_status: %" PRIi16 "\n", http_status);
  143. printf("squid_error: %" PRIi8 "\n", squid_error);
  144. printf("accept_ranges: %" PRIi8 "\n", accept_ranges);
  145. printf("location: \"%s\"\n", location.c_str());
  146. printf("retry_after: %" PRIi64 "\n", retry_after);
  147. }
  148. };
  149. struct THttpRequestHeader: public THttpBaseHeader {
  150. public:
  151. TString request_uri;
  152. char host[HOST_MAX];
  153. char from[MAXWORD_LEN];
  154. char user_agent[MAXWORD_LEN];
  155. char x_yandex_langregion[MAX_LANGREGION_LEN];
  156. char x_yandex_sourcename[MAXWORD_LEN];
  157. char x_yandex_requesttype[MAXWORD_LEN];
  158. char x_yandex_fetchoptions[MAXWORD_LEN];
  159. i8 http_method;
  160. i8 x_yandex_request_priority;
  161. i32 x_yandex_response_timeout;
  162. i32 max_age;
  163. i64 if_modified_since;
  164. public:
  165. THttpRequestHeader() {
  166. Init();
  167. }
  168. void Init() {
  169. request_uri.clear();
  170. host[0] = 0;
  171. from[0] = 0;
  172. user_agent[0] = 0;
  173. x_yandex_langregion[0] = 0;
  174. x_yandex_sourcename[0] = 0;
  175. x_yandex_requesttype[0] = 0;
  176. x_yandex_fetchoptions[0] = 0;
  177. http_method = HTTP_METHOD_UNDEFINED;
  178. x_yandex_request_priority = DEFAULT_REQUEST_PRIORITY;
  179. x_yandex_response_timeout = DEFAULT_RESPONSE_TIMEOUT;
  180. max_age = DEFAULT_MAX_AGE;
  181. if_modified_since = DEFAULT_IF_MODIFIED_SINCE;
  182. THttpBaseHeader::Init();
  183. }
  184. void Print() const {
  185. THttpBaseHeader::Print();
  186. printf("request_uri: \"%s\"\n", request_uri.c_str());
  187. printf("host: \"%s\"\n", host);
  188. printf("from: \"%s\"\n", from);
  189. printf("user_agent: \"%s\"\n", user_agent);
  190. printf("http_method: %" PRIi8 "\n", http_method);
  191. printf("response_timeout: %" PRIi32 "\n", x_yandex_response_timeout);
  192. printf("max_age: %" PRIi32 "\n", max_age);
  193. printf("if_modified_since: %" PRIi64 "\n", if_modified_since);
  194. }
  195. /// It doesn't care about errors in request or headers, where
  196. /// request_uri equals to '*'.
  197. /// This returns copy of the string, which you have to delete.
  198. TString GetUrl() {
  199. TString url;
  200. if (host[0] == 0 || !strcmp(host, "")) {
  201. url = request_uri;
  202. } else {
  203. url = HTTP_PREFIX;
  204. url += host;
  205. url += request_uri;
  206. }
  207. return url;
  208. }
  209. char* GetUrl(char* buffer, size_t size) {
  210. if (host[0] == 0 || !strcmp(host, "")) {
  211. strlcpy(buffer, request_uri.c_str(), size);
  212. } else {
  213. snprintf(buffer, size, "http://%s%s", host, request_uri.c_str());
  214. }
  215. return buffer;
  216. }
  217. };
  218. class THttpAuthHeader: public THttpHeader {
  219. public:
  220. char* realm;
  221. char* nonce;
  222. char* opaque;
  223. bool stale;
  224. int algorithm;
  225. bool qop_auth;
  226. bool use_auth;
  227. //we do not provide auth-int variant as too heavy
  228. //bool qop_auth_int;
  229. THttpAuthHeader()
  230. : realm(nullptr)
  231. , nonce(nullptr)
  232. , opaque(nullptr)
  233. , stale(false)
  234. , algorithm(0)
  235. , qop_auth(false)
  236. , use_auth(true)
  237. {
  238. THttpHeader::Init();
  239. }
  240. ~THttpAuthHeader() {
  241. free(realm);
  242. free(nonce);
  243. free(opaque);
  244. }
  245. void Print() {
  246. THttpHeader::Print();
  247. if (use_auth) {
  248. if (realm)
  249. printf("realm: \"%s\"\n", realm);
  250. if (nonce)
  251. printf("nonce: \"%s\"\n", nonce);
  252. if (opaque)
  253. printf("opaque: \"%s\"\n", opaque);
  254. printf("stale: %d\n", stale);
  255. printf("algorithm: %d\n", algorithm);
  256. printf("qop_auth: %d\n", qop_auth);
  257. }
  258. }
  259. };