HTTP (HyperText Transfer Protocol)是一款用于传输超文本的应用层协议。AliOS Things的网络协议栈包含了HTTP组件,提供HTTP客户端标准能力。开发者可以通过组件API,在设备端快速实现与HTTP服务端的数据交互。

下图是AliOS Things中HTTP组件的结构示意图。

其包括:

  • HTTP CoreHTTP核心模块,主要包括连接建立、请求创建、请求发送、回复接收、回复解析。 该模块实现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>
如果为兼容以前的代码,使用deprecated API时需要包含:
#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;