stream.h 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #pragma once
  2. #include "headers.h"
  3. #include <util/stream/output.h>
  4. #include <util/generic/maybe.h>
  5. #include <util/generic/ptr.h>
  6. #include <util/generic/string.h>
  7. #include <util/generic/strbuf.h>
  8. #include <util/generic/yexception.h>
  9. #include <util/generic/array_ref.h>
  10. class TSocket;
  11. struct THttpException: public yexception {
  12. };
  13. struct THttpParseException: public THttpException {
  14. };
  15. struct THttpReadException: public THttpException {
  16. };
  17. /// Чтение ответа HTTP-сервера.
  18. class THttpInput: public IInputStream {
  19. public:
  20. THttpInput(IInputStream* slave);
  21. THttpInput(THttpInput&& httpInput);
  22. ~THttpInput() override;
  23. /*
  24. * parsed http headers
  25. */
  26. /// Возвращает контейнер с заголовками ответа HTTP-сервера.
  27. const THttpHeaders& Headers() const noexcept;
  28. /*
  29. * parsed http trailers
  30. */
  31. /// Возвращает контейнер (возможно пустой) с trailer'ами ответа HTTP-сервера.
  32. /// Поток должен быть вычитан полностью прежде чем trailer'ы будут доступны.
  33. /// Пока поток не вычитан до конца возвращается Nothing.
  34. /// https://tools.ietf.org/html/rfc7230#section-4.1.2
  35. const TMaybe<THttpHeaders>& Trailers() const noexcept;
  36. /*
  37. * first line - response or request
  38. */
  39. /// Возвращает первую строку ответа HTTP-сервера.
  40. /// @details Первая строка HTTP-сервера - строка состояния,
  41. /// содержащая три поля: версию HTTP, код состояния и описание.
  42. const TString& FirstLine() const noexcept;
  43. /*
  44. * connection can be keep-alive
  45. */
  46. /// Проверяет, не завершено ли соединение с сервером.
  47. /// @details Транзакция считается завершенной, если не передан заголовок
  48. /// "Connection: Keep Alive".
  49. bool IsKeepAlive() const noexcept;
  50. /*
  51. * output data can be encoded
  52. */
  53. /// Проверяет, поддерживается ли данный тип кодирования содержимого
  54. /// ответа HTTP-сервера.
  55. bool AcceptEncoding(const TString& coding) const;
  56. /// Пытается определить наилучший тип кодирования ответа HTTP-сервера.
  57. /// @details Если ответ сервера говорит о том, что поддерживаются
  58. /// любые типы кодирования, выбирается gzip. В противном случае
  59. /// из списка типов кодирования выбирается лучший из поддерживаемых сервером.
  60. TString BestCompressionScheme() const;
  61. TString BestCompressionScheme(TArrayRef<const TStringBuf> codings) const;
  62. /// Если заголовки содержат Content-Length, возвращает true и
  63. /// записывает значение из заголовка в value
  64. bool GetContentLength(ui64& value) const noexcept;
  65. /// Признак запакованности данных, - если выставлен, то Content-Length, при наличии в заголовках,
  66. /// показывает объём запакованных данных, а из THttpInput мы будем вычитывать уже распакованные.
  67. bool ContentEncoded() const noexcept;
  68. /// Returns true if Content-Length or Transfer-Encoding header received
  69. bool HasContent() const noexcept;
  70. bool HasExpect100Continue() const noexcept;
  71. private:
  72. size_t DoRead(void* buf, size_t len) override;
  73. size_t DoSkip(size_t len) override;
  74. private:
  75. class TImpl;
  76. THolder<TImpl> Impl_;
  77. };
  78. /// Передача запроса HTTP-серверу.
  79. class THttpOutput: public IOutputStream {
  80. public:
  81. THttpOutput(IOutputStream* slave);
  82. THttpOutput(IOutputStream* slave, THttpInput* request);
  83. ~THttpOutput() override;
  84. /*
  85. * sent http headers
  86. */
  87. /// Возвращает контейнер с заголовками запроса к HTTP-серверу.
  88. const THttpHeaders& SentHeaders() const noexcept;
  89. /// Устанавливает режим, при котором сервер выдает ответ в упакованном виде.
  90. void EnableCompression(bool enable);
  91. void EnableCompression(TArrayRef<const TStringBuf> schemas);
  92. /// Устанавливает режим, при котором соединение с сервером не завершается
  93. /// после окончания транзакции.
  94. void EnableKeepAlive(bool enable);
  95. /// Устанавливает режим, при котором тело HTTP-запроса/ответа преобразуется в соответствии
  96. /// с заголовками Content-Encoding и Transfer-Encoding (включен по умолчанию)
  97. void EnableBodyEncoding(bool enable);
  98. /// Устанавливает режим, при котором тело HTTP-ответа сжимается кодеком
  99. /// указанным в Content-Encoding (включен по умолчанию)
  100. void EnableCompressionHeader(bool enable);
  101. /// Проверяет, производится ли выдача ответов в упакованном виде.
  102. bool IsCompressionEnabled() const noexcept;
  103. /// Проверяет, не завершается ли соединение с сервером после окончания транзакции.
  104. bool IsKeepAliveEnabled() const noexcept;
  105. /// Проверяет, преобразуется ли тело HTTP-запроса/ответа в соответствии
  106. /// с заголовками Content-Encoding и Transfer-Encoding
  107. bool IsBodyEncodingEnabled() const noexcept;
  108. /// Проверяет, сжимается ли тело HTTP-ответа кодеком
  109. /// указанным в Content-Encoding
  110. bool IsCompressionHeaderEnabled() const noexcept;
  111. /*
  112. * is this connection can be really keep-alive
  113. */
  114. /// Проверяет, можно ли установить режим, при котором соединение с сервером
  115. /// не завершается после окончания транзакции.
  116. bool CanBeKeepAlive() const noexcept;
  117. void SendContinue();
  118. /*
  119. * first line - response or request
  120. */
  121. /// Возвращает первую строку HTTP-запроса/ответа
  122. const TString& FirstLine() const noexcept;
  123. /// Возвращает размер отправленных данных (без заголовков, с учётом сжатия, без
  124. /// учёта chunked transfer encoding)
  125. size_t SentSize() const noexcept;
  126. private:
  127. void DoWrite(const void* buf, size_t len) override;
  128. void DoFlush() override;
  129. void DoFinish() override;
  130. private:
  131. class TImpl;
  132. THolder<TImpl> Impl_;
  133. };
  134. /// Возвращает код состояния из ответа сервера.
  135. unsigned ParseHttpRetCode(const TStringBuf& ret);
  136. /// Отправляет HTTP-серверу запрос с минимумом необходимых заголовков.
  137. void SendMinimalHttpRequest(TSocket& s, const TStringBuf& host, const TStringBuf& request, const TStringBuf& agent = "YandexSomething/1.0", const TStringBuf& from = "webadmin@yandex.ru");
  138. TArrayRef<const TStringBuf> SupportedCodings();
  139. /// @}