HTTP (HyperText Transfer Protocol)是一款用于传输超文本的应用层协议。AliOS Things的网络协议栈包含了HTTP组件,提供HTTP客户端标准能力。开发者可以通过组件API,在设备端快速实现与HTTP服务端的数据交互。
下图是AliOS Things中HTTP组件的结构示意图。
其包括:
- HTTP Core:HTTP核心模块,主要包括连接建立、请求创建、请求发送、回复接收、回复解析。 该模块实现HTTP主流程,对外提供标准的HTTP协议行为。
- Method API:请求方法接口模块,主要包括get、post、put、delete等基本请求方法接口。该模块封装了HTTP核心模块的发送请求、接收响应的过程,以简化用户的调用。
API列表
名称 | 说明 |
httpclient_prepare | 分配HTTP请求头部缓存和响应缓存 |
httpclient_unprepare | 释放HTTP请求头部缓存和响应缓存 |
httpclient_reset | 重置HTTP请求头部缓存和响应缓存 |
httpclient_get | 发起GET请求,并接收响应 |
httpclient_head | 发起HEAD请求,并接收响应 |
httpclient_post | 发起POST请求,并接收响应 |
httpclient_put | 发起PUT请求,并接收响应 |
httpclient_delete | 发起DELETE请求,并接收响应 |
httpclient_conn |
发起HTTP连接 |
httpclient_send | 发送HTTP请求 |
httpclient_recv | 接收HTTP响应 |
httpclient_clse | 关闭HTTP连接 |
httpclient_set_custom_header | 设置HTTP用户定义头部 |
httpclient_get_response_code | 获取HTTP响应码 |
httpclient_get_response_header_value | 获取HTTP响应头部字段值 |
httpclient_formdata_addtext | 添加文本form data |
httpclient_formdata_addfile | 添加文件form data |
注:该列表为新API,deprecated API不在本文介绍范围内。
使用
添加该组件
在使用http的组件或应用对应的aos.mk添加
$(NAME)_COMPONENTS += http
在使用http的组件或应用对应的Config.in添加
select AOS_COMP_HTTP if !AOS_CREATE_PROJECT
select CONFIG_NEW_HTTP_API
注:选择CONFIG_NEW_HTTP_API使用新API。如果为兼容以前的代码,请使用deprecated API(见http/http.h)。
头文件
对外头文件代码位于include/network/http
,包括
http/http.h
http/httpclient.h
使用时需包含
#include <httpclient.h>
#include <http.h>
使用示例
httpclient_t client = {0};
httpclient_data_t client_data = {0};
int ret;
char * customer_header = "Accept: */*\r\n";
memset(req_buf, 0, sizeof(req_buf));
client_data.header_buf = req_buf;
client_data.header_buf_len = sizeof(req_buf);
memset(rsp_buf, 0, sizeof(rsp_buf));
client_data.response_buf = rsp_buf;
client_data.response_buf_len = sizeof(rsp_buf);
httpclient_set_custom_header(&client, customer_header);
ret = httpclient_get(&client, url, &client_data);
if( ret >= 0 ) {
LOGI(TAG, "Data received: %s", client_data.response_buf);
}
更详细的例子请参考application/example/example_legacy/httpclient_app
API 详情
httpclient_prepare
原型
HTTPC_RESULT httpclient_prepare(httpclient_data_t *client_data, int header_size, int resp_size);
接口说明
分配HTTP请求头部缓存和响应缓存。
参数说明
参数 | 数据类型 | 方向 | 说明 |
---|---|---|---|
client_data | httpclient_data_t * | 输入 | 用户数据结构体 |
header_size | int | 输入 | 头部大小 |
resp_size | int | 输入 | 回复大小 |
httpclient_data_t定义见标准宏和结构体说明。
返回值说明
值 | 说明 |
---|---|
0 | 成功 |
非0 | 失败,失败原因见HTTPC_RESULT定义 |
接口示例
httpclient_data_t client_data = {0};
/* 分配空间,并将地址挂在client_data结构体 */
ret = httpclient_prepare(&client_data, REQ_BUF_SIZE, RSP_BUF_SIZE);
if (ret != 0) {
LOGE(TAG, "httpclient prepare buffer failed");
}
httpclient_unprepare
原型
HTTPC_RESULT httpclient_unprepare(httpclient_data_t *client_data);
接口说明
释放HTTP请求头部缓存和响应缓存。
参数说明
参数 | 数据类型 | 方向 | 说明 |
---|---|---|---|
client_data | httpclient_data_t * | 输入 | 用户数据结构体 |
返回值说明
值 | 说明 |
---|---|
0 | 成功 |
非0 | 失败,失败原因见HTTPC_RESULT定义 |
接口示例
httpclient_data_t client_data = {0};
/* 分配空间,并将地址挂在client_data结构体 */
ret = httpclient_prepare(&client_data, REQ_BUF_SIZE, RSP_BUF_SIZE);
if (ret != 0) {
LOGE(TAG, "httpclient prepare buffer failed");
}
/* 释放client_data中的缓存空间 */
httpclient_unprepare(&client_data);
httpclient_reset
原型
void httpclient_reset(httpclient_data_t *client_data);
接口说明
重置HTTP请求头部缓存和响应缓存。
参数说明
参数 | 数据类型 | 方向 | 说明 |
---|---|---|---|
client_data | httpclient_data_t * | 输入 | 用户数据结构体 |
返回值说明
无
接口示例
httpclient_data_t client_data = {0};
/* 分配空间,并将地址挂在client_data结构体 */
ret = httpclient_prepare(&client_data, REQ_BUF_SIZE, RSP_BUF_SIZE);
if (ret != 0) {
LOGE(TAG, "httpclient prepare buffer failed");
}
/* 重置client_data中的缓存空间 */
httpclient_reset(&client_data);
httpclient_get
原型
HTTPC_RESULT httpclient_get(httpclient_t *client, char *url, httpclient_data_t *client_data);
接口说明
根据连接参数,向URL发送GET请求,并等待回复。
参数说明
参数 | 数据类型 | 方向 | 说明 |
---|---|---|---|
client | httpclient_t * | 输入 | HTTP client上下文,包含配置参数,如服务端口号、服务端证书等 |
url | char * | 输入 | URL地址 |
client_data | httpclient_data_t * | 输出 | 回复数据,由调用者分配空间 |
返回值说明
值 | 说明 |
---|---|
0 | 成功 |
非0 | 失败,失败原因见HTTPC_RESULT定义 |
接口示例
httpclient_t client = {0};
httpclient_data_t client_data = {0};
/* 分配空间,并将地址挂在client_data结构体 */
ret = httpclient_prepare(&client_data, REQ_BUF_SIZE, RSP_BUF_SIZE);
if (ret != 0) {
LOGE(TAG, "httpclient prepare buffer failed");
}
/* 向URL发送GET请求,并等待回复 */
ret = httpclient_get(&client, url, &client_data);
if( ret >= 0 ) {
LOGI(TAG, "Data received: %s", client_data.response_buf);
}
httpclient_post
原型
HTTPC_RESULT httpclient_post(httpclient_t *client, char *url, httpclient_data_t *client_data);
接口说明
根据连接参数,向URL发送POST请求,并等待回复
参数说明
参数 | 数据类型 | 方向 | 说明 |
---|---|---|---|
client | httpclient_t * | 输入 | HTTP client上下文,包含配置参数,如服务端口号、服务端证书等 |
url | char * | 输入 | URL地址 |
client_data | httpclient_data_t * | 输出 | 回复数据,由调用者分配空间 |
返回值说明
值 | 说明 |
---|---|
0 | 成功 |
非0 | 失败,失败原因见HTTPC_RESULT定义 |
接口示例
httpclient_t client = {0};
httpclient_data_t client_data = {0};
/* 分配空间,并将地址挂在client_data结构体 */
ret = httpclient_prepare(&client_data, REQ_BUF_SIZE, RSP_BUF_SIZE);
if (ret != 0) {
LOGE(TAG, "httpclient prepare buffer failed");
}
/* 向URL发送POST请求,并等待回复 */
ret = httpclient_post(&client, url, &client_data);
if( ret >= 0 ) {
LOGI(TAG, "Data received: %s", client_data.response_buf);
}
httpclient_put
原型
HTTPC_RESULT httpclient_put(httpclient_t *client, char *url, httpclient_data_t *client_data);
接口说明
根据连接参数,向URL发送PUT请求,并等待回复
参数说明
参数 | 数据类型 | 方向 | 说明 |
---|---|---|---|
client | httpclient_t * | 输入 | HTTP client上下文,包含配置参数,如服务端口号、服务端证书等 |
url | char * | 输入 | URL地址 |
client_data | httpclient_data_t * | 输出 | 回复数据,由调用者分配空间 |
返回值说明
值 | 说明 |
---|---|
0 | 成功 |
非0 | 失败,失败原因见HTTPC_RESULT定义 |
接口示例
httpclient_t client = {0};
httpclient_data_t client_data = {0};
/* 分配空间,并将地址挂在client_data结构体 */
ret = httpclient_prepare(&client_data, REQ_BUF_SIZE, RSP_BUF_SIZE);
if (ret != 0) {
LOGE(TAG, "httpclient prepare buffer failed");
}
/* 向URL发送PUT请求,并等待回复 */
ret = httpclient_put(&client, url, &client_data);
if( ret >= 0 ) {
LOGI(TAG, "Data received: %s", client_data.response_buf);
}
httpclient_delete
原型
HTTPC_RESULT httpclient_delete(httpclient_t *client, char *url, httpclient_data_t *client_data);
接口说明
根据连接参数,向URL发送delete请求,并等待回复
参数说明
参数 | 数据类型 | 方向 | 说明 |
---|---|---|---|
client | httpclient_t * | 输入 | HTTP client上下文,包括配置参数,如服务端口号、服务端证书 |
url | char * | 输入 | URL地址 |
client_data | httpclient_data_t * | 输出 | 回复数据,由调用者分配空间 |
返回值说明
值 | 说明 |
---|---|
0 | 成功 |
非0 | 失败,失败原因见HTTPC_RESULT定义 |
接口示例
httpclient_t client = {0};
httpclient_data_t client_data = {0};
/* 分配空间,并将地址挂在client_data结构体 */
ret = httpclient_prepare(&client_data, REQ_BUF_SIZE, RSP_BUF_SIZE);
if (ret != 0) {
LOGE(TAG, "httpclient prepare buffer failed");
}
/* 向URL发送DELETE请求,并等待回复 */
ret = httpclient_delete(&client, url, &client_data);
if( ret >= 0 ) {
LOGI(TAG, "Data received: %s", client_data.response_buf);
}
httpclient_get_response_code
原型
int httpclient_get_response_code(httpclient_t *client);
接口说明
获取上一次请求服务端回复码
参数说明
参数 | 数据类型 | 方向 | 说明 |
---|---|---|---|
client | httpclient_t * | 输入 | HTTP client上下文,包括配置参数,如服务端口号、服务端证书 |
返回值说明
值 | 说明 |
---|---|
整型 | 服务端回复码 |
接口示例
/* 向URL发送GET请求,并等待回复 */
ret = httpclient_get(&client, url, &client_data);
if( ret >= 0 ) {
LOGI(TAG, "Data received: %s", client_data.response_buf);
}
/* 获取回复码 */
code = httpclient_get_response_code(&client);
httpclient_get_response_header_value
原型
int httpclient_get_response_header_value(char *header_buf, char *name, int *val_pos, int *val_len);
接口说明
根据名称获取回复头部特定值
参数说明
参数 | 数据类型 | 方向 | 说明 |
---|---|---|---|
header_buf | char * | 输入 | 头部缓存 |
name | char * | 输入 | 头部名称 |
val_pos | int * | 输出 | 头部开始位置 |
val_len | int * | 输出 | 头部长度 |
返回值说明
值 | 说明 |
---|---|
0 | 成功 |
非0 | 错误 |
接口示例
/* 向URL发送GET请求,并等待回复 */
ret = httpclient_get(&client, url, &client_data);
if( ret >= 0 ) {
LOGI(TAG, "Data received: %s", client_data.response_buf);
}
/* 获取回复头部Content-lenght字段值 */
if(0 == httpclient_get_response_header_value(client_data.header_buf, "Content-Length", (int *)&val_pos, (int *)&val_len)) {
sscanf(client_data.header_buf + val_pos, "%d", &total_len);
}
httpclient_set_custom_header
原型
void httpclient_set_custom_header(httpclient_t *client, char *header);
接口说明
设置HTTP请求报文定制头部
参数说明
参数 | 数据类型 | 方向 | 说明 |
---|---|---|---|
client | httpclient_t * | 输入 | HTTP client上下文,包含配置参数,如服务端口号、服务端证书等 |
header | char * | 输入 | 定制头部指针,必须为有\r\n结束符的字符串 |
返回值说明
无
接口示例
char * customer_header = "Accept: */*\r\n";
/* 设置请求头部 */
httpclient_set_custom_header(&client, customer_header);
/* 向URL发送GET请求,并等待回复 */
ret = httpclient_get(&client, url, &client_data);
if( ret >= 0 ) {
LOGI(TAG, "Data received: %s", client_data.response_buf);
}
httpclient_formdata_addtext
原型
int httpclient_formdata_addtext(httpclient_data_t* client_data, char* content_disposition, char* content_type, char* name, char* data, int data_len);
接口说明
添加文本表单数据
参数说明
参数 | 数据类型 | 方向 | 说明 |
---|---|---|---|
client_data | httpclient_data_t* | 输入 | 待添加的HTTP数据结构体地址 |
content_disposition | char * | 输入 | 待添加的内容地址 |
content_type | char * | 输入 | 内容类型的地址 |
name | char * | 输入 | 名称的地址 |
data | char * | 输入 | 表单数据地址 |
data_len | int | 输入 | 表单数据长度 |
返回值说明
值 | 说明 |
---|---|
0 | 成功 |
-1 | 错误 |
接口示例
char * upload_text = "upload text example";
/* 添加文本表单 */
httpclient_formdata_addtext(&client_data, "form-data", "application/octet-stream","uploadText", upload_text, strlen(upload_text));
/* 上传表单数据 */
httpc_post(&client, url, &client_data);
httpclient_formdata_addfile
原型
int httpc_formdata_addfile(httpclient_data_t* client_data, char* content_disposition, char* name, char* content_type, char* file_path);
接口说明
添加文件表单数据
参数说明
参数 | 数据类型 | 方向 | 说明 |
---|---|---|---|
client_data | httpclient_data_t* | 输入 | 待添加的HTTP数据结构体地址 |
content_disposition | char * | 输入 | 待添加的内容地址 |
name | char * | 输入 | 名称的地址 |
content_type | char * | 输入 | 内容类型的地址 |
file_path | char * | 输入 | 文件路径 |
返回值说明
值 | 说明 |
---|---|
0 | 成功 |
-1 | 错误 |
接口示例
/* 添加文件表单 */
httpclient_formdata_addfile(&client_data, "form-data", "uploadFile", "application/octet-stream", src_path);
/* 上传表单数据 */
httpc_post(&client, url, &client_data);
httpclient_send
原型
HTTPC_RESULT httpclient_send(httpclient_t *client, const char *url, int method, httpclient_data_t *client_data);
接口说明
向服务端发送请求
参数说明
参数 | 数据类型 | 方向 | 说明 |
---|---|---|---|
client | httpclient_t * | 输入 | HTTP client上下文,包含配置参数,如服务端口号、服务端证书等 |
url | const char * | 输入 | 请求地址 |
method | int | 输入 | 请求方法 |
client_data | const char * | 输入 | 用户数据结构体,包含发送头部缓存 |
返回值说明
值 | 说明 |
0 | 成功 |
非0 | 失败,失败原因见HTTPC_RESULT定义 |
接口示例
httpclient_t client = { 0 };
httpclient_data_t client_data = {0};
/* 准备client_data缓存空间 */
/* 建立HTTP连接 */
...
/* 向远端发送GET请求 */
ret = httpclient_send(&client, url, HTTP_GET, &client_data);
if(HTTP_SUCCESS != ret) {
LOGE(TAG, "http send request failed");
return -1;
}
httpclient_recv
原型
HTTPC_RESULT httpclient_recv(httpclient_t *client, httpclient_data_t *client_data);
接口说明
接收服务端回复
参数说明
参数 | 数据类型 | 方向 | 说明 |
---|---|---|---|
client | httpclient_t * | 输入 | HTTP client上下文,包含配置参数,如服务端口号、服务端证书等 |
client_data | httpclient_data_t * | 输出 | 用户数据结构体,包含接收回复缓存,该空间由用户分配 |
返回值说明
值 | 说明 |
0 | 成功 |
非0 | 失败,失败原因见HTTPC_RESULT定义 |
接口示例
while (total_len == 0 || recv_total_len < total_len) {
/* 从远端接收数据 */
ret = httpclient_recv(&client, &client_data);
if (ret == HTTP_SUCCESS || ret == HTTP_EAGAIN) {
recv_len = client_data.content_block_len;
/* 处理缓存中的数据 */
} else {
recv_len = 0;
}
if (ret < 0) {
break;
}
}
httpclient_conn
原型
HTTPC_RESULT httpclient_conn(httpclient_t *client, const char *url);
接口说明
建立HTTP连接。
参数说明
参数 | 数据类型 | 方向 | 说明 |
---|---|---|---|
client | httpclient_t * | 输入 | HTTP client上下文,包含配置参数,如服务端口号、服务端证书等 |
url | const char * | 输入 | HTTP/HTPS地址 |
返回值说明
值 | 说明 |
0 | 成功 |
非0 | 失败,失败原因见HTTPC_RESULT定义 |
接口示例
/* 根据URL与远端建立HTTP/HTTPS连接 */
ret = httpclient_conn(&client, url);
if(HTTP_SUCCESS != ret ) {
LOGE(TAG, "http connect failed");
return -1;
}
httpclient_clse
原型
void httpclient_clse(httpclient_t *client);
接口说明
关闭http连接
参数说明
参数 | 数据类型 | 方向 | 说明 |
---|---|---|---|
client | httpclient_t * | 输入 | HTTP client上下文,包含配置参数,如服务端口号、服务端证书等 |
返回值说明
无
接口示例
/* 根据URL与远端建立HTTP/HTTPS连接 */
ret = httpclient_conn(&client, url);
/* 关闭HTTP连接 */
httpclient_clse(&client);
配置说明
HTTP可配置项包括:
- 是否支持HTTP安全通道,默认为否
移植说明
HTTP模块需要实现连接wrapper
接口 | 描述 |
int http_tcp_conn_wrapper(httpclient_t *client, const char *host) |
建立TCP连接 client:HTTP上下文 host:远端服务地址 返回值:0成功,-1失败 |
int http_tcp_conn_wrapper(httpclient_t *client, const char *host) |
关闭TCP连接 client:HTTP上下文 返回值:0成功,-1失败 |
int http_tcp_send_wrapper(httpclient_t *client, const char *data, int length) |
向TCP远端发送数据 client:HTTP上下文 data:数据地址 length:长度 返回值:>0发送长度,-1失败 |
int http_tcp_recv_wrapper(httpclient_t *client, char *buf, int buflen, int timeout_ms, int *p_read_len) |
接收TCP数据client:HTTP上下文 buf:接收缓存 buflen:缓存大小 timeout_ms:超时时间 p_read_len:接收长度 返回值:HTTPC_RESULT |
int http_ssl_conn_wrapper(httpclient_t *client, const char *host) |
建立SSL连接 client:HTTP上下文 host:远端服务地址 返回值:0成功,-1失败 |
int http_ssl_close_wrapper(httpclient_t *client) |
关闭SSL连接 client:HTTP上下文 返回值:0成功,-1失败 |
int http_ssl_send_wrapper(httpclient_t *client, const char *data, size_t length) |
向SSL远端发送数据 client:HTTP上下文 data:数据地址 length:长度 返回值:>0发送长度,-1失败 |
int http_ssl_recv_wrapper(httpclient_t *client, char *buf, int buflen, int timeout_ms, int *p_read_len); |
接收SSL数据 client:HTTP上下文 buf:接收缓存 buflen:缓存大小 timeout_ms:超时时间 p_read_len:接收长度 返回值:HTTPC_RESULT |
标准宏和结构体说明
HTTPC_RESULT枚举定义
/** @brief http error code */
typedef enum {
HTTP_EAGAIN = 1, /**< 更多的数据 */
HTTP_SUCCESS = 0, /**< 操作成功 */
HTTP_ENOBUFS = -1, /**< 缓存错误 */
HTTP_EARG = -2, /**< 参数错误 */
HTTP_ENOTSUPP = -3, /**< 不支持 */
HTTP_EDNS = -4, /**< DNS解析错误 */
HTTP_ECONN = -5, /**< 连接失败 */
HTTP_ESEND = -6, /**< 发送数据失败 */
HTTP_ECLSD = -7, /**< 连接关闭 */
HTTP_ERECV = -8, /**< 接收失败 */
HTTP_EPARSE = -9, /**< url解析是吧 */
HTTP_EPROTO = -10, /**< 协议错误 */
HTTP_EUNKOWN = -11, /**< 未知错误 */
HTTP_ETIMEOUT = -12, /**< 超时 */
} HTTPC_RESULT;
httpclient_t结构体定义
typedef struct {
int socket; /**< 套接字ID */
int remote_port; /**< 远端port */
int response_code; /**< 响应码 */
char *header; /**< HTTP请求头部 */
char *auth_user; /**< 用户名 */
char *auth_password; /**< 密码 */
bool is_http; /**< 是否是HTTP连接 */
#if CONFIG_HTTP_SECURE
const char *server_cert; /**< 服务端证书地址 */
const char *client_cert; /**< 客户端证书地址 */
const char *client_pk; /**< 客户端私钥 */
int server_cert_len; /**< 服务端证书长度 */
int client_cert_len; /**< 客户端证书长度 */
int client_pk_len; /**< 客户端私钥长度 */
void *ssl; /**< ssl上下文地址 */
#endif
} httpclient_t;
httpclient_data_t结构体定义
typedef struct {
bool is_more; /* 指示是否需要接收更多数据 */
bool is_chunked; /* 指示收到的数据是否分块(chunked) */
int retrieve_len; /* 需要获取的总长度 */
int response_content_len; /* 回复内容的长度*/
int content_block_len; /* 单块长度 */
int post_buf_len; /* post数据缓存大小 */
int response_buf_len; /* 回复主体缓存大小 */
int header_buf_len; /* 回复头部缓存大小 */
char *post_content_type; /* post数据类型 */
char *post_buf; /* post数据缓存地址 */
char *response_buf; /* 回复主体缓存地址*/
char *header_buf; /* 回复头部缓存地址 */
bool is_redirected; /* 是否是重定向URL */
char* redirect_url; /* 重定向URL */
} httpclient_data_t;
HTTP_REQUEST_TYPE枚举定义
typedef enum {
HTTP_GET,
HTTP_POST,
HTTP_PUT,
HTTP_DELETE,
HTTP_HEAD
} HTTP_REQUEST_TYPE;
在文档使用中是否遇到以下问题
更多建议
匿名提交