streamline session mgmt, add session refresh

This commit is contained in:
Sky Johnson 2025-06-14 14:53:13 -05:00
parent 7e4c8d12cc
commit 0ac37c6ab3
2 changed files with 75 additions and 59 deletions

View File

@ -142,44 +142,35 @@ private:
// Client disconnected
}
void process_request(int client_fd, std::string_view request_data) {
Request req = Parser::parse(request_data);
void process_request(int client_fd, std::string_view request_data) {
Request req = Parser::parse(request_data);
if (!req.valid) {
send_error_response(client_fd, "Bad Request", 400, req.version);
return;
}
// Handle session
std::string session_id;
bool needs_session = sessions.needs_session(req);
if (needs_session) {
std::string_view existing_id = sessions.extract_session_id(req);
session_id = existing_id.empty() ? sessions.create() : std::string(existing_id);
}
Response response;
// Try router first
if (router.handle(req, response)) {
if (needs_session) set_session_cookie(response, session_id);
send_response(client_fd, response, req.version);
return;
}
// Then try static files
if (static_handler && static_handler->handle(req, response)) {
set_session_cookie(response, session_id);
send_response(client_fd, response, req.version);
} else {
response.status = 404;
response.set_text("Not Found");
if (needs_session) set_session_cookie(response, session_id);
send_response(client_fd, response, req.version);
}
if (!req.valid) {
send_error_response(client_fd, "Bad Request", 400, req.version);
return;
}
Response response;
if (static_handler && static_handler->handle(req, response)) {
send_response(client_fd, response, req.version);
return;
}
if (router.handle(req, response)) {
std::string_view existing_id = sessions.extract_session_id(req);
std::string session_id = existing_id.empty() ?
sessions.create() : std::string(existing_id);
set_session_cookie(response, session_id);
send_response(client_fd, response, req.version);
} else {
response.status = 404;
response.set_text("Not Found");
send_response(client_fd, response, req.version);
}
}
void set_session_cookie(Response& response, const std::string& session_id) {
response.cookies.push_back("session_id=" + session_id + "; HttpOnly; Path=/; SameSite=Strict");
}

View File

@ -123,30 +123,6 @@ public:
store_.set_file("sessions.txt");
}
bool needs_session(const Request& req) const {
if (req.path.starts_with("/static") ||
req.path.starts_with("/assets") ||
req.path.ends_with(".css") ||
req.path.ends_with(".js") ||
req.path.ends_with(".png") ||
req.path.ends_with(".jpg") ||
req.path.ends_with(".jpeg") ||
req.path.ends_with(".gif") ||
req.path.ends_with(".ico") ||
req.path.ends_with(".svg") ||
req.path.ends_with(".woff") ||
req.path.ends_with(".woff2") ||
req.path.ends_with(".ttf")) {
return false;
}
return req.path.starts_with("/api") ||
req.path.starts_with("/admin") ||
req.method == HttpMethod::POST ||
req.method == HttpMethod::PUT ||
req.method == HttpMethod::DELETE;
}
std::string create() {
std::string id = generate_id();
size_t shard = get_shard(id);
@ -226,6 +202,55 @@ public:
return true;
}
std::string refresh(const std::string& old_id) {
size_t old_shard = get_shard(old_id);
std::lock_guard<std::mutex> lock(mutexes_[old_shard]);
auto it = shards_[old_shard].find(old_id);
if (it == shards_[old_shard].end()) return old_id;
// Generate new ID
std::string new_id = generate_id();
size_t new_shard = get_shard(new_id);
// Handle cross-shard case
if (new_shard != old_shard) {
std::lock_guard<std::mutex> new_lock(mutexes_[new_shard]);
// Check session limit on new shard
if (shards_[new_shard].size() >= MAX_SESSIONS_PER_SHARD) {
evict_lru_session(new_shard);
}
// Move session data
SessionData session = std::move(it->second);
lru_lists_[old_shard].erase(session.lru_iter);
// Add to new shard
lru_lists_[new_shard].push_front(new_id);
session.lru_iter = lru_lists_[new_shard].begin();
session.last_access = std::chrono::steady_clock::now();
session.dirty = true;
shards_[new_shard][new_id] = std::move(session);
shards_[old_shard].erase(it);
} else {
// Same shard - just update the key
SessionData session = std::move(it->second);
lru_lists_[old_shard].erase(session.lru_iter);
lru_lists_[old_shard].push_front(new_id);
session.lru_iter = lru_lists_[old_shard].begin();
session.last_access = std::chrono::steady_clock::now();
session.dirty = true;
shards_[old_shard][new_id] = std::move(session);
shards_[old_shard].erase(it);
}
return new_id;
}
size_t size() {
size_t total = 0;
for (size_t i = 0; i < SHARD_COUNT; ++i) {