cpp_server/cookie.hpp

137 lines
2.8 KiB
C++

#pragma once
#include <string_view>
#include <vector>
#include <string>
using std::string_view;
struct Cookie {
string_view name;
string_view value;
Cookie(string_view n, string_view v) : name(n), value(v) {}
};
class CookieParser {
public:
static std::vector<Cookie> parse(string_view cookie_header) {
std::vector<Cookie> cookies;
const char* ptr = cookie_header.data();
const char* end = ptr + cookie_header.size();
while (ptr < end) {
// Skip whitespace and semicolons
while (ptr < end && (*ptr == ' ' || *ptr == ';')) ptr++;
if (ptr >= end) break;
// Find name end (=)
const char* name_start = ptr;
while (ptr < end && *ptr != '=' && *ptr != ';') ptr++;
if (ptr >= end || *ptr != '=') break;
string_view name(name_start, ptr - name_start);
ptr++; // Skip '='
// Find value end (; or end)
const char* value_start = ptr;
while (ptr < end && *ptr != ';') ptr++;
string_view value(value_start, ptr - value_start);
// Trim whitespace from name and value
name = trim(name);
value = trim(value);
if (!name.empty()) {
cookies.emplace_back(name, value);
}
}
return cookies;
}
private:
static string_view trim(string_view str) {
const char* start = str.data();
const char* end = start + str.size();
// Trim leading whitespace
while (start < end && *start == ' ') start++;
// Trim trailing whitespace
while (end > start && *(end - 1) == ' ') end--;
return string_view(start, end - start);
}
};
// Cookie helpers for request/response handling
class CookieHelpers {
public:
// Get cookie value from request, returns empty string_view if not found
static string_view get_cookie(const std::vector<Cookie>& cookies, string_view name) {
for (const auto& cookie : cookies) {
if (cookie.name == name) {
return cookie.value;
}
}
return {};
}
// Build Set-Cookie header value
static std::string build_set_cookie(string_view name, string_view value,
int max_age = -1, string_view path = "", string_view domain = "",
bool secure = false, bool http_only = false) {
std::string result;
result.reserve(256);
result += name;
result += "=";
result += value;
if (max_age >= 0) {
result += "; Max-Age=";
result += std::to_string(max_age);
}
if (!path.empty()) {
result += "; Path=";
result += path;
}
if (!domain.empty()) {
result += "; Domain=";
result += domain;
}
if (secure) {
result += "; Secure";
}
if (http_only) {
result += "; HttpOnly";
}
return result;
}
// Build delete cookie header (expires immediately)
static std::string build_delete_cookie(string_view name, string_view path = "") {
std::string result;
result.reserve(128);
result += name;
result += "=; Max-Age=0";
if (!path.empty()) {
result += "; Path=";
result += path;
}
return result;
}
};