目录
1 接口总览
http_req是请求处理相关代码,这里面一共包含4个接口,即构造对象、释放资源、设置报文头以及发送请求
http_req *http_req_new(void);
void http_req_destroy(http_req *a_req);
int http_req_prepare(http_req *a_req);
int http_req_send(http_req *a_req, http_trans_conn *a_conn);
2 构造对象
http_req_new构造一个请求资源对象,具体内容可以参考前文的http_req结构体内容
/*
* 返回值:分配好资源的http_req内容
*/
http_req *
http_req_new(void)
{
http_req *l_return = NULL;
l_return = (http_req *)malloc(sizeof(http_req));
memset(l_return, 0, sizeof(http_req));
/* 默认1.1版本 */
l_return->http_ver = 1.1;
l_return->headers = http_hdr_list_new();
return l_return;
}
3 析构对象
当分配的资源使用完毕需要释放资源,则使用http_req_destroy接口
/*
* 输入参数:http_req_new分配的http_req资源
*/
void
http_req_destroy(http_req *a_req)
{
if (!a_req)
return;
if (a_req->headers)
http_hdr_list_destroy(a_req->headers);
free(a_req);
}
4 设置报文头
主要设置的是host信息,如果是post、put或者trace请求的话则设置Content-Length字段,如果没有设置代理的话则还需要设置User-Agent字段
/*
* 输入参数:http_req,请求资源
* 输出参数:http_req,http_req对象资源
* 返回值: 0-成功 -1-失败
*/
int
http_req_prepare(http_req *a_req)
{
int l_return = 0;
char l_buf[30];
if (!a_req)
return -1;
memset(l_buf, 0, 30);
/* 设置请求域名或者host信息 */
http_hdr_set_value(a_req->headers,http_hdr_Host,a_req->host);
/* 监测报文是否带有报文体 */
if ((a_req->type == http_req_type_post) ||
(a_req->type == http_req_type_put) ||
(a_req->type == http_req_type_trace))
{
sprintf(l_buf, "%d", a_req->body_len);
http_hdr_set_value(a_req->headers,http_hdr_Content_Length,l_buf);
}
/* 如果未设置用户代理,则设置默认值 */
if (http_hdr_get_value(a_req->headers, http_hdr_User_Agent) == NULL)
http_hdr_set_value(a_req->headers, http_hdr_User_Agent,"libghttp/1.0");
return l_return;
}
5 发送请求
在该接口内如果是异步处理的话则直接跳转到操作位置,将数据打包发送,如果是同步则按照既定步骤一步步的将数据处理发送。
/*
* 输入参数:http_req,请求资源
* 输入参数:a_conn,网络资源
* 返回值: HTTP_TRANS_ERR 发送错误,HTTP_TRANS_NOT_DONE 没有传送结束,HTTP_TRANS_DONE 传送结束
*/
int
http_req_send(http_req *a_req, http_trans_conn *a_conn)
{
char *l_request = NULL;
int l_request_len = 0;
int i = 0;
int l_len = 0;
int l_headers_len = 0;
int l_rv = 0;
char *l_content = NULL;
/* 如果是异步发送则直接跳转到操作位置 */
if (a_conn->sync == HTTP_TRANS_ASYNC)
{
if (a_req->state == http_req_state_sending_request)
goto http_req_state_sending_request_jump;
if (a_req->state == http_req_state_sending_headers)
goto http_req_state_sending_headers_jump;
if (a_req->state == http_req_state_sending_body)
goto http_req_state_sending_body_jump;
}
/* 分配足够的空间存储header首行 */
l_request = malloc(30 + strlen(a_req->resource) + (a_conn->proxy_host ? (strlen(a_req->host) + 20) : 0));
memset(l_request, 0, 30 + strlen(a_req->resource) + (a_conn->proxy_host ? (strlen(a_req->host) + 20) : 0));
/* copy it into the buffer */
if (a_conn->proxy_host)
{
l_request_len = sprintf(l_request,"%s %s HTTP/%01.1f\r\n",http_req_type_char[a_req->type],a_req->full_uri,a_req->http_ver);
}
else
{
l_request_len = sprintf(l_request,"%s %s HTTP/%01.1f\r\n",http_req_type_char[a_req->type],a_req->resource,a_req->http_ver);
}
printf("request:%s\n",l_request);
/* 将请求header首行放到发送缓冲区*/
http_trans_append_data_to_buf(a_conn, l_request, l_request_len);
/* free up the request - we don't need it anymore */
free(l_request);
l_request = NULL;
/* 设置状态 */
a_req->state = http_req_state_sending_request;
http_req_state_sending_request_jump:
/* 发送请求 */
do {
l_rv = http_trans_write_buf(a_conn);
if ((a_conn->sync == HTTP_TRANS_ASYNC) && (l_rv == HTTP_TRANS_NOT_DONE))
return HTTP_TRANS_NOT_DONE;
if ((l_rv == HTTP_TRANS_DONE) && (a_conn->last_read == 0))
return HTTP_TRANS_ERR;
} while (l_rv == HTTP_TRANS_NOT_DONE);
/* 重置缓冲区 */
http_trans_buf_reset(a_conn);
/* 将header里面的所有内容放到发送缓冲区 */
for (i = 0; i < HTTP_HDRS_MAX; i++)
{
l_len = 0;
if (a_req->headers->header[i])
{
l_len = strlen(a_req->headers->header[i]);
if (l_len > 0)
{
http_trans_append_data_to_buf(a_conn, a_req->headers->header[i], l_len);
l_headers_len += l_len;
http_trans_append_data_to_buf(a_conn, ": ", 2);
l_headers_len += 2;
/* note, it's ok to have no value for a request */
if ((l_len = strlen(a_req->headers->value[i])) > 0)
{
http_trans_append_data_to_buf(a_conn, a_req->headers->value[i], l_len);
l_headers_len += l_len;
}
http_trans_append_data_to_buf(a_conn, "\r\n", 2);
l_headers_len += 2;
}
}
}
http_trans_append_data_to_buf(a_conn, "\r\n", 2);
l_headers_len += 2;
/* set the state */
a_req->state = http_req_state_sending_headers;
http_req_state_sending_headers_jump:
/* 发送报文头 */
do {
l_rv = http_trans_write_buf(a_conn);
if ((a_conn->sync == HTTP_TRANS_ASYNC) && (l_rv == HTTP_TRANS_NOT_DONE))
return HTTP_TRANS_NOT_DONE;
if ((l_rv == HTTP_TRANS_DONE) && (a_conn->last_read == 0))
return HTTP_TRANS_ERR;
} while (l_rv == HTTP_TRANS_NOT_DONE);
/* reset the buffer */
http_trans_buf_reset(a_conn);
l_content = http_hdr_get_value(a_req->headers, http_hdr_Content_Length);
if (l_content)
{
/* 将请求报文体放到发送缓冲区 */
http_trans_append_data_to_buf(a_conn, a_req->body, a_req->body_len);
a_req->state = http_req_state_sending_body;
http_req_state_sending_body_jump:
do {
l_rv = http_trans_write_buf(a_conn);
if ((a_conn->sync == HTTP_TRANS_ASYNC) && (l_rv == HTTP_TRANS_NOT_DONE))
return HTTP_TRANS_NOT_DONE;
if ((l_rv == HTTP_TRANS_DONE) && (a_conn->last_read == 0))
return HTTP_TRANS_ERR;
} while (l_rv == HTTP_TRANS_NOT_DONE);
/* reset the buffer */
http_trans_buf_reset(a_conn);
}
return HTTP_TRANS_DONE;
}