userver: HTTP, HTTPS, WebSocket
Loading...
Searching...
No Matches
HTTP, HTTPS, WebSocket

Introduction

🐙 userver implements HTTP/HTTPS 1.1 and WebSocket server in userver-core library using components::Server component.

Capabilities

Streaming API

Interactive clients (e.g. web browser) might want to get at least first bytes of the HTTP response if the whole HTTP response is generated slowly. In this case the HTTP handler might want to use Streaming API and return HTTP response body as a byte stream rather than as a single-part blob.

To enable Streaming API in your handler:

1) define HandleStreamRequest() method:

#include <userver/server/http/http_response_body_stream_fwd.hpp>
...
void HandleStreamRequest(const server::http::HttpRequest&,

2) Enable Streaming API in static config:

components_manager:
components:
handler-stream-api:
response-body-stream: true

3) Set dynamic config USERVER_HANDLER_STREAM_API_ENABLED.

4) Write your handler code:

void HandleStreamRequest(
const server::http::HttpRequest& request,
server::http::ResponseBodyStream& response_body_stream) const override {
for (const auto& header_name : request.GetHeaderNames()) {
const auto& header_value = request.GetHeader(header_name);
headers[header_name] = header_value;
}
const auto& port = request.GetArg("port");
auto url = fmt::format("http://localhost:{}/test", port);
const auto& timeout_string = request.GetArg("timeout");
const auto timeout = timeout_string.empty()
? kDefaultTimeout
: std::chrono::seconds{std::stoi(timeout_string)};
const auto retries = 1;
auto external_request = http_client_.CreateRequest()
.get(url)
.headers(std::move(headers))
.timeout(timeout)
.retry(retries);
auto client_response =
external_request.async_perform_stream_body(std::move(queue));
TESTPOINT("stream_after_start", {});
for (const auto& header_item : client_response.GetHeaders()) {
TESTPOINT("stream_after_get_headers", {});
const auto& header_name = header_item.first;
const auto& header_value = header_item.second;
response_body_stream.SetHeader(header_name, header_value);
}
auto status_code = client_response.StatusCode();
response_body_stream.SetStatusCode(status_code);
response_body_stream.SetHeader(std::string{"abc"}, std::string{"def"});
response_body_stream.SetEndOfHeaders();
TESTPOINT("stream_after_set_end_of_headers", {});
std::string body_part;
auto deadline = engine::Deadline::FromDuration(std::chrono::seconds(10));
while (client_response.ReadChunk(body_part, deadline)) {
TESTPOINT("stream_after_read_chunk", {});
response_body_stream.PushBodyChunk(std::move(body_part),
TESTPOINT("stream_after_push_body_chunk", {});
}
}

Components