如何在C++ CGI程序中获取GET/POST变量?(Apache+Ubuntu环境)
在Ubuntu 22.04.1 Apache上用C++ CGI处理表单GET/POST数据的基础方法
核心原理说明
表单的GET和POST数据不会直接作为环境变量存在,需根据请求方式分别处理:
- GET请求:表单数据拼接为
key=value&key2=value2格式,放在URL查询字符串中,Apache会将该字符串存入QUERY_STRING环境变量。 - POST请求:表单数据通过HTTP请求体发送,Apache将数据传递给CGI程序的标准输入,同时通过
CONTENT_LENGTH环境变量告知数据字节长度。
完整实现代码(仅用标准库)
以下代码包含URL解码、键值对解析,以及GET/POST请求的处理逻辑:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> // URL解码:处理%xx编码和+替换为空格 void url_decode(char *str) { char *dest = str; while (*str) { if (*str == '+') { *dest = ' '; } else if (*str == '%' && isxdigit(str[1]) && isxdigit(str[2])) { // 十六进制转十进制 int hex_val = 0; hex_val += isdigit(str[1]) ? str[1] - '0' : toupper(str[1]) - 'A' + 10; hex_val *= 16; hex_val += isdigit(str[2]) ? str[2] - '0' : toupper(str[2]) - 'A' + 10; *dest = (char)hex_val; str += 2; } else { *dest = *str; } str++; dest++; } *dest = '\0'; } // 解析键值对字符串并输出 void parse_form_data(char *data) { if (!data || *data == '\0') { printf("无表单数据\n"); return; } char *pair = strtok(data, "&"); while (pair != NULL) { char *eq_pos = strchr(pair, '='); if (eq_pos != NULL) { *eq_pos = '\0'; char *key = pair; char *value = eq_pos + 1; url_decode(key); url_decode(value); printf("%s: %s\n", key, value); } else { url_decode(pair); printf("%s: 无值\n", pair); } pair = strtok(NULL, "&"); } } int main() { // 必须先输出HTTP响应头 printf("Content-type:text/plain\n\n"); // 获取请求方法 char *method = getenv("REQUEST_METHOD"); if (!method) { printf("无法获取请求方法\n"); return 1; } printf("请求方法: %s\n", method); printf("--- 表单数据 ---\n"); if (strcmp(method, "GET") == 0) { // 处理GET请求:读取QUERY_STRING char *query_str = getenv("QUERY_STRING"); parse_form_data(query_str); } else if (strcmp(method, "POST") == 0) { // 处理POST请求:读取标准输入 char *content_length_str = getenv("CONTENT_LENGTH"); if (!content_length_str || *content_length_str == '\0') { printf("CONTENT_LENGTH环境变量无效\n"); return 1; } int content_length = atoi(content_length_str); if (content_length <= 0) { printf("表单数据长度无效\n"); return 1; } // 分配内存存储POST数据 char *post_data = (char*)malloc(content_length + 1); if (!post_data) { printf("内存分配失败\n"); return 1; } // 读取数据 int bytes_read = fread(post_data, 1, content_length, stdin); if (bytes_read != content_length) { printf("读取POST数据不完整\n"); free(post_data); return 1; } post_data[content_length] = '\0'; parse_form_data(post_data); free(post_data); } else { printf("不支持的请求方法\n"); } printf("--- 处理完成 ---\n"); return 0; }
编译与部署步骤
- 编译代码:将代码保存为
form_handler.cpp,编译为CGI程序:g++ form_handler.cpp -o /var/www/html/cgi-bin/form_handler.cgi - 设置权限:确保程序可执行:
chmod +x /var/www/html/cgi-bin/form_handler.cgi - Apache配置:
- 启用CGI模块:
sudo a2enmod cgi - 编辑网站配置文件
/etc/apache2/sites-available/000-default.conf,确认以下内容:ScriptAlias /cgi-bin/ /var/www/html/cgi-bin/ <Directory /var/www/html/cgi-bin/> AllowOverride None Options +ExecCGI Require all granted </Directory> - 重启Apache:
sudo systemctl restart apache2
- 启用CGI模块:
测试用HTML表单
<!doctype html> <html> <head> <title>CGI表单测试</title> </head> <body> <h2>POST请求测试</h2> <form action="cgi-bin/form_handler.cgi" method="post"> <input type="text" name="username" value="SampleName"> <input type="password" name="Password" value="SamplePass"> <button type="submit" name="Submit">提交POST</button> </form> <hr> <h2>GET请求测试</h2> <form action="cgi-bin/form_handler.cgi" method="get"> <input type="text" name="username" value="SampleName"> <input type="password" name="Password" value="SamplePass"> <button type="submit" name="Submit">提交GET</button> </form> </body> </html>
内容的提问来源于stack exchange,提问作者Black plague
相关产品推荐
相关产品推荐

