Request Options
vix::requests::RequestOptions defines how one outgoing request should be sent.
A request always has a method and a URL, but real HTTP calls often need more than that. They may need headers, query parameters, a timeout, authentication, redirect rules, TLS behavior, or a custom user agent. RequestOptions keeps those details in one object so the request call stays readable while still making the behavior explicit.
vix::requests::RequestOptions options;
options.headers.set("Accept", "application/json");
options.params.set("page", "1");
options.timeout = std::chrono::seconds(10);
auto response = vix::requests::get(
"https://example.com/api/items",
options);2
3
4
5
6
7
8
9
Use options when the request needs behavior that should not be hidden inside the URL or hardcoded into the transport layer.
Basic use
#include <vix/requests/requests.hpp>
#include <vix/print.hpp>
#include <chrono>
int main()
{
try
{
vix::requests::RequestOptions options;
options.headers.set("Accept", "application/json");
options.params.set("page", "1");
options.params.set("q", "vix requests");
options.timeout = std::chrono::seconds(10);
auto response = vix::requests::get(
"https://example.com/search",
options);
response.raise_for_status();
vix::print("status:", response.status_code());
vix::print("body:", response.text());
return 0;
}
catch (const vix::requests::RequestException &error)
{
vix::eprint("request failed:", error.what());
return 1;
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Run it:
vix run main.cppThe options object is passed to the request call. It does not change global behavior, and it does not affect other requests unless you reuse the same object yourself.
Headers
Headers are stored in options.headers.
vix::requests::RequestOptions options;
options.headers.set("Accept", "application/json");
options.headers.set("X-Client", "vix");2
3
4
The header container uses case-insensitive lookup. This matches how HTTP headers are normally treated, while still preserving the original casing used when the header was inserted.
options.headers.set("Content-Type", "application/json");
vix::print(options.headers.has("content-type"));
vix::print(options.headers.get("CONTENT-TYPE").value_or("missing"));2
3
4
Use set when the request should have one value for a header. Use append when multiple values are valid, such as repeated response-style headers. For normal outgoing request headers, set is usually the right choice.
Query params
Query parameters are stored in options.params.
vix::requests::RequestOptions options;
options.params.set("page", "1");
options.params.set("q", "vix requests");
auto response = vix::requests::get(
"https://example.com/search",
options);2
3
4
5
6
7
8
The params are appended to the URL before the request is sent. Values are URL-encoded, so spaces and reserved characters are handled by the module instead of being written manually in the URL string.
If the URL already has a query string, the new params are appended.
vix::requests::RequestOptions options;
options.params.set("page", "2");
auto response = vix::requests::get(
"https://example.com/search?sort=new",
options);2
3
4
5
6
The final request target is equivalent to:
/search?sort=new&page=2Timeout
The timeout setting controls how long the request should wait during network operations.
#include <chrono>
vix::requests::RequestOptions options;
options.timeout = std::chrono::seconds(10);2
3
4
5
Assigning one duration sets the same value for connect, read, and total timeout phases. This is the simplest form and is enough for most requests.
Use a Timeout object when the phases need different limits.
vix::requests::Timeout timeout;
timeout.set_connect(std::chrono::seconds(3));
timeout.set_read(std::chrono::seconds(10));
timeout.set_total(std::chrono::seconds(15));
vix::requests::RequestOptions options;
options.timeout = timeout;2
3
4
5
6
7
8
A timeout duration of zero means that no explicit timeout is configured for that phase. Negative timeout values are rejected.
Basic authentication
Use set_basic_auth when the request should send HTTP Basic authentication.
vix::requests::RequestOptions options;
options.set_basic_auth("username", "password");
auto response = vix::requests::get(
"https://example.com/private",
options);2
3
4
5
6
7
The module builds the Authorization header during request serialization. If the request already has an explicit Authorization header, that header is not overwritten.
vix::requests::RequestOptions options;
options.headers.set("Authorization", "Bearer token");
options.set_basic_auth("username", "password");2
3
4
In this case, the explicit Authorization header remains the one used by the request.
Redirects
Redirects are enabled by default.
vix::requests::RequestOptions options;
options.follow_redirects = true;
options.max_redirects = 10;2
3
4
When redirects are enabled, the client follows redirect responses such as 301, 302, 303, 307, and 308, then returns the final response.
auto response = vix::requests::get(
"https://example.com/old-path",
options);
vix::print("final url:", response.url());
vix::print("status:", response.status_code());2
3
4
5
6
Disable redirects when the application needs to inspect the redirect response itself.
vix::requests::RequestOptions options;
options.follow_redirects = false;
auto response = vix::requests::get(
"https://example.com/old-path",
options);
vix::print("status:", response.status_code());
vix::print("location:", response.location().value_or("none"));2
3
4
5
6
7
8
9
10
If a redirect chain is longer than max_redirects, or if it loops back to a URL that was already visited, the request raises TooManyRedirectsException.
TLS verification
HTTPS requests verify TLS certificates by default.
vix::requests::RequestOptions options;
options.verify_tls = true;
auto response = vix::requests::get(
"https://example.com/",
options);2
3
4
5
6
7
Keep TLS verification enabled for normal traffic. It protects the request from accepting a certificate that does not match the server.
For local development, self-signed certificates, or test fixtures, verification can be disabled for a specific request.
vix::requests::RequestOptions options;
options.verify_tls = false;
auto response = vix::requests::get(
"https://localhost:8443/",
options);2
3
4
5
6
7
Disabling TLS verification should be a local or controlled testing decision, not a default production setting.
Keep-alive
The keep_alive option controls the default Connection header when the request does not already set one.
vix::requests::RequestOptions options;
options.keep_alive = true;2
3
When keep_alive is true, the effective headers use:
Connection: keep-aliveWhen it is false, the effective headers use:
Connection: closeIf the request already has an explicit Connection header, the explicit value is preserved.
User agent
user_agent is sent when the request does not already provide a User-Agent header.
vix::requests::RequestOptions options;
options.set_user_agent("my-vix-client/1.0");
auto response = vix::requests::get(
"https://example.com/",
options);2
3
4
5
6
7
This is useful when calling APIs that expect clients to identify themselves. It also keeps the user agent close to the code that defines the client behavior.
An explicit User-Agent header takes priority.
vix::requests::RequestOptions options;
options.headers.set("User-Agent", "custom-agent");
options.set_user_agent("my-vix-client/1.0");2
3
4
The effective request uses custom-agent.
Host override
Most requests should use the host from the URL. host_override exists for cases where the request must connect to one URL but send a different Host header.
vix::requests::RequestOptions options;
options.set_host_override("api.internal");
auto response = vix::requests::get(
"https://127.0.0.1:8443/status",
options);2
3
4
5
6
7
Clear the override when it should no longer be used.
options.clear_host_override();Use host overrides carefully. They are useful for local testing, internal routing, and special deployment setups, but they can make request behavior harder to understand when used casually.
Effective headers
The module builds effective headers before sending the request. It keeps the headers provided in RequestOptions, then adds the defaults that are needed for HTTP serialization when they are missing.
The generated headers can include:
Host
User-Agent
Accept
Connection
Content-Type
Content-Length
Authorization2
3
4
5
6
7
Host, User-Agent, Accept, and Connection are added only when the request does not already define them. Content-Type and Content-Length are added when the request has a body and those headers are missing. Authorization is added for configured basic auth when no explicit authorization header exists.
This means the caller can stay concise for normal requests, while still keeping control when a header must be set manually.
Options with request bodies
For methods that send a body, the body argument comes before the options argument.
vix::requests::RequestOptions options;
options.headers.set("Accept", "application/json");
auto response = vix::requests::post(
"https://example.com/api/items",
vix::requests::json_body(R"({"name":"Vix"})"),
options);2
3
4
5
6
7
8
The same shape is used for post, put, and patch.
client.post(url, body, options);
client.put(url, body, options);
client.patch(url, body, options);
session.post(url, body, options);
session.put(url, body, options);
session.patch(url, body, options);2
3
4
5
6
7
For methods without a body, options come directly after the URL.
client.get(url, options);
client.del(url, options);
client.head(url, options);
session.get(url, options);
session.del(url, options);
session.head(url, options);2
3
4
5
6
7
Options with Session
A Session has default options. A request can still pass its own options for one call.
vix::requests::Session session;
session.set_header("Accept", "application/json");
session.timeout() = std::chrono::seconds(10);
vix::requests::RequestOptions options;
options.params.set("page", "1");
options.timeout = std::chrono::seconds(3);
auto response = session.get(
"https://example.com/api/items",
options);2
3
4
5
6
7
8
9
10
11
12
Use session defaults for values that describe the client as a whole. Use per-request options for values that belong to one request only, such as a page number, request id, or a short timeout for a specific endpoint.
Default values
A default RequestOptions object starts with the normal behavior expected for an HTTP client.
vix::requests::RequestOptions options;The important defaults are:
headers: empty
params: empty
timeout: no explicit timeout
auth: empty
follow_redirects: true
max_redirects: 10
verify_tls: true
keep_alive: true
user_agent: Vix requests user agent
host_override: empty2
3
4
5
6
7
8
9
10
These defaults keep simple requests short while still making the behavior configurable when needed.
Common mistakes
Putting query params directly into the URL when they are dynamic
This works for fixed URLs, but it becomes harder to read when values are computed.
auto response = vix::requests::get(
"https://example.com/search?page=1&q=vix%20requests");2
Prefer Params when the values come from code.
vix::requests::RequestOptions options;
options.params.set("page", "1");
options.params.set("q", "vix requests");
auto response = vix::requests::get(
"https://example.com/search",
options);2
3
4
5
6
7
8
The module handles encoding and keeps the URL readable.
Disabling TLS verification globally in your own code
Disabling TLS verification can be useful for local development, but it should be done only where the request needs it.
vix::requests::RequestOptions options;
options.verify_tls = false;
auto response = vix::requests::get(
"https://localhost:8443/",
options);2
3
4
5
6
For normal HTTPS traffic, leave verify_tls enabled.
Calling raise_for_status() too late
If the code depends on the request being successful, call raise_for_status() before using the response body.
auto response = vix::requests::get("https://example.com/api/items");
response.raise_for_status();
vix::print(response.text());2
3
4
5
This keeps the success path clear and moves HTTP error handling into the catch block.
API summary
struct BasicAuth
{
std::string username;
std::string password;
bool configured() const noexcept;
};
struct RequestOptions
{
Headers headers;
Params params;
Timeout timeout;
BasicAuth auth;
bool follow_redirects = true;
std::size_t max_redirects = 10;
bool verify_tls = true;
bool keep_alive = true;
std::string user_agent;
std::optional<std::string> host_override;
bool redirects_enabled() const noexcept;
bool has_user_agent() const noexcept;
bool has_host_override() const noexcept;
RequestOptions &set_basic_auth(
std::string username,
std::string password);
RequestOptions &set_timeout(Timeout::Duration value);
RequestOptions &set_user_agent(std::string value);
RequestOptions &set_host_override(std::string value);
RequestOptions &clear_host_override();
};2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
Helpers:
vix::requests::merge_request_options(baseOptions, overrideOptions);
vix::requests::has_option_header(options, name);2
Next step
Continue with headers and params. They are used often enough that it helps to understand how lookup, replacement, duplicates, and encoding behave.