HTTP Response
HttpResponse represents an HTTP response message with status code, reason phrase, and headers.
It provides methods for building and parsing HTTP responses in both client and server contexts.
HttpResponse is designed to be:
- simple — easy status and header management
- standard — follows HTTP/1.1 response format
- flexible — works with clients and servers
- efficient — minimal overhead
Basic usage
Creating responses
// libjoin.
#include <join/httpmessage.hpp>
// Create response
HttpResponse res;
// Set status and reason
res.response("200", "OK");
res.response("404", "Not Found");
res.response("500", "Internal Server Error");Setting headers
HttpResponse res;
res.response("200", "OK");
// Add headers
res.header("Content-Type", "application/json");
res.header("Content-Length", "123");
res.header("Cache-Control", "no-cache");Status codes
Common status codes
// Success
res.response("200", "OK");
res.response("201", "Created");
res.response("204", "No Content");
// Redirection
res.response("301", "Moved Permanently");
res.response("302", "Found");
res.response("304", "Not Modified");
// Client errors
res.response("400", "Bad Request");
res.response("401", "Unauthorized");
res.response("403", "Forbidden");
res.response("404", "Not Found");
// Server errors
res.response("500", "Internal Server Error");
res.response("502", "Bad Gateway");
res.response("503", "Service Unavailable");Getting status
HttpResponse res;
res.response("200", "OK");
std::string status = res.status(); // "200"
std::string reason = res.reason(); // "OK"
Headers
Content headers
HttpResponse res;
res.response("200", "OK");
// Content type
res.header("Content-Type", "text/html; charset=utf-8");
res.header("Content-Type", "application/json");
res.header("Content-Type", "image/png");
// Content length
res.header("Content-Length", std::to_string(bodySize));
// Content encoding
res.header("Content-Encoding", "gzip");Caching headers
// No caching
res.header("Cache-Control", "no-cache, no-store, must-revalidate");
res.header("Pragma", "no-cache");
res.header("Expires", "0");
// Cache for 1 hour
res.header("Cache-Control", "public, max-age=3600");
// Last modified
res.header("Last-Modified", "Wed, 21 Oct 2015 07:28:00 GMT");
res.header("ETag", "\"33a64df551425fcc55e4d42a148795d9f25f89d4\"");CORS headers
// Allow cross-origin requests
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
res.header("Access-Control-Allow-Headers", "Content-Type, Authorization");
res.header("Access-Control-Max-Age", "86400");Serialization
Writing response
HttpResponse res;
res.response("200", "OK");
res.header("Content-Type", "text/plain");
res.header("Content-Length", "13");
// Write to stream
std::stringstream ss;
res.writeHeaders(ss);
ss << "Hello, World!";
// Output:
// HTTP/1.1 200 OK
// Content-Type: text/plain
// Content-Length: 13
//
// Hello, World!
Reading response
HttpResponse res;
// Read from stream
if (res.readHeaders(stream) == 0)
{
// Headers parsed successfully
std::string status = res.status();
std::string reason = res.reason();
// Check content length
size_t length = res.contentLength();
}Common patterns
Success response
HttpResponse res;
res.response("200", "OK");
res.header("Content-Type", "application/json");
std::string json = R"({"status":"success"})";
res.header("Content-Length", std::to_string(json.size()));
stream << res;
stream << json;
stream.flush();Error response
HttpResponse res;
res.response("404", "Not Found");
res.header("Content-Type", "text/html");
std::string html = "<html><body><h1>404 Not Found</h1></body></html>";
res.header("Content-Length", std::to_string(html.size()));
stream << res;
stream << html;
stream.flush();Redirect response
HttpResponse res;
res.response("302", "Found");
res.header("Location", "https://example.com/new-location");
res.header("Content-Length", "0");
stream << res;
stream.flush();JSON API response
HttpResponse res;
res.response("200", "OK");
res.header("Content-Type", "application/json");
res.header("Cache-Control", "no-cache");
std::string json = R"({
"data": {
"id": 123,
"name": "Alice"
}
})";
res.header("Content-Length", std::to_string(json.size()));
stream << res;
stream << json;
stream.flush();Server usage
Sending responses
// In server handler
HttpResponse res;
// Success
res.response("200", "OK");
res.header("Content-Type", "text/plain");
std::string content = "Request processed successfully";
res.header("Content-Length", std::to_string(content.size()));
res.writeHeaders(stream);
stream << content;
stream.flush();Error handling
void sendError(std::ostream& stream, const std::string& status,
const std::string& reason)
{
HttpResponse res;
res.response(status, reason);
res.header("Content-Type", "text/html");
res.header("Connection", "close");
std::string html = "<html><body><h1>" + status + " " +
reason + "</h1></body></html>";
res.header("Content-Length", std::to_string(html.size()));
res.writeHeaders(stream);
stream << html;
stream.flush();
}Client usage
Receiving responses
// Send request
client << request;
// Receive response
HttpResponse res;
client >> res;
// Check status
if (res.status() == "200")
{
// Success - read body
std::string body;
size_t length = res.contentLength();
body.resize(length);
client.read(&body[0], length);
}
else
{
// Error
std::cerr << "Error: " << res.status() << " "
<< res.reason() << "\n";
}Helper methods
Content length
HttpResponse res;
// ... receive response ...
// Get content length from header
size_t length = res.contentLength();
if (length > 0)
{
std::string body;
body.resize(length);
stream.read(&body[0], length);
}Header checks
// Check if header exists
if (res.hasHeader("Content-Type"))
{
std::string type = res.header("Content-Type");
}
// Get all headers
const auto& headers = res.headers();
for (const auto& [name, value] : headers)
{
std::cout << name << ": " << value << "\n";
}Error handling
HttpResponse res;
if (res.readHeaders(stream) == -1)
{
std::error_code ec = join::lastError;
if (ec == HttpErrc::BadRequest)
{
// Malformed response
}
// Handle error...
}Best practices
Always set Content-Length
std::string body = generateBody();
res.header("Content-Length", std::to_string(body.size()));Use appropriate status codes
// Resource created
res.response("201", "Created");
// No content to return
res.response("204", "No Content");
// Client error
res.response("400", "Bad Request");
// Not your fault
res.response("500", "Internal Server Error");Clear and reuse
HttpResponse res;
for (const auto& item : items)
{
res.clear(); // Reset for reuse
res.response("200", "OK");
// Send response...
}Summary
| Feature | Supported |
|---|---|
| Status codes | ✅ |
| Headers | ✅ |
| HTTP/1.1 | ✅ |
| Serialization | ✅ |
| Content length | ✅ |
| Copy/move semantics | ✅ |