diff options
author | Devtools Arcadia <[email protected]> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <[email protected]> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/http/io/stream.h |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/http/io/stream.h')
-rw-r--r-- | library/cpp/http/io/stream.h | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/library/cpp/http/io/stream.h b/library/cpp/http/io/stream.h new file mode 100644 index 00000000000..78ca4fc814c --- /dev/null +++ b/library/cpp/http/io/stream.h @@ -0,0 +1,178 @@ +#pragma once + +#include "headers.h" + +#include <util/stream/output.h> +#include <util/generic/maybe.h> +#include <util/generic/ptr.h> +#include <util/generic/string.h> +#include <util/generic/strbuf.h> +#include <util/generic/yexception.h> +#include <util/generic/array_ref.h> + +class TSocket; + +struct THttpException: public yexception { +}; + +struct THttpParseException: public THttpException { +}; + +struct THttpReadException: public THttpException { +}; + +/// Чтение ответа HTTP-сервера. +class THttpInput: public IInputStream { +public: + THttpInput(IInputStream* slave); + THttpInput(THttpInput&& httpInput); + ~THttpInput() override; + + /* + * parsed http headers + */ + /// Возвращает контейнер с заголовками ответа HTTP-сервера. + const THttpHeaders& Headers() const noexcept; + + /* + * parsed http trailers + */ + /// Возвращает контейнер (возможно пустой) с trailer'ами ответа HTTP-сервера. + /// Поток должен быть вычитан полностью прежде чем trailer'ы будут доступны. + /// Пока поток не вычитан до конца возвращается Nothing. + /// https://tools.ietf.org/html/rfc7230#section-4.1.2 + const TMaybe<THttpHeaders>& Trailers() const noexcept; + + /* + * first line - response or request + */ + /// Возвращает первую строку ответа HTTP-сервера. + /// @details Первая строка HTTP-сервера - строка состояния, + /// содержащая три поля: версию HTTP, код состояния и описание. + const TString& FirstLine() const noexcept; + + /* + * connection can be keep-alive + */ + /// Проверяет, не завершено ли соединение с сервером. + /// @details Транзакция считается завершенной, если не передан заголовок + /// "Connection: Keep Alive". + bool IsKeepAlive() const noexcept; + + /* + * output data can be encoded + */ + /// Проверяет, поддерживается ли данный тип кодирования содержимого + /// ответа HTTP-сервера. + bool AcceptEncoding(const TString& coding) const; + + /// Пытается определить наилучший тип кодирования ответа HTTP-сервера. + /// @details Если ответ сервера говорит о том, что поддерживаются + /// любые типы кодирования, выбирается gzip. В противном случае + /// из списка типов кодирования выбирается лучший из поддерживаемых сервером. + TString BestCompressionScheme() const; + TString BestCompressionScheme(TArrayRef<const TStringBuf> codings) const; + + /// Если заголовки содержат Content-Length, возвращает true и + /// записывает значение из заголовка в value + bool GetContentLength(ui64& value) const noexcept; + + /// Признак запакованности данных, - если выставлен, то Content-Length, при наличии в заголовках, + /// показывает объём запакованных данных, а из THttpInput мы будем вычитывать уже распакованные. + bool ContentEncoded() const noexcept; + + /// Returns true if Content-Length or Transfer-Encoding header received + bool HasContent() const noexcept; + + bool HasExpect100Continue() const noexcept; + +private: + size_t DoRead(void* buf, size_t len) override; + size_t DoSkip(size_t len) override; + +private: + class TImpl; + THolder<TImpl> Impl_; +}; + +/// Передача запроса HTTP-серверу. +class THttpOutput: public IOutputStream { +public: + THttpOutput(IOutputStream* slave); + THttpOutput(IOutputStream* slave, THttpInput* request); + ~THttpOutput() override; + + /* + * sent http headers + */ + /// Возвращает контейнер с заголовками запроса к HTTP-серверу. + const THttpHeaders& SentHeaders() const noexcept; + + /// Устанавливает режим, при котором сервер выдает ответ в упакованном виде. + void EnableCompression(bool enable); + void EnableCompression(TArrayRef<const TStringBuf> schemas); + + /// Устанавливает режим, при котором соединение с сервером не завершается + /// после окончания транзакции. + void EnableKeepAlive(bool enable); + + /// Устанавливает режим, при котором тело HTTP-запроса/ответа преобразуется в соответствии + /// с заголовками Content-Encoding и Transfer-Encoding (включен по умолчанию) + void EnableBodyEncoding(bool enable); + + /// Устанавливает режим, при котором тело HTTP-ответа сжимается кодеком + /// указанным в Content-Encoding (включен по умолчанию) + void EnableCompressionHeader(bool enable); + + /// Проверяет, производится ли выдача ответов в упакованном виде. + bool IsCompressionEnabled() const noexcept; + + /// Проверяет, не завершается ли соединение с сервером после окончания транзакции. + bool IsKeepAliveEnabled() const noexcept; + + /// Проверяет, преобразуется ли тело HTTP-запроса/ответа в соответствии + /// с заголовками Content-Encoding и Transfer-Encoding + bool IsBodyEncodingEnabled() const noexcept; + + /// Проверяет, сжимается ли тело HTTP-ответа кодеком + /// указанным в Content-Encoding + bool IsCompressionHeaderEnabled() const noexcept; + + /* + * is this connection can be really keep-alive + */ + /// Проверяет, можно ли установить режим, при котором соединение с сервером + /// не завершается после окончания транзакции. + bool CanBeKeepAlive() const noexcept; + + void SendContinue(); + + /* + * first line - response or request + */ + /// Возвращает первую строку HTTP-запроса/ответа + const TString& FirstLine() const noexcept; + + /// Возвращает размер отправленных данных (без заголовков, с учётом сжатия, без + /// учёта chunked transfer encoding) + size_t SentSize() const noexcept; + +private: + void DoWrite(const void* buf, size_t len) override; + void DoFlush() override; + void DoFinish() override; + +private: + class TImpl; + THolder<TImpl> Impl_; +}; + +/// Возвращает код состояния из ответа сервера. +unsigned ParseHttpRetCode(const TStringBuf& ret); + +/// Отправляет HTTP-серверу запрос с минимумом необходимых заголовков. +void SendMinimalHttpRequest(TSocket& s, const TStringBuf& host, const TStringBuf& request, const TStringBuf& agent = "YandexSomething/1.0", const TStringBuf& from = "[email protected]"); + +TArrayRef<const TStringBuf> SupportedCodings(); + +/// @} |