HTTP Request#
HttpRequest represents an HTTP request message with methods, headers, path, and query parameters.
It provides a clean API for building and parsing HTTP requests for both client and server applications.
HttpRequest is designed to be:
- complete — handles all HTTP request components
- flexible — supports all standard HTTP methods
- easy to use — intuitive API for headers and parameters
- standard-compliant — follows HTTP/1.1 specification
Basic usage#
Creating requests#
#include <join/httpmessage.hpp>
// Default GET request
HttpRequest req;
// Specify method
HttpRequest req(HttpMethod::Post);
// Set path and parameters
req.path("/api/users");
req.parameter("id", "123");
req.parameter("filter", "active");Setting headers#
HttpRequest req(HttpMethod::Get);
// Add headers
req.header("Accept", "application/json");
req.header("Authorization", "Bearer token123");
req.header("User-Agent", "MyApp/1.0");
// Check if header exists
if (req.hasHeader("Authorization"))
{
std::string auth = req.header("Authorization");
}HTTP methods#
Available methods#
// Standard HTTP methods
HttpRequest get(HttpMethod::Get); // GET
HttpRequest head(HttpMethod::Head); // HEAD
HttpRequest post(HttpMethod::Post); // POST
HttpRequest put(HttpMethod::Put); // PUT
HttpRequest del(HttpMethod::Delete); // DELETE
// Get method as string
std::string method = req.methodString(); // "GET", "POST", etc.
Path and parameters#
Setting path#
HttpRequest req;
// Simple path
req.path("/users");
// Path with segments
req.path("/api/v1/users/123");
// Get path
std::string path = req.path(); // "/api/v1/users/123"
Query parameters#
// Add parameters
req.parameter("page", "2");
req.parameter("limit", "50");
req.parameter("sort", "name");
// Check parameter
if (req.hasParameter("page"))
{
std::string page = req.parameter("page");
}
// Get all parameters
const auto& params = req.parameters();
// Get query string
std::string query = req.query(); // "?page=2&limit=50&sort=name"
URN (path + query)#
req.path("/search");
req.parameter("q", "test");
req.parameter("lang", "en");
std::string urn = req.urn(); // "/search?q=test&lang=en"
Headers#
Common headers#
HttpRequest req;
// Content type
req.header("Content-Type", "application/json");
// Content length
req.header("Content-Length", "1234");
// Accept
req.header("Accept", "application/json");
// Authorization
req.header("Authorization", "Bearer " + token);
// Custom headers
req.header("X-API-Key", apiKey);
req.header("X-Request-ID", requestId);Multiple headers#
HttpRequest::HeaderMap headers = {
{"Accept", "application/json"},
{"Accept-Encoding", "gzip, deflate"},
{"Accept-Language", "en-US,en;q=0.9"}
};
req.headers(headers);Request information#
Host and authorization#
// Get host from Host header
std::string host = req.host(); // "example.com" or "[::1]"
// Get authorization type
std::string authType = req.auth(); // "Bearer", "Basic", etc.
// Get credentials
std::string creds = req.credentials(); // Token or encoded credentials
Version#
// Set HTTP version
req.version("HTTP/1.1"); // Default
// Get version
std::string ver = req.version();Serialization#
Writing request#
HttpRequest req(HttpMethod::Post);
req.path("/api/submit");
req.header("Content-Type", "application/json");
req.header("Content-Length", "42");
// Write to stream
std::stringstream ss;
req.writeHeaders(ss);
// Output:
// POST /api/submit HTTP/1.1
// Content-Type: application/json
// Content-Length: 42
//
Reading request#
HttpRequest req;
// Read from stream
std::stringstream ss(requestData);
if (req.readHeaders(ss) == 0)
{
// Headers parsed successfully
std::string method = req.methodString();
std::string path = req.path();
}Common patterns#
Client request#
// Build GET request
HttpRequest req(HttpMethod::Get);
req.path("/api/data");
req.parameter("format", "json");
req.header("Accept", "application/json");
req.header("Authorization", "Bearer " + token);
// Send to server
client << req;API request with body#
// POST with JSON body
HttpRequest req(HttpMethod::Post);
req.path("/api/users");
req.header("Content-Type", "application/json");
std::string body = R"({"name":"Alice","age":30})";
req.header("Content-Length", std::to_string(body.size()));
// Send
client << req;
client << body;
client.flush();Form submission#
HttpRequest req(HttpMethod::Post);
req.path("/submit");
req.header("Content-Type", "application/x-www-form-urlencoded");
std::string formData = "name=Alice&email=alice%40example.com";
req.header("Content-Length", std::to_string(formData.size()));
client << req;
client << formData;
client.flush();Server usage#
Parsing incoming request#
// In server handler
HttpRequest req;
if (req.readHeaders(stream) == 0)
{
// Access request data
HttpMethod method = req.method();
std::string path = req.path();
std::string userAgent = req.header("User-Agent");
// Get query parameters
std::string id = req.parameter("id");
// Process request...
}Error handling#
HttpRequest req;
if (req.readHeaders(stream) == -1)
{
std::error_code ec = join::lastError;
if (ec == HttpErrc::BadRequest)
{
// Malformed request
}
else if (ec == HttpErrc::Unsupported)
{
// Unsupported method
}
else if (ec == HttpErrc::UriTooLong)
{
// URI exceeds limits
}
}Best practices#
URL encoding#
// Parameters are automatically URL-encoded when set
req.parameter("query", "hello world"); // Becomes "hello%20world"
req.parameter("email", "user@example.com"); // Becomes "user%40example.com"
Clear and reuse#
HttpRequest req;
for (const auto& endpoint : endpoints)
{
req.clear(); // Reset for reuse
req.method(HttpMethod::Get);
req.path(endpoint);
// Send request...
}Content length#
// Always set Content-Length for requests with body
std::string body = generateBody();
req.header("Content-Length", std::to_string(body.size()));Summary#
| Feature | Supported |
|---|---|
| All HTTP methods | ✅ |
| Headers | ✅ |
| Query parameters | ✅ |
| URL encoding | ✅ |
| Path normalization | ✅ |
| HTTP/1.1 | ✅ |
| Serialization | ✅ |
| Copy/move semantics | ✅ |