如何在libmicrohttpd中中断POST数据处理并向客户端响应
解决Libmicrohttpd中途中断POST处理并返回错误响应的问题
Libmicrohttpd支持迭代处理POST数据,但默认逻辑只能在接收完所有POST数据后才返回响应——即便处理中发现错误,也只能跳过后续上传、设置upload_data_size=0,无法立即中断并给客户端返回错误。如果在上传过程中直接调用MHD_queue_response会返回MHD_NO,可通过以下方式解决:
核心实现逻辑
Libmicrohttpd的回调机制要求必须先完成当前数据块的处理,再通过标记状态+后续回调触发响应的方式实现中途中断,不能在接收数据的回调分支里直接调用响应队列接口。
1. 标记错误并终止数据接收
当检测到错误(如POST数据格式非法、超出预设大小限制)时:
- 给自定义连接结构体(
con_info)标记错误状态,比如设置answercode为对应HTTP错误码(如MHD_HTTP_BAD_REQUEST) - 将
*upload_data_size设为0,告知Libmicrohttpd停止接收后续POST数据 - 返回
MHD_YES,让回调进入下一轮执行
2. 在回调下一轮触发错误响应
当回调再次被调用时,*upload_data_size会变为0(已终止数据接收),此时直接调用MHD_queue_response返回错误响应,最后返回MHD_NO关闭连接。
修改后的代码示例
{ struct connection_info_struct *con_info = *con_cls; if (0 != *upload_data_size) { /* 仍在接收POST数据 */ if (0 != con_info->answercode) { /* 已标记错误,直接触发响应并终止连接 */ *upload_data_size = 0; struct MHD_Response *response = MHD_create_response_from_buffer( strlen(postprocerror), (void*)postprocerror, MHD_RESPMEM_PERSISTENT ); if (response != NULL) { MHD_queue_response(connection, con_info->answercode, response); MHD_destroy_response(response); } return MHD_NO; // 返回MHD_NO终止连接 } if (MHD_YES != MHD_post_process( con_info->postprocessor, upload_data, *upload_data_size )) { // 标记错误状态 con_info->answerstring = postprocerror; con_info->answercode = MHD_HTTP_INTERNAL_SERVER_ERROR; // 终止后续数据接收 *upload_data_size = 0; return MHD_YES; // 让回调进入下一轮触发响应 } *upload_data_size = 0; return MHD_YES; } /* 上传完成或已终止上传 */ if (NULL != con_info->fp) { fclose(con_info->fp); con_info->fp = NULL; } if (0 == con_info->answercode) { con_info->answerstring = completepage; con_info->answercode = MHD_HTTP_OK; } struct MHD_Response *response = MHD_create_response_from_buffer( strlen(con_info->answerstring), (void*)con_info->answerstring, MHD_RESPMEM_PERSISTENT ); if (response != NULL) { MHD_queue_response(connection, con_info->answercode, response); MHD_destroy_response(response); } return MHD_NO; }
关键注意点
- 不能在
*upload_data_size != 0的分支直接调用MHD_queue_response:此时Libmicrohttpd仍处于请求输入处理阶段,队列响应会失败(返回MHD_NO)。 - 标记错误后返回
MHD_YES是为了让回调流程继续,直到进入*upload_data_size = 0的分支,此时再执行响应队列操作才会生效。
内容的提问来源于stack exchange,提问作者aryndin
相关产品推荐
相关产品推荐

