Request
This page shows how to use vix::Request in Vix Core.
Use it when you want to read the HTTP method, path, query parameters, route parameters, headers, body, JSON data, or request-scoped state.
Public header
#include <vix.hpp>You can also include the request header directly:
#include <vix/http/Request.hpp>What Request provides
vix::Request represents an incoming HTTP request.
It gives access to:
- HTTP method
- full target
- path without query string
- raw query string
- parsed query parameters
- route parameters
- request headers
- request body
- parsed JSON body
- request-scoped state
Most handlers receive a request by reference.
app.get("/", [](vix::Request &req, vix::Response &res)
{
(void)req;
res.text("Hello");
});2
3
4
5
6
Basic usage
#include <vix.hpp>
int main()
{
vix::App app;
app.get("/debug", [](vix::Request &req, vix::Response &res)
{
res.json({
"method", req.method(),
"path", req.path(),
"target", req.target()
});
});
app.run(8080);
return 0;
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Request:
GET /debug?page=1Example response:
{
"method": "GET",
"path": "/debug",
"target": "/debug?page=1"
}2
3
4
5
HTTP method
Use method() to read the request method.
app.get("/method", [](vix::Request &req, vix::Response &res)
{
res.json({
"method", req.method()
});
});2
3
4
5
6
Example:
GET
POST
PUT
PATCH
DELETE
HEAD
OPTIONS2
3
4
5
6
7
Target
Use target() to read the full request target.
The target includes the path and query string.
app.get("/debug", [](vix::Request &req, vix::Response &res)
{
res.json({
"target", req.target()
});
});2
3
4
5
6
Request:
GET /debug?page=2Example response:
{
"target": "/debug?page=2"
}2
3
Path
Use path() to read the path without the query string.
app.get("/debug", [](vix::Request &req, vix::Response &res)
{
res.json({
"path", req.path()
});
});2
3
4
5
6
Request:
GET /debug?page=2Example response:
{
"path": "/debug"
}2
3
Raw query string
Use query_string() to read the raw query string without ?.
app.get("/search", [](vix::Request &req, vix::Response &res)
{
res.json({
"query_string", req.query_string()
});
});2
3
4
5
6
Request:
GET /search?q=vix&page=2Example response:
{
"query_string": "q=vix&page=2"
}2
3
Query parameters
Use query_value(...) to read one query parameter.
app.get("/search", [](vix::Request &req, vix::Response &res)
{
const std::string q = req.query_value("q", "");
const std::string page = req.query_value("page", "1");
res.json({
"q", q,
"page", page
});
});2
3
4
5
6
7
8
9
10
Request:
GET /search?q=vix&page=2Example response:
{
"q": "vix",
"page": "2"
}2
3
4
Query fallback
The second argument to query_value(...) is the fallback value.
const std::string page = req.query_value("page", "1");If the query parameter is missing, the fallback is returned.
GET /search?q=vixResult:
page = 1Check query parameter
Use has_query(...).
app.get("/search", [](vix::Request &req, vix::Response &res)
{
if (!req.has_query("q"))
{
res.status(400).json({
"error", "missing query parameter q"
});
return;
}
res.json({
"q", req.query_value("q")
});
});2
3
4
5
6
7
8
9
10
11
12
13
14
Read all query parameters
Use query() to access the parsed query map.
app.get("/search", [](vix::Request &req, vix::Response &res)
{
const auto &query = req.query();
res.json({
"count", query.size()
});
});2
3
4
5
6
7
8
Route parameters
Use param(...) to read a route parameter.
app.get("/users/{id}", [](vix::Request &req, vix::Response &res)
{
res.json({
"id", req.param("id")
});
});2
3
4
5
6
Request:
GET /users/42Example response:
{
"id": "42"
}2
3
Route parameter fallback
Use the second argument to provide a fallback.
const std::string id = req.param("id", "unknown");If the parameter does not exist, the fallback is returned.
Check route parameter
Use has_param(...).
app.get("/users/{id}", [](vix::Request &req, vix::Response &res)
{
if (!req.has_param("id"))
{
res.status(400).json({
"error", "missing id"
});
return;
}
res.json({
"id", req.param("id")
});
});2
3
4
5
6
7
8
9
10
11
12
13
14
Read all route parameters
Use params().
app.get("/users/{user_id}/posts/{post_id}", [](vix::Request &req, vix::Response &res)
{
const auto ¶ms = req.params();
res.json({
"count", params.size(),
"user_id", req.param("user_id"),
"post_id", req.param("post_id")
});
});2
3
4
5
6
7
8
9
10
Request:
GET /users/7/posts/42Example response:
{
"count": 2,
"user_id": "7",
"post_id": "42"
}2
3
4
5
Headers
Use header(...) to read a header value.
app.get("/agent", [](vix::Request &req, vix::Response &res)
{
res.json({
"user_agent", req.header("User-Agent")
});
});2
3
4
5
6
If the header is missing, an empty string is returned.
Check header
Use has_header(...).
app.get("/auth", [](vix::Request &req, vix::Response &res)
{
if (!req.has_header("Authorization"))
{
res.status(401).json({
"error", "missing authorization header"
});
return;
}
res.json({
"authorized", true
});
});2
3
4
5
6
7
8
9
10
11
12
13
14
Read all headers
Use headers().
app.get("/headers", [](vix::Request &req, vix::Response &res)
{
const auto &headers = req.headers();
res.json({
"count", headers.size()
});
});2
3
4
5
6
7
8
Body
Use body() to read the raw request body.
app.post("/echo", [](vix::Request &req, vix::Response &res)
{
res.text(req.body());
});2
3
4
Request body:
hello from VixResponse:
hello from VixJSON body
Use json() to parse the body as JSON.
app.post("/json", [](vix::Request &req, vix::Response &res)
{
const auto &body = req.json();
res.json({
"received", body
});
});2
3
4
5
6
7
8
Request body:
{
"name": "Ada"
}2
3
Example response:
{
"received": {
"name": "Ada"
}
}2
3
4
5
Convert JSON body
Use json_as<T>() to convert the parsed JSON body to a type when supported.
auto value = req.json_as<MyType>();Example shape:
app.post("/users", [](vix::Request &req, vix::Response &res)
{
auto user = req.json_as<User>();
res.status(201).json({
"created", true
});
});2
3
4
5
6
7
8
The conversion depends on the JSON type support available for T.
Request state
RequestState is request-scoped storage.
Use it when middleware needs to pass data to handlers.
struct CurrentUser
{
std::string id;
};2
3
4
Middleware can store a value.
app.use([](vix::Request &req, vix::Response &res, vix::App::Next next)
{
(void)res;
req.state().set(CurrentUser{"42"});
next();
});2
3
4
5
6
7
8
A handler can read it later.
app.get("/me", [](vix::Request &req, vix::Response &res)
{
const auto &user = req.state().get<CurrentUser>();
res.json({
"id", user.id
});
});2
3
4
5
6
7
8
Check request state
Use has_state_type<T>().
if (req.has_state_type<CurrentUser>())
{
const auto &user = req.state().get<CurrentUser>();
}2
3
4
Optional request state
Use try_get<T>() when a value may be missing.
app.get("/me", [](vix::Request &req, vix::Response &res)
{
auto *user = req.state().try_get<CurrentUser>();
if (!user)
{
res.status(401).json({
"error", "unauthorized"
});
return;
}
res.json({
"id", user->id
});
});2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Store request state in middleware
#include <vix.hpp>
#include <string>
struct CurrentUser
{
std::string id;
};
int main()
{
vix::App app;
app.use("/api/private", [](vix::Request &req, vix::Response &res, vix::App::Next next)
{
const std::string token = req.header("Authorization");
if (token.empty())
{
res.status(401).json({
"error", "missing authorization header"
});
return;
}
req.state().set(CurrentUser{"42"});
next();
});
app.get("/api/private/me", [](vix::Request &req, vix::Response &res)
{
const auto &user = req.state().get<CurrentUser>();
res.json({
"id", user.id
});
});
app.run(8080);
return 0;
}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
38
39
40
41
42
43
Modify request fields
Most application code reads the request, but the request object also exposes setters.
Set the method:
req.set_method("GET");Set the target and recompute path/query caches:
req.set_target("/users?page=1");Set the body:
req.set_body("new body");Set a header:
req.set_header("X-App", "Vix");Remove a header:
req.remove_header("X-App");These APIs are mostly useful for middleware, testing, adapters, or advanced integrations.
Set route parameters
Use set_params(...) for advanced code that builds or adapts requests.
vix::Request::ParamMap params;
params["id"] = "42";
req.set_params(std::move(params));2
3
4
Normal route handlers should use req.param(...) instead.
Copy request with parameters
Use with_params(...) to return a copy of a request with new route parameters.
auto next_req = req.with_params({
"id", "42"
});2
3
This is mostly used internally by the request handler adapter.
Request lifecycle
A request is usually created by the HTTP session.
Transport read
-> HTTP parser
-> ParsedRequestHead
-> Request
-> Router
-> RequestHandler
-> user handler2
3
4
5
6
7
Application code normally receives it here:
app.get("/path", [](vix::Request &req, vix::Response &res)
{
// use req here
});2
3
4
Request and routing
The router uses:
req.method()
req.target()
req.path()2
3
Route parameters are added before the final user handler runs.
req.param("id");Query parameters are parsed from the target.
req.query_value("page");Request and middleware
Middleware receives the same request object as the handler.
app.use([](vix::Request &req, vix::Response &res, vix::App::Next next)
{
(void)res;
vix::print(req.method(), req.path());
next();
});2
3
4
5
6
7
8
Middleware can read request data, validate it, or attach state.
Complete example
#include <vix.hpp>
#include <string>
struct CurrentUser
{
std::string id;
};
int main()
{
vix::App app;
app.use("/api", [](vix::Request &req, vix::Response &res, vix::App::Next next)
{
res.header("X-API", "Vix");
next();
});
app.protect("/api/private", [](vix::Request &req, vix::Response &res, vix::App::Next next)
{
const std::string token = req.header("Authorization");
if (token.empty())
{
res.status(401).json({
"error", "missing authorization header"
});
return;
}
req.state().set(CurrentUser{"42"});
next();
});
app.get("/api/users/{id}", [](vix::Request &req, vix::Response &res)
{
res.json({
"id", req.param("id"),
"page", req.query_value("page", "1"),
"method", req.method(),
"path", req.path()
});
});
app.post("/api/echo", [](vix::Request &req, vix::Response &res)
{
res.json({
"body", req.body()
});
});
app.get("/api/private/me", [](vix::Request &req, vix::Response &res)
{
const auto &user = req.state().get<CurrentUser>();
res.json({
"id", user.id
});
});
app.run(8080);
return 0;
}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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
API summary
| API | Purpose |
|---|---|
method() | Return the HTTP method. |
set_method(method) | Set the HTTP method. |
target() | Return the full request target. |
set_target(target) | Set the target and recompute path/query data. |
path() | Return the path without query string. |
query_string() | Return the raw query string. |
query() | Return parsed query parameters. |
has_query(name) | Check whether a query parameter exists. |
query_value(name, fallback) | Return a query parameter value. |
params() | Return route parameters. |
set_params(params) | Replace route parameters. |
has_param(name) | Check whether a route parameter exists. |
param(name, fallback) | Return a route parameter value. |
headers() | Return all headers. |
set_headers(headers) | Replace all headers. |
header(name) | Return one header value. |
has_header(name) | Check whether a header exists. |
set_header(name, value) | Set one header. |
remove_header(name) | Remove one header. |
body() | Return the request body. |
set_body(body) | Replace the request body. |
json() | Parse and return the body as JSON. |
json_as<T>() | Convert the JSON body to type T. |
has_state() | Check whether state storage exists. |
state() | Access request-scoped state. |
has_state_type<T>() | Check whether state contains T. |
with_params(params) | Return a request copy with new parameters. |
Best practices
Use path() when matching or logging the route path.
vix::print(req.path());Use target() when you need the original path plus query string.
vix::print(req.target());Use fallbacks for optional query parameters.
const std::string page = req.query_value("page", "1");Use route parameters for resource identifiers.
const std::string id = req.param("id");Use middleware and RequestState for authenticated user data.
req.state().set(CurrentUser{"42"});Validate input before using it.
if (!req.has_query("q"))
{
res.status(400).json({"error", "missing q"});
return;
}2
3
4
5
Next steps
Read the next pages:
