1. Считать куки из заголовка запроса.
2. Сравнить их с уже имеющимися значениями.
3. Отправить их обратно клиенту, если это необходимо.
Ниже приведу код, который добавляет такую функциональность:
Код: Выделить всё
#include <iostream>
#include <string>
#include <cstring>
#include <sstream>
#include <unistd.h>
#include <arpa/inet.h>
#include <map>
const int PORT = 8070;
const int BACKLOG = 10;
const int BUFFER_SIZE = 1024;
// Хранение значений куки в переменной
std::map<std::string, std::string> existingCookies = {
{"cookie1", "value1"},
{"cookie2", "value2"}
};
std::map<std::string, std::string> parseData(const std::string& data) {
std::map<std::string, std::string> result;
std::string keyValuePair;
std::istringstream stream(data);
while (std::getline(stream, keyValuePair, '&')) {
size_t pos = keyValuePair.find('=');
if (pos != std::string::npos) {
std::string key = keyValuePair.substr(0, pos);
std::string value = keyValuePair.substr(pos + 1);
result[key] = value;
}
}
return result;
}
// Функция для получения значений куки из заголовка
std::map<std::string, std::string> getCookies(const std::string& request) {
std::map<std::string, std::string> cookies;
std::string line;
std::istringstream request_stream(request);
while (std::getline(request_stream, line)) {
if (line.find("Cookie: ") == 0) {
size_t pos = line.find("Cookie: ") + 8; // Начало значений куки
std::string cookieData = line.substr(pos);
cookies = parseData(cookieData);
break;
}
}
return cookies;
}
std::string handleGET(const std::string& path) {
std::string body = "<!DOCTYPE html>"
"<html lang='en'>"
"<head>"
"<meta charset='UTF-8'>"
"<meta name='viewport' content='width=device-width, initial-scale=1.0'>"
"<title>Простой C++ Веб-сервер</title>"
"</head>"
"<body>"
"<h1>Вы сделали GET запрос на путь: " + path + "</h1>"
"<form action='/' method='POST'>"
"<input type='text' name='send_text'>"
"<br>"
"<input type='text' name='send_text222'>"
"<input type='submit' value='Submit'>"
"</form>"
"</body>"
"</html>";
return "HTTP/1.1 200 OK
"
"Content-Type: text/html; charset=utf-8
"
"Content-Length: " + std::to_string(body.size()) + "\n"
"Connection: close
"
"\n" + body;
}
std::string handlePOST(const std::string& data, const std::map<std::string, std::string>& cookies) {
std::string body = "<!DOCTYPE html>"
"<html lang='en'>"
"<head>"
"<meta charset='UTF-8'>"
"<meta name='viewport' content='width=device-width, initial-scale=1.0'>"
"<title>Простой C++ Веб-сервер</title>"
"</head>"
"<body>"
"<h1>Вы сделали POST запрос с данными:</h1>"
"<pre>" + data + "</pre>"
"<h2>Значения куки:</h2><pre>";
// Сравнение куки
for (const auto& existing : existingCookies) {
body += existing.first + ": " + existing.second + " | ";
}
body += "</pre></body></html>";
return "HTTP/1.1 200 OK
"
"Content-Type: text/html; charset=utf-8
"
"Content-Length: " + std::to_string(body.size()) + "\n"
"Connection: close
"
"\n" + body;
}
std::string parseRequest(const std::string& request) {
std::string method, path, data;
std::istringstream request_stream(request);
request_stream >> method >> path; // Получаем метод и путь
std::string line;
std::map<std::string, std::string> cookies;
while (std::getline(request_stream, line) && line != "") {
// Собираем заголовки и получаем куки
if (line.find("Cookie: ") == 0) {
cookies = getCookies(request);
}
}
// Если это POST запрос, то нужно получить данные
if (method == "POST") {
// Получаем длину содержимого
while (std::getline(request_stream, line)) {
if (line.find("Content-Length: ") != std::string::npos) {
int content_length = std::stoi(line.substr(16));
data.resize(content_length);
request_stream.read(&data[0], content_length);
break;
}
}
return handlePOST(data, cookies);
} else if (method == "GET") {
return handleGET(path);
}
return "HTTP/1.1 405 Method Not Allowed
"
"Connection: close
"
"\n";
}
int main() {
int server_fd, new_socket;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("Socket failed");
exit(EXIT_FAILURE);
}
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("Bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, BACKLOG) < 0) {
perror("Listen failed");
exit(EXIT_FAILURE);
}
std::cout << "Server is listening on port " << PORT << std::endl;
while (true) {
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
perror("Accept failed");
exit(EXIT_FAILURE);
}
char buffer[BUFFER_SIZE] = {0};
read(new_socket, buffer, BUFFER_SIZE);
std::string request(buffer);
std::cout << "Received request:\n" << request << std::endl;
std::string response = parseRequest(request);
send(new_socket, response.c_str(), response.size(), 0);
close(new_socket);
}
return 0;
}
1. Структура `existingCookies`: Хранит известные значения куки для сравнения.
2. Функция `getCookies`: Извлекает куки из заголовков запроса.
3. Изменение функции `handlePOST`: Теперь она отображает значения куки, которые были сохранены на сервере.
4. Сравнение куки: Сопоставляет полученные куки с уже существующими и выводит их.
Теперь, когда клиент отправляет HTTP-запросы к серверу, они будут получать как данные формы, так и значения куки, которые были сохранены на сервере.