FastCGI Web应用中点击提交按钮后调用指定C函数的问题
预订系统FastCGI表单提交与业务函数整合方案
问题背景
开发预订系统Web应用时,已完成以下功能:
- 用libcurl实现
send_mail()函数发送邮件 - 用
fcgi_stdio.h实现FastCGI服务,可处理GET请求显示表单、POST请求解析表单数据 book_for()和send_mail()单独调用功能正常
需求:点击表单Submit按钮后,自动调用book_for(to, name, num_guest, phone, date)和send_mail("addr", "confirmation.mail")完成预订记录与邮件通知。
原代码
#define __USE_XOPEN #define _GNU_SOURCE #include <stdio.h> #include <fcgi_stdio.h> #include <string.h> #include <stdlib.h> #include "mail.h" #include "booking.h" int main() { char to[20], name[20]; //char *year, *mon, *day, *hour, *min; char date[20]; char num_guest[4], phone[10]; while (FCGI_Accept() >= 0) { printf("Content-type: text/html\n\n"); printf("<h1>Welcome</h1>"); char *method = getenv("REQUEST_METHOD"); char form[2048] = {0}; char output[2048] = {0}; if(strcmp(method, "GET") == 0) { strcpy(form, "<form method='POST' action=''>" "<input id='name' name='name' type='text'></input>" "<br>" "<input id='to' name='to' type='email'></input>" "<br>" "<input id='date' type='datetime-local' name='date' />" "<br>" "<input type='tel' " "id='phone' name='phone' size='20' " "minlenght='9' maxlenght='14' required>" "<br>" "<input type='number' id='num_guest' name='num_guest'" "min='1' max='18'>" "<br>" "<input type='submit' value='Submit'>" "</form>" ); } else if (strcmp(method, "POST") == 0) { int ilen = atoi(getenv("CONTENT_LENGTH")); //char *bufp = malloc(ilen); char *bufp = (char *) malloc(ilen * sizeof(char)); fread(bufp, ilen, 1, stdin); printf("<h3>Thank you for your reservation!</h3>"); strcpy(output, bufp); free(bufp); /* declare data variables */ sscanf(output, "name=%[^&]&to=%[^&]&date=%[^&]&phone=%[^&]&num_guest=%[^&]", name, to, date, phone, num_guest); replace(date, "%3A", ":"); // makes the date readable replace(to, "%40", "@"); // makes the mail readable } printf( "<div>" "%s" "</div>", form ); } return 0; }
解决方案
只需在POST请求的参数解析完成后,直接调用目标函数即可。同时建议增加基础错误检查,避免异常情况影响服务稳定性。
修改后的POST分支代码
else if (strcmp(method, "POST") == 0) { int ilen = atoi(getenv("CONTENT_LENGTH")); // 检查请求数据长度合法性 if (ilen <= 0) { printf("<h3>Invalid request data!</h3>"); strcpy(form, "<a href=''>Go back to booking form</a>"); goto end_post; } char *bufp = (char *) malloc(ilen * sizeof(char)); // 检查内存分配是否成功 if (!bufp) { printf("<h3>Server error: failed to allocate memory!</h3>"); strcpy(form, "<a href=''>Go back to booking form</a>"); goto end_post; } fread(bufp, ilen, 1, stdin); printf("<h3>Thank you for your reservation!</h3>"); strcpy(output, bufp); free(bufp); /* 解析表单数据 */ int parse_result = sscanf(output, "name=%[^&]&to=%[^&]&date=%[^&]&phone=%[^&]&num_guest=%[^&]", name, to, date, phone, num_guest); // 确认所有参数解析成功 if (parse_result != 5) { printf("<h3>Invalid form data! Please try again.</h3>"); strcpy(form, "<a href=''>Go back to booking form</a>"); goto end_post; } replace(date, "%3A", ":"); replace(to, "%40", "@"); // 调用业务函数并处理返回结果 if (book_for(to, name, num_guest, phone, date) != 0) { printf("<h3>Failed to save your reservation! Please try again later.</h3>"); } else { if (send_mail("addr", "confirmation.mail") != 0) { printf("<h3>Reservation saved, but failed to send confirmation email.</h3>"); } else { printf("<h3>Confirmation email sent to %s!</h3>", to); } } // 提供返回表单的入口 strcpy(form, "<a href=''>Make another reservation</a>"); end_post: ; }
修改说明
- 核心功能整合:在参数解析和URL解码完成后,直接调用
book_for()和send_mail()完成业务逻辑 - 错误防护:
- 校验请求数据长度,过滤无效请求
- 检查内存分配结果,避免空指针异常
- 验证表单参数解析完整性,确保数据有效性
- 判断业务函数返回值,给用户明确操作反馈
- 用户体验优化:操作完成后提供返回表单的链接,方便用户再次预订
内容的提问来源于stack exchange,提问作者Julio
相关产品推荐
相关产品推荐

