C++ HTTP Fundamentals Complete Guide
이 글의 핵심
Master C++ HTTP: RFC-compliant parsing, headers, chunked encoding, Boost.Beast, common errors, and production patterns.
Introduction: “HTTP request parsing is full of bugs”
Problem Scenario 1: Manual Parsing Pitfalls
// ❌ Problem: manual parsing crashes on edge cases
std::string parse_path(const std::string& raw) {
auto pos = raw.find(" ");
auto pos2 = raw.find(" ", pos + 1);
return raw.substr(pos + 1, pos2 - pos - 1); // 💥 Multiple spaces? Empty string?
}
// Issues:
// - HTTP/1.0 vs HTTP/1.1 differences
// - Consecutive spaces, tabs, CRLF vs LF mixing
// - Multi-byte characters (Content-Length vs actual bytes)
// - Chunked encoding: Transfer-Encoding: chunked handling missing
Why does this happen?
HTTP protocol looks simple but has many edge cases: \r\n vs \n, consecutive spaces, percent encoding, chunked encoding, Keep-Alive, etc. Manual parsing accumulates bugs.
Additional Problem Scenarios
Scenario 2: Content-Length and body mismatch
Client sends Content-Length: 100 but only 50 bytes arrive—async_read waits forever without timeout, blocking server threads.
Scenario 3: Chunked encoding parsing failure
Streaming responses with Transfer-Encoding: chunked not handled—body truncated. Essential for large file downloads and real-time streaming.
Scenario 4: Header case and duplicates
Content-Type vs content-type, multiple Set-Cookie headers not handled—parsing errors or security vulnerabilities.
Scenario 5: Request split across TCP packets
One request arrives over multiple async_read_some calls. Failure to detect “request complete” passes wrong data to next request.
Solution:
- Boost.Beast: RFC-compliant parser, built-in error handling
- flat_buffer: preserves data during parsing
- http::read: automatically determines request/response completion
- chunked encoding: Beast handles automatically Goals:
- Understand HTTP request/response structure completely
- Header parsing (case-insensitive, duplicates, encoding)
- Chunked encoding (Transfer-Encoding: chunked)
- Beast parser usage
- Common errors and solutions
- Best practices and production patterns Requirements: Boost.Beast 1.70+, Boost.Asio 1.70+ What you’ll learn:
- Precise HTTP protocol structure
- Safe request/response parsing with Beast
- Production-grade HTTP server/client foundations
Conceptual Analogy
Sockets and async I/O are like mailbox addresses and delivery routes. With correct address (IP·port), data arrives, and Asio is like one post office with multiple carriers (threads·handlers) dividing work.
Table of Contents
- HTTP Protocol Structure
- Request Parsing
- Response Parsing
- Header Handling
- Chunked Encoding
- Beast-Based Complete Parser
- Common Errors and Solutions
- Best Practices
- Production Patterns
1. HTTP Protocol Structure
Request/Response Flow
sequenceDiagram
participant C as Client
participant S as Server
C->>S: Request Line + Headers + CRLF + Body
Note over S: Parse → Route → Process
S->>C: Status Line + Headers + CRLF + Body
HTTP Request Structure
GET /api/users?id=1 HTTP/1.1\r\n
Host: example.com\r\n
Content-Type: application/json\r\n
Content-Length: 0\r\n
\r\n
Components:
- Request Line:
METHOD SP Request-URI SP HTTP-Version CRLF - Headers:
Field-Name: Field-Value CRLF(repeated) - Blank line:
CRLF(separates headers from body) - Body: length determined by
Content-LengthorTransfer-Encoding: chunked
HTTP Response Structure
HTTP/1.1 200 OK\r\n
Content-Type: application/json\r\n
Content-Length: 27\r\n
\r\n
{"message":"Hello World"}
Components:
- Status Line:
HTTP-Version SP Status-Code SP Reason-Phrase CRLF - Headers: same format as request
- Blank line: separates headers from body
- Body: response content
HTTP Message Parsing Visualization
flowchart TB
subgraph Request[HTTP Request]
RL[Request Line\nGET /path HTTP/1.1]
H1[Headers\nHost: example.com\nContent-Type: ...]
BL[Blank Line CRLF]
BD[Body\nContent Data]
end
RL --> H1 --> BL --> BD
style RL fill:#4caf50
style BL fill:#ff9800
2. Request Parsing
Request Line Parsing
#include <string>
#include <sstream>
#include <stdexcept>
struct ParsedRequestLine {
std::string method; // GET, POST, ...
std::string path; // /api/users
std::string query; // id=1 (query string)
std::string version; // HTTP/1.1
};
ParsedRequestLine parse_request_line(const std::string& line) {
std::istringstream iss(line);
ParsedRequestLine result;
// METHOD SP Request-URI SP HTTP-Version
if (!(iss >> result.method >> result.path >> result.version)) {
throw std::runtime_error("Invalid request line");
}
// Split query string: /api/users?id=1 → path=/api/users, query=id=1
auto qpos = result.path.find('?');
if (qpos != std::string::npos) {
result.query = result.path.substr(qpos + 1);
result.path = result.path.substr(0, qpos);
}
return result;
}
// Usage
int main() {
auto parsed = parse_request_line("GET /api/users?id=1 HTTP/1.1");
// parsed.method == "GET"
// parsed.path == "/api/users"
// parsed.query == "id=1"
// parsed.version == "HTTP/1.1"
}
Note: Production requires percent decoding (%20 → space) and path traversal attack prevention (/../../../etc/passwd). Beast handles these.
Headers and Body Separation
// CRLF twice = end of headers
std::pair<std::string, std::string> split_headers_and_body(
const std::string& raw)
{
// Find \r\n\r\n or \n\n (some clients use LF only)
const std::string crlfcrlf = "\r\n\r\n";
const std::string lflf = "\n\n";
auto pos = raw.find(crlfcrlf);
if (pos == std::string::npos) {
pos = raw.find(lflf);
}
if (pos == std::string::npos) {
return {"", ""}; // Still receiving headers
}
size_t header_end = (raw.find(crlfcrlf) != std::string::npos)
? pos + crlfcrlf.size()
: pos + lflf.size();
return {
raw.substr(0, pos),
raw.substr(header_end)
};
}
Content-Length Based Body Reading
#include <cstdlib>
#include <optional>
std::optional<size_t> get_content_length(const std::string& headers) {
// Extract 123 from Content-Length: 123
const std::string key = "Content-Length:";
auto pos = headers.find(key);
if (pos == std::string::npos) {
return std::nullopt; // No body or chunked
}
pos += key.size();
while (pos < headers.size() && headers[pos] == ' ') ++pos;
char* end;
long value = std::strtol(headers.c_str() + pos, &end, 10);
if (value < 0 || end == headers.c_str() + pos) {
return std::nullopt; // Invalid format
}
return static_cast<size_t>(value);
}
3. Response Parsing
Status Line Parsing
struct ParsedStatusLine {
std::string version; // HTTP/1.1
int status_code; // 200, 404, ...
std::string reason; // OK, Not Found, ...
};
ParsedStatusLine parse_status_line(const std::string& line) {
std::istringstream iss(line);
ParsedStatusLine result;
if (!(iss >> result.version >> result.status_code)) {
throw std::runtime_error("Invalid status line");
}
std::getline(iss, result.reason); // Rest: " OK\r" or " OK"
// Trim whitespace
result.reason.erase(0, result.reason.find_first_not_of(" \t\r\n"));
result.reason.erase(result.reason.find_last_not_of(" \t\r\n") + 1);
return result;
}
// Usage
// parse_status_line("HTTP/1.1 200 OK") → 200, "OK"
// parse_status_line("HTTP/1.1 404 Not Found") → 404, "Not Found"
Response Body Reading Strategy
// Body reading strategy
enum class BodyReadStrategy {
NoBody, // HEAD, 204, 304, etc.
ContentLength, // Content-Length present
Chunked, // Transfer-Encoding: chunked
UntilClose // HTTP/1.0, read until connection close
};
BodyReadStrategy determine_strategy(
int status_code,
const std::string& method,
const std::map<std::string, std::string>& headers)
{
if (method == "HEAD" || status_code == 204 || status_code == 304) {
return BodyReadStrategy::NoBody;
}
auto it = headers.find("transfer-encoding");
if (it != headers.end() &&
it->second.find("chunked") != std::string::npos) {
return BodyReadStrategy::Chunked;
}
if (headers.count("content-length")) {
return BodyReadStrategy::ContentLength;
}
return BodyReadStrategy::UntilClose; // HTTP/1.0 fallback
}
4. Header Handling
Header Parsing (Case-Insensitive)
#include <map>
#include <algorithm>
#include <cctype>
std::map<std::string, std::string> parse_headers(const std::string& header_block) {
std::map<std::string, std::string> headers;
std::istringstream iss(header_block);
std::string line;
while (std::getline(iss, line) && !line.empty() &&
(line.back() == '\r' ? (line.pop_back(), true) : true)) {
auto colon = line.find(':');
if (colon == std::string::npos) continue;
std::string name = line.substr(0, colon);
std::string value = line.substr(colon + 1);
// Trim whitespace
value.erase(0, value.find_first_not_of(" \t"));
value.erase(value.find_last_not_of(" \t\r\n") + 1);
// Normalize header name to lowercase (HTTP headers are case-insensitive)
std::transform(name.begin(), name.end(), name.begin(),
[](unsigned char c) { return std::tolower(c); });
// Multiple headers with same name: Set-Cookie, etc. need special handling
if (headers.count(name)) {
headers[name] += ", " + value; // Simple merge
} else {
headers[name] = value;
}
}
return headers;
}
Key Headers
| Header | Purpose | Example |
|---|---|---|
Content-Type | Body MIME type | application/json, text/html |
Content-Length | Body byte count | 1024 |
Transfer-Encoding | Transfer encoding | chunked |
Host | Request target host | example.com:8080 |
Connection | Connection persistence | keep-alive, close |
Accept-Encoding | Compression support | gzip, deflate, br |
Content-Type Parsing (MIME + charset)
struct ParsedContentType {
std::string media_type; // application/json
std::string charset; // utf-8 (if present)
};
ParsedContentType parse_content_type(const std::string& value) {
ParsedContentType result;
auto semicolon = value.find(';');
result.media_type = value.substr(0, semicolon);
result.media_type.erase(0, result.media_type.find_first_not_of(" \t"));
result.media_type.erase(result.media_type.find_last_not_of(" \t") + 1);
if (semicolon != std::string::npos) {
std::string rest = value.substr(semicolon + 1);
auto eq = rest.find('=');
if (eq != std::string::npos) {
std::string key = rest.substr(0, eq);
std::string val = rest.substr(eq + 1);
// Remove whitespace and quotes
val.erase(0, val.find_first_not_of(" \t\""));
val.erase(val.find_last_not_of(" \t\"") + 1);
if (key.find("charset") != std::string::npos) {
result.charset = val;
}
}
}
return result;
}
5. Chunked Encoding
Chunk Format
5\r\n
Hello\r\n
6\r\n
World\r\n
0\r\n
\r\n
Format: [hex size]\r\n[data]\r\n repeated, ending with 0\r\n\r\n
Chunk Decoding Implementation
#include <vector>
#include <cctype>
std::pair<std::vector<char>, size_t> decode_chunk(
const char* data, size_t size, size_t& consumed)
{
std::vector<char> body;
consumed = 0;
const char* p = data;
const char* end = data + size;
while (p < end) {
// Read chunk size (hex)
if (p + 2 > end) break; // Need at least "0\r\n"
char* hex_end;
unsigned long chunk_size = std::strtoul(p, &hex_end, 16);
p = hex_end;
// Skip \r\n
if (p + 2 > end) break;
if (p[0] != '\r' || p[1] != '\n') {
throw std::runtime_error("Invalid chunk: expected CRLF");
}
p += 2;
consumed = p - data;
if (chunk_size == 0) {
// Last chunk, may have trailing \r\n
if (p + 2 <= end && p[0] == '\r' && p[1] == '\n') {
consumed += 2;
}
break;
}
// Chunk data
if (p + chunk_size + 2 > end) {
break; // Insufficient data
}
body.insert(body.end(), p, p + chunk_size);
p += chunk_size;
consumed = p - data;
if (p[0] != '\r' || p[1] != '\n') {
throw std::runtime_error("Invalid chunk: expected CRLF after data");
}
p += 2;
consumed = p - data;
}
return {body, consumed};
}
Chunked Encoding Visualization
flowchart LR
subgraph Chunked[Chunked Encoding]
C1[5\r\nHello\r\n]
C2["6\r\n World\r\n"]
C3[0\r\n\r\n]
end
C1 --> C2 --> C3
subgraph Decoded[Decoded Result]
D["Hello World"]
end
Chunked -->|decode_chunk| Decoded
6. Beast-Based Complete Parser
Reading HTTP Request with Beast
#include <boost/beast.hpp>
#include <boost/asio.hpp>
namespace beast = boost::beast;
namespace http = beast::http;
namespace net = boost::asio;
using tcp = net::ip::tcp;
void read_http_request(tcp::socket& socket) {
beast::flat_buffer buffer;
http::request<http::string_body> req;
beast::error_code ec;
http::read(socket, buffer, req, ec);
if (ec) {
if (ec == http::error::end_of_stream) {
// Connection closed (normal)
return;
}
std::cerr << "Read error: " << ec.message() << "\n";
return;
}
// Use parsed request
std::cout << "Method: " << req.method_string() << "\n";
std::cout << "Path: " << req.target() << "\n";
std::cout << "Version: " << req.version() << "\n";
for (const auto& field : req) {
std::cout << field.name() << ": " << field.value() << "\n";
}
std::cout << "Body: " << req.body() << "\n";
}
Reading HTTP Response with Beast (Automatic Chunked Handling)
void read_http_response(beast::tcp_stream& stream) {
beast::flat_buffer buffer;
http::response_parser<http::string_body> parser;
parser.body_limit(std::numeric_limits<std::uint64_t>::max()); // Body limit
beast::error_code ec;
http::read(stream, buffer, parser, ec);
if (ec) {
std::cerr << "Read error: " << ec.message() << "\n";
return;
}
auto res = parser.get();
std::cout << "Status: " << res.result_int() << "\n";
std::cout << "Body: " << res.body() << "\n";
// Beast automatically decodes Transfer-Encoding: chunked
}
Async Request Reading
void do_read_async(beast::tcp_stream& stream,
std::function<void(http::request<http::string_body>)> on_request)
{
auto buffer = std::make_shared<beast::flat_buffer>();
auto req = std::make_shared<http::request<http::string_body>>();
http::async_read(stream, *buffer, *req,
[&stream, buffer, req, on_request](beast::error_code ec, std::size_t) {
if (ec) {
if (ec != http::error::end_of_stream) {
std::cerr << "Read error: " << ec.message() << "\n";
}
return;
}
on_request(std::move(*req));
});
}
HTTP Response Generation and Sending
void send_json_response(beast::tcp_stream& stream,
unsigned status, const std::string& json_body)
{
http::response<http::string_body> res{http::status::ok, 11};
res.set(http::field::server, "MyServer/1.0");
res.set(http::field::content_type, "application/json");
res.body() = json_body;
res.prepare_payload(); // Auto-set Content-Length
if (status != 200) {
res.result(static_cast<http::status>(status));
}
beast::error_code ec;
http::write(stream, res, ec);
if (ec) {
std::cerr << "Write error: " << ec.message() << "\n";
}
}
Complete HTTP Server Example (Beast)
#include <boost/beast.hpp>
#include <boost/asio.hpp>
#include <iostream>
#include <memory>
namespace beast = boost::beast;
namespace http = beast::http;
namespace net = boost::asio;
using tcp = net::ip::tcp;
class HttpSession : public std::enable_shared_from_this<HttpSession> {
beast::tcp_stream stream_;
beast::flat_buffer buffer_;
http::request<http::string_body> req_;
public:
explicit HttpSession(tcp::socket socket)
: stream_(std::move(socket)) {}
void start() { do_read(); }
private:
void do_read() {
req_ = {};
buffer_.consume(buffer_.size());
auto self = shared_from_this();
http::async_read(stream_, buffer_, req_,
[self, this](beast::error_code ec, std::size_t) {
if (ec) {
if (ec != http::error::end_of_stream)
std::cerr << "read: " << ec.message() << "\n";
return;
}
handle_request();
});
}
void handle_request() {
http::response<http::string_body> res{http::status::ok, req_.version()};
res.set(http::field::server, "Beast-HTTP-Server");
res.set(http::field::content_type, "text/plain");
if (req_.method() == http::verb::get && req_.target() == "/") {
res.body() = "Hello, World!";
} else if (req_.method() == http::verb::get &&
req_.target().starts_with("/api/")) {
res.set(http::field::content_type, "application/json");
res.body() = "{\"message\":\"API response\"}";
} else {
res.result(http::status::not_found);
res.body() = "Not Found";
}
res.prepare_payload();
auto self = shared_from_this();
http::async_write(stream_, res,
[self, this](beast::error_code ec, std::size_t) {
if (!ec) {
if (req_.keep_alive()) {
do_read(); // Keep-Alive: next request
}
}
});
}
};
int main() {
net::io_context ioc;
tcp::acceptor acceptor(ioc, {tcp::v4(), 8080});
std::function<void()> do_accept;
do_accept = [&]() {
acceptor.async_accept(
[&](beast::error_code ec, tcp::socket socket) {
if (!ec) {
std::make_shared<HttpSession>(std::move(socket))->start();
}
do_accept();
});
};
do_accept();
std::cout << "HTTP server on :8080\n";
ioc.run();
}
7. Common Errors and Solutions
Problem 1: “end_of_stream” or “connection reset”
Cause: Client disconnects mid-request (browser refresh, timeout). Solution:
http::async_read(stream_, buffer_, req_,
[self, this](beast::error_code ec, std::size_t) {
if (ec) {
if (ec == http::error::end_of_stream ||
ec == net::error::connection_reset) {
// Treat as normal connection close
return;
}
std::cerr << "read error: " << ec.message() << "\n";
return;
}
handle_request();
});
Problem 2: “body limit exceeded”
Cause: Request body exceeds body_limit (DoS prevention default).
Solution:
http::request_parser<http::string_body> parser;
parser.body_limit(10 * 1024 * 1024); // 10MB
http::async_read(stream_, buffer_, parser, ...);
Problem 3: “partial message” or infinite read wait
Cause: Content-Length mismatch with actual body, or chunked encoding parsing error.
Solution:
- Beast handles automatically. For manual parsing, validate
Content-Length. - Set timeout to prevent infinite wait:
stream_.expires_after(std::chrono::seconds(30));
http::async_read(stream_, buffer_, req_, handler);
Problem 4: Keep-Alive next request parsing failure
Cause: Multiple requests on one connection, previous request buffer not cleared. Solution:
void do_read() {
req_ = {}; // Reset request
buffer_.consume(buffer_.size()); // Clear buffer
http::async_read(stream_, buffer_, req_, ...);
}
Problem 5: Header Injection (CRLF Injection)
Cause: User input directly in headers allows \r\n to inject new headers.
Solution:
// ❌ Dangerous
res.set("X-Custom", user_input);
// ✅ Safe: remove CRLF
std::string safe_value = user_input;
safe_value.erase(
std::remove(safe_value.begin(), safe_value.end(), '\r'),
safe_value.end());
safe_value.erase(
std::remove(safe_value.begin(), safe_value.end(), '\n'),
safe_value.end());
res.set("X-Custom", safe_value);
Problem 6: Large Body Memory Explosion
Cause: string_body for 1GB file upload uses 1GB memory.
Solution: Use dynamic_body or file_body:
http::request<http::dynamic_body> req;
// Or
http::request_parser<http::file_body> parser;
parser.body_limit(100 * 1024 * 1024); // 100MB
boost::beast::file_mode mode = boost::beast::file_mode::write;
parser.get().body().open("/tmp/upload.dat", mode);
8. Best Practices
1. Always Use Beast
// ❌ Manual parsing: edge case bugs
std::string path = extract_path(raw_request);
// ✅ Beast: RFC-compliant, validated
http::request<http::string_body> req;
http::read(socket, buffer, req);
std::string path = std::string(req.target());
2. Set body_limit
http::request_parser<http::string_body> parser;
parser.body_limit(1024 * 1024); // 1MB limit (upload size limit)
3. Set Timeout
stream_.expires_after(std::chrono::seconds(30));
4. Call prepare_payload()
res.body() = "Hello";
res.prepare_payload(); // Auto-set Content-Length
5. Handle Keep-Alive
if (req.keep_alive()) {
res.keep_alive(true);
do_read(); // Wait for next request
} else {
res.keep_alive(false);
stream_.socket().shutdown(tcp::socket::shutdown_send);
}
6. Consistent Error Responses
std::string escape_json(const std::string& s) {
std::string out;
for (char c : s) {
if (c == '"') out += "\\\"";
else if (c == '\\') out += "\\\\";
else if (c == '\n') out += "\\n";
else if (c == '\r') out += "\\r";
else out += c;
}
return out;
}
void send_error(beast::tcp_stream& stream, unsigned status,
const std::string& message)
{
http::response<http::string_body> res{
static_cast<http::status>(status), 11};
res.set(http::field::content_type, "application/json");
res.body() = "{\"error\":\"" + escape_json(message) + "\"}";
res.prepare_payload();
http::write(stream, res);
}
9. Production Patterns
Pattern 1: Request Logging Middleware
void log_request(const http::request<http::string_body>& req) {
auto now = std::chrono::system_clock::now();
auto time = std::chrono::system_clock::to_time_t(now);
std::cerr << std::put_time(std::localtime(&time), "%Y-%m-%d %H:%M:%S")
<< " " << req.method_string() << " " << req.target()
<< " " << req.version() << "\n";
}
Pattern 2: Request Size Limits (Rate Limiting)
constexpr size_t MAX_HEADER_SIZE = 8 * 1024; // 8KB
constexpr size_t MAX_BODY_SIZE = 10 * 1024 * 1024; // 10MB
http::request_parser<http::string_body> parser;
parser.header_limit(MAX_HEADER_SIZE);
parser.body_limit(MAX_BODY_SIZE);
Pattern 3: Graceful Shutdown
std::atomic<bool> shutdown_requested{false};
void do_accept() {
if (shutdown_requested) return;
acceptor_.async_accept(
[this](beast::error_code ec, tcp::socket socket) {
if (shutdown_requested) return;
if (!ec) {
std::make_shared<HttpSession>(std::move(socket))->start();
}
do_accept();
});
}
// SIGINT handler
void on_signal() {
shutdown_requested = true;
acceptor_.close();
}
Pattern 4: Connection Pool (Client)
class HttpClientPool {
net::io_context& ioc_;
std::queue<std::unique_ptr<beast::tcp_stream>> pool_;
std::mutex mtx_;
tcp::resolver::results_type endpoints_;
public:
void get_connection(std::function<void(beast::tcp_stream&)> callback) {
std::unique_lock lock(mtx_);
if (!pool_.empty()) {
auto stream = std::move(pool_.front());
pool_.pop();
lock.unlock();
callback(*stream);
return;
}
lock.unlock();
auto stream = std::make_unique<beast::tcp_stream>(ioc_);
stream->async_connect(endpoints_,
[this, cb = std::move(callback), s = stream.get()]
(beast::error_code ec) {
if (!ec) cb(*s);
});
}
void release_connection(std::unique_ptr<beast::tcp_stream> stream) {
std::lock_guard lock(mtx_);
pool_.push(std::move(stream));
}
};
Pattern 5: Health Check Endpoint
if (req.target() == "/health") {
res.result(http::status::ok);
res.set(http::field::content_type, "application/json");
res.body() = "{\"status\":\"ok\"}";
res.prepare_payload();
// Skip DB/cache checks for fast response
return;
}
Pattern 6: CORS Headers
res.set("Access-Control-Allow-Origin", "*");
res.set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
res.set("Access-Control-Allow-Headers", "Content-Type, Authorization");
if (req.method() == http::verb::options) {
res.result(http::status::ok);
res.body() = "";
res.prepare_payload();
return; // Preflight response
}
Implementation Checklist
- Use Beast
http::read/http::write(avoid manual parsing) - Set
body_limit(DoS prevention) - Set
expires_aftertimeout - Call
prepare_payload() - Handle Keep-Alive (
buffer_.consume,req_ = {}) - Prevent CRLF injection (validate header values)
- Consistent error responses (JSON format)
- Logging middleware
- Graceful shutdown
References
- RFC 7230 - HTTP/1.1: Message Syntax and Routing
- RFC 7231 - HTTP/1.1: Semantics and Content
- Boost.Beast Documentation
Summary
Key Points
- HTTP structure: Request line/status line, headers, blank line, body
- Parsing: Beast handles edge cases (CRLF, chunked, Content-Length)
- Headers: Case-insensitive, handle duplicates
- Chunked encoding: Beast auto-decodes
- Best practices: Limits, timeouts, prepare_payload, Keep-Alive hygiene
- Production: Logging, CORS, health checks, connection pools
HTTP Message Components
| Component | Request | Response |
|---|---|---|
| First line | GET /path HTTP/1.1 | HTTP/1.1 200 OK |
| Headers | Host: example.com | Content-Type: application/json |
| Blank line | \r\n | \r\n |
| Body | JSON, form data, etc. | JSON, HTML, etc. |
Common Error Codes
| Code | Meaning | When |
|---|---|---|
| 200 | OK | Success |
| 201 | Created | POST success |
| 204 | No Content | DELETE success |
| 400 | Bad Request | Invalid input |
| 401 | Unauthorized | Auth failure |
| 404 | Not Found | Resource missing |
| 500 | Internal Server Error | Server error |
Related Articles
- C++ Multithreaded Network Server Guide
- C++ SSL/TLS Secure Communication
- C++ REST API Server Complete Guide
Keywords
C++ HTTP, Boost.Beast, HTTP parsing, chunked encoding, Asio, REST, HTTP/1.1, request/response One-line summary: Master C++ HTTP with Beast for RFC-compliant parsing, automatic chunked decoding, and production-ready server/client foundations.
자주 묻는 질문 (FAQ)
Q. 이 내용을 실무에서 언제 쓰나요?
A. Master C++ HTTP: RFC-compliant request/response parsing, header handling (case-insensitive, duplicates), chunked transfe… 실무에서는 위 본문의 예제와 선택 가이드를 참고해 적용하면 됩니다.
Q. 선행으로 읽으면 좋은 글은?
A. 각 글 하단의 이전 글 또는 관련 글 링크를 따라가면 순서대로 배울 수 있습니다. C++ 시리즈 목차에서 전체 흐름을 확인할 수 있습니다.
Q. 더 깊이 공부하려면?
A. cppreference와 해당 라이브러리 공식 문서를 참고하세요. 글 말미의 참고 자료 링크도 활용하면 좋습니다.
같이 보면 좋은 글 (내부 링크)
이 주제와 연결되는 다른 글입니다.
- C++ HTTP 클라이언트·서버 완벽 가이드 | Beast·파싱·Keep-Alive·청크 인코딩
- C++ 초경량 HTTP 웹 프레임워크 바닥부터 만들기 [#48-2]
- C++ HTTP 클라이언트 완벽 가이드 | REST API 호출·연결 풀·타임아웃·프로덕션 패턴
이 글에서 다루는 키워드 (관련 검색어)
C++, HTTP, Beast, Asio, parsing, chunked encoding, headers 등으로 검색하시면 이 글이 도움이 됩니다.