以下是common.c代码,可以结合server_process理解,写好注释给我#include "common.h"
void send_response(int client_fd, int status, const char* title, const char* text) {
char response[BUFFER_SIZE];
int len = snprintf(response, BUFFER_SIZE,
"HTTP/1.1 %d %s\r\n"
"Content-Type: text/html\r\n"
"Connection: close\r\n"
"\r\n"
"<html><head><title>%d %s</title></head>"
"<body><h1>%d %s</h1><p>%s</p></body></html>",
status, title, status, title, status, title, text);
send(client_fd, response, len, 0);
DEBUG("Sent %d response\n", status);
}
void send_file(int client_fd, const char* path) {
int fd = open(path, O_RDONLY);
if (fd < 0) {
perror("open");
send_response(client_fd, 404, "Not Found", "File not found");
return;
}
struct stat file_stat;
if (fstat(fd, &file_stat) < 0) {
perror("fstat");
close(fd);
send_response(client_fd, 500, "Internal Error", "Could not get file stats");
return;
}
// 确定Content-Type
const char *content_type = "text/plain";
if (strstr(path, ".html")) content_type = "text/html";
else if (strstr(path, ".css")) content_type = "text/css";
else if (strstr(path, ".js")) content_type = "application/javascript";
else if (strstr(path, ".png")) content_type = "image/png";
else if (strstr(path, ".jpg")) content_type = "image/jpeg";
else if (strstr(path, ".json")) content_type = "application/json";
char header[BUFFER_SIZE];
int header_len = snprintf(header, BUFFER_SIZE,
"HTTP/1.1 200 OK\r\n"
"Content-Type: %s\r\n"
"Content-Length: %ld\r\n"
"Connection: close\r\n\r\n",
content_type, file_stat.st_size);
send(client_fd, header, header_len, 0);
sendfile(client_fd, fd, NULL, file_stat.st_size);
DEBUG("Sent file: %s (%ld bytes)\n", path, file_stat.st_size);
close(fd);
}
// URL解码函数
char* url_decode(const char* str) {
if (!str) return NULL;
char* decoded = malloc(strlen(str) + 1);
if (!decoded) return NULL;
char* d = decoded;
for (const char* s = str; *s; s++) {
if (*s == '+') {
*d++ = ' ';
} else if (*s == '%' && isxdigit(s[1]) && isxdigit(s[2])) {
char hex[3] = {s[1], s[2], '\0'};
*d++ = (char)strtol(hex, NULL, 16);
s += 2;
} else {
*d++ = *s;
}
}
*d = '\0';
return decoded;
}
// 处理POST请求
void handle_post_request(int client_fd, const char* path, const char* post_data, size_t data_len) {
DEBUG("Handling POST request to %s\n", path);
// 简单的表单处理
if (strcmp(path, "/submit") == 0) {
// 解析表单数据
char* decoded = url_decode(post_data);
if (!decoded) {
send_response(client_fd, 500, "Internal Error", "Failed to decode data");
return;
}
DEBUG("Decoded POST data: %s\n", decoded);
// 提取表单字段
char name[256] = {0};
char email[256] = {0};
char message[1024] = {0};
char* token = strtok(decoded, "&");
while (token) {
char* eq = strchr(token, '=');
if (eq) {
*eq = '\0';
char* key = token;
char* value = eq + 1;
if (strcmp(key, "name") == 0) {
strncpy(name, value, sizeof(name)-1);
} else if (strcmp(key, "email") == 0) {
strncpy(email, value, sizeof(email)-1);
} else if (strcmp(key, "message") == 0) {
strncpy(message, value, sizeof(message)-1);
}
}
token = strtok(NULL, "&");
}
// 构建响应页面
char response[BUFFER_SIZE];
int len = snprintf(response, BUFFER_SIZE,
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n"
"Connection: close\r\n"
"\r\n"
"<html><head><title>Form Submitted</title></head>"
"<body><h1>Thank You!</h1>"
"<p>Name: %s</p>"
"<p>Email: %s</p>"
"<p>Message: %s</p>"
"<p><a href=\"/\">Back to home</a></p></body></html>",
name, email, message);
send(client_fd, response, len, 0);
free(decoded);
}
// 简单的API处理
else if (strcmp(path, "/api/data") == 0) {
char response[BUFFER_SIZE];
int len = snprintf(response, BUFFER_SIZE,
"HTTP/1.1 200 OK\r\n"
"Content-Type: application/json\r\n"
"Connection: close\r\n"
"\r\n"
"{\"status\":\"success\",\"message\":\"Data received\",\"length\":%zu}",
data_len);
send(client_fd, response, len, 0);
}
else {
send_response(client_fd, 404, "Not Found", "POST endpoint not found");
}
}
void handle_request(int client_fd) {
char buffer[BUFFER_SIZE];
ssize_t bytes_read = recv(client_fd, buffer, BUFFER_SIZE - 1, 0);
if (bytes_read <= 0) {
DEBUG("Connection closed or error\n");
close(client_fd);
return;
}
buffer[bytes_read] = '\0';
DEBUG("Request:\n%s\n", buffer);
// 检测HTTP方法
HttpMethod method = HTTP_UNKNOWN;
char *method_start = buffer;
char *method_end = strchr(method_start, ' ');
if (method_end) {
*method_end = '\0';
if (strcmp(method_start, "GET") == 0) method = HTTP_GET;
else if (strcmp(method_start, "POST") == 0) method = HTTP_POST;
else if (strcmp(method_start, "PUT") == 0) method = HTTP_PUT;
else if (strcmp(method_start, "DELETE") == 0) method = HTTP_DELETE;
*method_end = ' '; // 恢复原始数据
}
// 解析请求路径
char *path_start = buffer;
if (method != HTTP_UNKNOWN) {
path_start = strchr(buffer, ' ') + 1;
}
char *path_end = strchr(path_start, ' ');
if (!path_end) {
send_response(client_fd, 400, "Bad Request", "Invalid request");
close(client_fd);
return;
}
*path_end = '\0';
// 处理POST请求
if (method == HTTP_POST) {
// 查找Content-Length
char *content_length_start = strstr(buffer, "Content-Length: ");
size_t content_length = 0;
if (content_length_start) {
content_length_start += 15; // 跳过"Content-Length: "
char *content_length_end = strchr(content_length_start, '\r');
if (content_length_end) {
*content_length_end = '\0';
content_length = atoi(content_length_start);
*content_length_end = '\r'; // 恢复原始数据
}
}
// 限制POST数据大小
if (content_length > MAX_POST_SIZE) {
send_response(client_fd, 413, "Payload Too Large", "POST data too large");
close(client_fd);
return;
}
// 查找POST数据开始位置
char *post_data = strstr(buffer, "\r\n\r\n");
if (post_data) {
post_data += 4; // 跳过空行
// 确保不超出缓冲区
size_t data_size = bytes_read - (post_data - buffer);
if (data_size < content_length) {
// 需要读取更多数据(简化处理)
DEBUG("Incomplete POST data, need to read more\n");
send_response(client_fd, 400, "Bad Request", "Incomplete POST data");
close(client_fd);
return;
}
// 处理POST请求
handle_post_request(client_fd, path_start, post_data, content_length);
close(client_fd);
return;
}
}
// 构建完整路径(处理GET请求)
char full_path[256];
if (strcmp(path_start, "/") == 0) {
snprintf(full_path, sizeof(full_path), "%s/Index.html", ROOT_DIR);
} else {
snprintf(full_path, sizeof(full_path), "%s%s", ROOT_DIR, path_start);
}
// 检查文件是否存在
struct stat st;
if (stat(full_path, &st) == 0 && S_ISREG(st.st_mode)) {
send_file(client_fd, full_path);
} else {
send_response(client_fd, 404, "Not Found", "File not found");
}
close(client_fd);
}
最新发布