我有以下代码来处理microhttp服务器中的POST数据:
#include <microhttpd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#define PAGE "<html><head><title>libmicrohttpd demo</title>"\
"</head><body>libmicrohttpd demo!!</body></html>"
struct postStatus {
bool status;
char *buff;
};
static int ahc_echo(void * cls,
struct MHD_Connection * connection,
const char * url,
const char * method,
const char * version,
const char * upload_data,
size_t * upload_data_size,
void ** ptr) {
const char * page = cls;
struct MHD_Response * response;
int ret;
struct postStatus *post = NULL;
post = (struct postStatus*)*ptr;
if(post == NULL) {
post = malloc(sizeof(struct postStatus));
post->status = false;
*ptr = post;
}
if(!post->status) {
post->status = true;
return MHD_YES;
} else {
if(*upload_data_size != 0) {
post->buff = malloc(*upload_data_size + 1);
snprintf(post->buff, *upload_data_size,"%s",upload_data);
*upload_data_size = 0;
return MHD_YES;
} else {
printf("Post data: %s\n",post->buff);
free(post->buff);
}
}
if(post != NULL)
free(post);
response = MHD_create_response_from_buffer (strlen(page),
(void*) page,
MHD_RESPMEM_PERSISTENT);
ret = MHD_queue_response(connection,
MHD_HTTP_OK,
response);
MHD_destroy_response(response);
return ret;
}
int main(int argc,
char ** argv) {
struct MHD_Daemon * d;
d = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY,
9000,
NULL,
NULL,
&ahc_echo,
PAGE,
MHD_OPTION_END);
if (d == NULL)
return 1;
sleep(10000);
MHD_stop_daemon(d);
return 0;
}
我尝试以下CURL命令来测试POST数据处理:
curl -XPOST -d '{"email":"test@gmail.com","password":"test"}' 'http://192.168.1.17:9000'
但是我得到了输出{"email":"test@gmail.com","password":"test"
。我没有得到最后一个}
。我也尝试了更长的json输入。还是一样。无法获得最后一个大括号。有人可以帮忙吗?
由于
编辑:我搞定了。我使用strncpy(post->buff, upload_data, *upload_data_size)
代替snprintf
。
有人可以解释为什么没有snprintf工作?
答案 0 :(得分:1)
ahc_echo()将被调用至少两次。请求数据可能被拆分为多个调用,并且此碎片非常随机(取决于缓冲区的请求,以及套接字上的每个read()调用返回的内容)。因此,您当前的代码仅适用于较小的请求,但仍然不安全。
MHD_create_post_processor()是解析此部分缓冲区的助手。
https://www.gnu.org/software/libmicrohttpd/tutorial.html#Processing-POST-data完成了这个
原因
snprintf(post->buff, *upload_data_size,"%s",upload_data);
不起作用,应该是
snprintf(post->buff, *upload_data_size + 1,"%s",upload_data);
以匹配malloc()中使用的内存大小,该内存具有\ 0终止的空间。
strncpy(post->buff, upload_data, *upload_data_size);
实际上是危险的,因为它应该是
strncpy(post->buff, upload_data, *upload_data_size);
post->buff[*upload_data_size] = 0;
由于你需要确保结果为零终止(幸运的是,内存现在已经包含零,这是使用malloc()
时的随机行为,而不是calloc()
),并且增加复制大小为*upload_data_size + 1
是错误的,因为这会使源溢出一个字节,其中也包含随机数据,甚至可能包含无效的内存。