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

Quality:

Introduction

🐙 userver implements HTTP/HTTPS 1.1, HTTP 2.0 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), engine::Deadline());
TESTPOINT("stream_after_push_body_chunk", {});
}
}

HTTP version

The HTTP server in userver supports versions 1.1 and 2.0. The default version is 1.1. You can enable version 2.0 in the static config such as:

# yaml
components_manager:
components:
# ... other components
server:
listener:
port: 8080
task_processor: main-task-processor
connection:
http-version: '2' # enum `1.1` or `2`
http2-session:
max_concurrent_streams: 100
max_frame_size: 16384
initial_window_size: 65536

You can set some options specific to HTTP/2.0 in the http2-session section. See docs for these options in components::Server

Components