Implementation:ClickHouse ClickHouse Poco HTTPCookie
| Source File | base/poco/Net/src/HTTPCookie.cpp |
|---|---|
| Lines of Code | 343 |
| Principle | Principle:ClickHouse_ClickHouse_HTTP_Client_Communication |
| Domain | Networking, HTTP |
| Language | C++ |
| Last Updated | 2026-02-08 00:00 GMT |
Overview
Implementation of HTTP cookie handling supporting both Netscape (version 0) and RFC 2109 (version 1) cookie formats with parsing, generation, and attribute management.
Purpose
Provides comprehensive HTTP cookie support for client and server applications, handling cookie creation, parsing from headers, and formatting for transmission.
Key Classes
- HTTPCookie: Represents an HTTP cookie with all attributes
Core Functionality
Construction
// Empty cookie
HTTPCookie();
// Named cookie
HTTPCookie(const std::string& name);
// Named cookie with value
HTTPCookie(const std::string& name, const std::string& value);
// From name-value collection (parsed from header)
HTTPCookie(const NameValueCollection& nvc);
// Copy constructor
HTTPCookie(const HTTPCookie& cookie);
Attribute Management
// Core attributes
void setVersion(int version); // 0 (Netscape) or 1 (RFC 2109)
void setName(const std::string& name);
void setValue(const std::string& value);
// Security and scope
void setDomain(const std::string& domain);
void setPath(const std::string& path);
void setSecure(bool secure); // HTTPS only
void setHttpOnly(bool flag); // No JavaScript access
void setPriority(const std::string& priority); // "Low", "Medium", "High"
// Lifetime
void setMaxAge(int maxAge); // Seconds, -1 = session cookie
void setComment(const std::string& comment); // Version 1 only
// Getters
int getVersion() const;
const std::string& getName() const;
const std::string& getValue() const;
// ... etc
Cookie Formatting
// Convert to Set-Cookie header value
std::string toString() const;
// URL encoding/decoding for cookie values
static std::string escape(const std::string& str);
static std::string unescape(const std::string& str);
Implementation Details
Parsing from NameValueCollection
Extracts cookie from parsed header parameters:
HTTPCookie(const NameValueCollection& nvc) {
for (auto& param : nvc) {
if (icompare(param.name, "domain") == 0)
setDomain(param.value);
else if (icompare(param.name, "path") == 0)
setPath(param.value);
else if (icompare(param.name, "max-age") == 0)
setMaxAge(NumberParser::parse(param.value));
else if (icompare(param.name, "secure") == 0)
setSecure(true);
else if (icompare(param.name, "expires") == 0) {
// Parse date, convert to max-age
DateTime exp = DateTimeParser::parse(param.value, tzd);
Timestamp now;
setMaxAge((exp.timestamp() - now) / Timestamp::resolution());
}
else if (icompare(param.name, "httponly") == 0)
setHttpOnly(true);
else {
// First unknown param is name=value
setName(param.name);
setValue(param.value);
}
}
}
Netscape Format (Version 0)
Simple cookie format:
std::string toString() const {
std::string result = _name + "=" + _value;
if (!_domain.empty())
result += "; domain=" + _domain;
if (!_path.empty())
result += "; path=" + _path;
if (!_priority.empty())
result += "; Priority=" + _priority;
if (_maxAge != -1) {
Timestamp ts;
ts += _maxAge * Timestamp::resolution();
result += "; expires=" + DateTimeFormatter::format(ts, DateTimeFormat::HTTP_FORMAT);
}
if (_secure)
result += "; secure";
if (_httpOnly)
result += "; HttpOnly";
return result;
}
Format: `name=value; domain=.example.com; path=/; expires=Thu, 01-Jan-2026 00:00:00 GMT; secure; HttpOnly`
RFC 2109 Format (Version 1)
Quoted values:
if (_version == 1) {
result = _name + "=\"" + _value + "\"";
if (!_comment.empty())
result += "; Comment=\"" + _comment + "\"";
if (!_domain.empty())
result += "; Domain=\"" + _domain + "\"";
if (!_path.empty())
result += "; Path=\"" + _path + "\"";
if (_maxAge != -1)
result += "; Max-Age=\"" + NumberFormatter::format(_maxAge) + "\"";
if (_secure)
result += "; secure";
if (_httpOnly)
result += "; HttpOnly";
result += "; Version=\"1\"";
}
Format: `name="value"; Domain=".example.com"; Max-Age="3600"; Version="1"`
URL Encoding
static const std::string ILLEGAL_CHARS = "()[]/|\\',;";
std::string HTTPCookie::escape(const std::string& str) {
std::string result;
URI::encode(str, ILLEGAL_CHARS, result);
return result;
}
std::string HTTPCookie::unescape(const std::string& str) {
std::string result;
URI::decode(str, result);
return result;
}
Usage Examples
Creating Cookies (Server)
// Session cookie
HTTPCookie cookie("sessionid", "abc123");
cookie.setPath("/");
cookie.setHttpOnly(true);
cookie.setSecure(true);
HTTPResponse response;
response.addCookie(cookie);
Persistent Cookie
HTTPCookie cookie("preferences", "theme=dark");
cookie.setMaxAge(30 * 24 * 3600); // 30 days
cookie.setDomain(".example.com");
cookie.setPath("/");
response.addCookie(cookie);
Parsing Cookies (Client)
HTTPResponse response;
// ... receive response ...
std::vector<HTTPCookie> cookies;
response.getCookies(cookies);
for (auto& cookie : cookies) {
std::cout << cookie.getName() << "=" << cookie.getValue() << std::endl;
if (cookie.getSecure())
std::cout << " Secure cookie" << std::endl;
}
Cookie with Priority
HTTPCookie cookie("important", "data");
cookie.setPriority("High");
cookie.setMaxAge(3600);
response.addCookie(cookie);
Cookie Attributes
Security Attributes
- Secure: Cookie only sent over HTTPS
- HttpOnly: Cookie inaccessible to JavaScript
- Domain: Scope of cookie (subdomain matching)
- Path: URL path scope
Lifetime Attributes
- Max-Age: Lifetime in seconds (-1 = session cookie)
- Expires: Alternative to Max-Age (specific timestamp)
Other Attributes
- Priority: Browser priority (Low/Medium/High)
- Comment: Human-readable description (RFC 2109)
- Version: Cookie specification version (0 or 1)
Security Considerations
XSS Protection
- Use `HttpOnly` to prevent JavaScript access
- Prevents cookie theft via XSS attacks
MITM Protection
- Use `Secure` flag for sensitive cookies
- Ensures transmission only over HTTPS
Scope Control
- Set restrictive `Domain` and `Path`
- Minimize cookie exposure
- Use leading dot for subdomain sharing
Cookie Injection
- Validate cookie names and values
- URL-encode special characters
- Prevent header injection attacks
Testing Considerations
- Test both Netscape and RFC 2109 formats
- Verify URL encoding/decoding
- Test expiration date calculation
- Check attribute parsing
- Test with various domain/path combinations
- Verify secure and HttpOnly flags
- Test priority attribute
- Check Max-Age vs Expires handling
Dependencies
- `Poco::Net::NameValueCollection`: Parameter storage
- `Poco::Timestamp`: Time handling
- `Poco::DateTime`: Date formatting/parsing
- `Poco::DateTimeFormatter`: HTTP date formatting
- `Poco::DateTimeParser`: Date parsing
- `Poco::NumberFormatter`: Number to string
- `Poco::NumberParser`: String to number
- `Poco::URI`: URL encoding/decoding