HTTP.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * Copyright (c) 2013-2019, The PurpleI2P Project
  3. *
  4. * This file is part of Purple i2pd project and licensed under BSD3
  5. *
  6. * See full license text in LICENSE file at top of project tree
  7. */
  8. #ifndef HTTP_H__
  9. #define HTTP_H__
  10. #include <cstring>
  11. #include <map>
  12. #include <list>
  13. #include <sstream>
  14. #include <string>
  15. #include <vector>
  16. namespace i2p
  17. {
  18. namespace http
  19. {
  20. const char CRLF[] = "\r\n"; /**< HTTP line terminator */
  21. const char HTTP_EOH[] = "\r\n\r\n"; /**< HTTP end-of-headers mark */
  22. extern const std::vector<std::string> HTTP_METHODS; /**< list of valid HTTP methods */
  23. extern const std::vector<std::string> HTTP_VERSIONS; /**< list of valid HTTP versions */
  24. struct URL
  25. {
  26. std::string schema;
  27. std::string user;
  28. std::string pass;
  29. std::string host;
  30. unsigned short int port;
  31. std::string path;
  32. std::string query;
  33. std::string frag;
  34. URL(): schema(""), user(""), pass(""), host(""), port(0), path(""), query(""), frag("") {};
  35. /**
  36. * @brief Tries to parse url from string
  37. * @return true on success, false on invalid url
  38. */
  39. bool parse (const char *str, std::size_t len = 0);
  40. bool parse (const std::string& url);
  41. /**
  42. * @brief Parse query part of url to key/value map
  43. * @note Honestly, this should be implemented with std::multimap
  44. */
  45. bool parse_query(std::map<std::string, std::string> & params);
  46. /**
  47. * @brief Serialize URL structure to url
  48. * @note Returns relative url if schema if empty, absolute url otherwise
  49. */
  50. std::string to_string ();
  51. /**
  52. * @brief return true if the host is inside i2p
  53. */
  54. bool is_i2p() const;
  55. };
  56. struct HTTPMsg
  57. {
  58. std::map<std::string, std::string> headers;
  59. void add_header(const char *name, std::string & value, bool replace = false);
  60. void add_header(const char *name, const char *value, bool replace = false);
  61. void del_header(const char *name);
  62. /** @brief Returns declared message length or -1 if unknown */
  63. long int content_length() const;
  64. };
  65. struct HTTPReq
  66. {
  67. std::list<std::pair<std::string, std::string> > headers;
  68. std::string version;
  69. std::string method;
  70. std::string uri;
  71. HTTPReq (): version("HTTP/1.0"), method("GET"), uri("/") {};
  72. /**
  73. * @brief Tries to parse HTTP request from string
  74. * @return -1 on error, 0 on incomplete query, >0 on success
  75. * @note Positive return value is a size of header
  76. */
  77. int parse(const char *buf, size_t len);
  78. int parse(const std::string& buf);
  79. /** @brief Serialize HTTP request to string */
  80. std::string to_string();
  81. void write(std::ostream & o);
  82. void AddHeader (const std::string& name, const std::string& value);
  83. void UpdateHeader (const std::string& name, const std::string& value);
  84. void RemoveHeader (const std::string& name, const std::string& exempt); // remove all headers starting with name, but exempt
  85. void RemoveHeader (const std::string& name) { RemoveHeader (name, ""); };
  86. std::string GetHeader (const std::string& name) const;
  87. };
  88. struct HTTPRes : HTTPMsg {
  89. std::string version;
  90. std::string status;
  91. unsigned short int code;
  92. /**
  93. * @brief Simplifies response generation
  94. *
  95. * If this variable is set, on @a to_string() call:
  96. * * Content-Length header will be added if missing,
  97. * * contents of @a body will be included in generated response
  98. */
  99. std::string body;
  100. HTTPRes (): version("HTTP/1.1"), status("OK"), code(200) {}
  101. /**
  102. * @brief Tries to parse HTTP response from string
  103. * @return -1 on error, 0 on incomplete query, >0 on success
  104. * @note Positive return value is a size of header
  105. */
  106. int parse(const char *buf, size_t len);
  107. int parse(const std::string& buf);
  108. /**
  109. * @brief Serialize HTTP response to string
  110. * @note If @a version is set to HTTP/1.1, and Date header is missing,
  111. * it will be generated based on current time and added to headers
  112. * @note If @a body is set and Content-Length header is missing,
  113. * this header will be added, based on body's length
  114. */
  115. std::string to_string();
  116. void write(std::ostream & o);
  117. /** @brief Checks that response declared as chunked data */
  118. bool is_chunked() const ;
  119. /** @brief Checks that response contains compressed data */
  120. bool is_gzipped(bool includingI2PGzip = true) const;
  121. };
  122. /**
  123. * @brief returns HTTP status string by integer code
  124. * @param code HTTP code [100, 599]
  125. * @return Immutable string with status
  126. */
  127. const char * HTTPCodeToStatus(int code);
  128. /**
  129. * @brief Replaces %-encoded characters in string with their values
  130. * @param data Source string
  131. * @param null If set to true - decode also %00 sequence, otherwise - skip
  132. * @return Decoded string
  133. */
  134. std::string UrlDecode(const std::string& data, bool null = false);
  135. /**
  136. * @brief Merge HTTP response content with Transfer-Encoding: chunked
  137. * @param in Input stream
  138. * @param out Output stream
  139. * @return true on success, false otherwise
  140. */
  141. bool MergeChunkedResponse (std::istream& in, std::ostream& out);
  142. } // http
  143. } // i2p
  144. #endif /* HTTP_H__ */