HTTP 开发指导_Rev1.2

English

修订记录

版本

日期

作者

修订内容

Rev1.0

2023-09-14

CLY

创建文档

Rev1.1

2024-03-25

sxx

更改文档名称

Rev1.2

2025-10-28

LXH

增加发送、接收超时时间设置
增加最大发送数据大小

1 简介

本文档介绍 NT26F HTTP函数接口, 函数接口位于 components/kernel/lierda_api/liot_http/liot_http.h 文件声明。

2 API 函数概览

函数

说明

liot_httpc_new()

创建一个新的HTTP客户端句柄并初始化HTTP客户端资源

liot_httpc_perform()

发送 HTTP 请求

liot_httpc_stop()

停止HTTP请求

liot_httpc_release()

释放 HTTP 客户端资源

liot_httpc_setopt()

配置 HTTP 客户端属性

liot_httpc_getinfo()

获取HTTP消息头信息

liot_httpc_formadd()

配置 HTTP 表单属性。

liot_httpc_is_running()

判断HTTP客户端是否处于运行态

liot_httpc_url_parse()

解析URL

3 类型说明

3.1 liot_httpc_method_e

HTTP请求方法。

  1. 声明

typedef enum
{
    LIOT_HTTPC_METHOD_NONE   = 0,
    LIOT_HTTPC_METHOD_GET    = 1,
    LIOT_HTTPC_METHOD_POST   = 2,
    LIOT_HTTPC_METHOD_PUT    = 3,
    LIOT_HTTPC_METHOD_HEAD   = 4,
    LIOT_HTTPC_METHOD_LAST   = 5,
    LIOT_HTTPC_METHOD_DELETE = 6,
} liot_httpc_method_e;
  1. 参数

参数

说明

LIOT_HTTPC_METHOD_NONE

无请求

LIOT_HTTPC_METHOD_GET

HTTP GET请求

LIOT_HTTPC_METHOD_POST

HTTP POST请求

LIOT_HTTPC_METHOD_PUT

HTTP PUT 请求,暂不支持

LIOT_HTTPC_METHOD_HEAD

HTTP HEAD请求

LIOT_HTTPC_METHOD_LAST

上一次的请求,暂不支持

LIOT_HTTPC_METHOD_DELETE

HTTP DELETE请求

3.2 liot_http_client_t

HTTP客户端句柄。

  1. 声明

typedef int liot_http_client_t;

4 API 函数详解

4.1 liot_httpc_new

该函数用于创建一个新的 HTTP 客户端句柄并初始化 HTTP 客户端资源。

  1. 声明

int liot_httpc_new(liot_http_client_t *client, liot_http_client_event_cb_t cb, void *arg);
  1. 参数

client:

[Out] HTTP客户端句柄。

cb:

[In] HTTP请求事件回调处理函数。参考liot_http_client_event_cb_t。

arg:

[In] HTTP请求事件回调处理函数的参数。

  1. 返回值

执行结果码,请参考liot_httpc_result_code_e。

4.1.1 liot_http_client_event_cb_t

请求事件回调处理函数。

  1. 声明

typedef void (*liot_http_client_event_cb_t)(liot_http_client_t *client, int evt, int evt_code, void *arg);
  1. 参数

client:

[Out] http客户端句柄。

evt:

[In] http请求事件类型。参考liot_httpc_event_id_e。

evt_code:

[In] http请求事件结果类型。参考liot_httpc_event_type_e。

arg:

[In] http请求事件回调处理函数的参数。

  1. 返回值

执行结果码,请参考 liot_httpc_result_code_e。

4.1.2 liot_httpc_event_id_e

HTTP API 执行结果错误码。

  1. 声明

typedef enum
{
    LIOT_HTTP_EVENT_SESSION_ESTABLISH  = 0,
    LIOT_HTTP_EVENT_RESPONE_STATE_LINE = 1,
    LIOT_HTTP_EVENT_SESSION_DISCONNECT = 2,
} liot_httpc_event_id_e;
  1. 参数

参数

说明

LIOT_HTTP_EVENT_SESSION_ESTABLISH

HTTP请求连接建立成功

LIOT_HTTP_EVENT_RESPONE_STATE_LINE

HTTP请求开始响应

LIOT_HTTP_EVENT_SESSION_DISCONNECT

HTTP请求连接断开连接

4.1.3 liot_httpc_event_type_e

HTTP请求过程中触发事件的状态。

  1. 声明

typedef enum
{
    LIOT_HTTPC_SESSION_OPEN      = 1,
    LIOT_HTTPC_UPLOAD_START      = 2,
    LIOT_HTTPC_UPLOAD_END        = 3,
    LIOT_HTTPC_RESPONSE_STATUS   = 4,
    LIOT_HTTPC_RESPONSE_COMPLETE = 5,
    LIOT_HTTPC_RESPONSE_TIMEOUT  = 6,
    LIOT_HTTPC_SESSION_CLOSE     = 7,
    LIOT_HTTPC_RAW_REQ_START     = 8,
    LIOT_HTTPC_RAW_REQ_END       = 9,
} liot_httpc_event_type_e;
  1. 参数

参数

说明

LIOT_HTTPC_SESSION_OPEN

HTTP客户端连接建立成功事件状态

LIOT_HTTPC_UPLOAD_START

HTTP客户端开始上传文件事件状态,暂不支持

LIOT_HTTPC_UPLOAD_END

HTTP客户端完成上传文件事件,暂不支持

LIOT_HTTPC_RESPONSE_STATUS

HTTP客户端开始接收响应数据事件

LIOT_HTTPC_RESPONSE_COMPLETE

HTTP客户端完成接收响应数据事件

LIOT_HTTPC_RESPONSE_TIMEOUT

HTTP客户端接收响应数据超时事件

LIOT_HTTPC_SESSION_CLOSE

HTTP客户端链路已关闭事件

LIOT_HTTPC_RAW_REQ_START

HTTP客户端开始上传RAW文件事件,暂不支持

LIOT_HTTPC_RAW_REQ_END

HTTP客户端上传RAW文件已完成事件,暂不支持

4.1.4 liot_httpc_result_code_e

HTTP API 执行结果错误码。

  1. 声明

typedef enum
{
    LIOT_HTTPC_SUCCESS            = LIOT_SUCCESS,
    LIOT_HTTPC_ERR_INVALID_PARAM  = 1 | LIOT_HTTP_ERRCODE_BASE,
    LIOT_HTTPC_ERR_UNKNOWN        = 2 | LIOT_HTTP_ERRCODE_BASE,
    LIOT_HTTPC_ERR_OUT_OF_MEM     = 3 | LIOT_HTTP_ERRCODE_BASE,
    LIOT_HTTPC_ERR_SOCKET_FAILURE = 4 | LIOT_HTTP_ERRCODE_BASE,
    LIOT_HTTPC_ERR_NOT_SUPPORT    = 5 | LIOT_HTTP_ERRCODE_BASE,
    LIOT_HTTPC_ERR_NOT_ALLOW      = 6 | LIOT_HTTP_ERRCODE_BASE,
    LIOT_HTTPC_ERR_NO_NETWORK     = 7 | LIOT_HTTP_ERRCODE_BASE,
    LIOT_HTTPC_ERR_NO_SSL_CERT    = 8 | LIOT_HTTP_ERRCODE_BASE,
    LIOT_HTTPC_ERR_TIMEOUT        = 9 | LIOT_HTTP_ERRCODE_BASE,
    LIOT_HTTPC_EMPTY_URL          = 10 | LIOT_HTTP_ERRCODE_BASE,
    LIOT_HTTPC_SSL_ERROR          = 11 | LIOT_HTTP_ERRCODE_BASE,
} liot_httpc_result_code_e;
  1. 参数

参数

说明

LIOT_HTTPC_SUCCESS

成功

LIOT_HTTPC_ERR_INVALID_PARAM

函数参数错误

LIOT_HTTPC_ERR_UNKNOWN

未知的错误

LIOT_HTTPC_ERR_OUT_OF_MEM

空间不足

LIOT_HTTPC_ERR_SOCKET_FAILURE

socket失败

LIOT_HTTPC_ERR_NOT_SUPPORT

功能不支持

LIOT_HTTPC_ERR_NOT_ALLOW

操作不允许

LIOT_HTTPC_ERR_NO_NETWORK

无网络

LIOT_HTTPC_ERR_NO_SSL_CERT

SSL无证书

LIOT_HTTPC_ERR_TIMEOUT

超时

LIOT_HTTPC_EMPTY_URL

URL为空

LIOT_HTTPC_SSL_ERROR

SSL错误

4.2 liot_httpc_perform

发送 HTTP 请求。

  1. 声明

int liot_httpc_perform(liot_http_client_t *client);
  1. 参数

client:

[In] HTTP请求客户端句柄。

  1. 返回值

执行结果码,请参考 liot_httpc_result_code_e。

4.3 liot_httpc_stop

该函数用于停止HTTP客户端请求。

  1. 声明

int liot_httpc_stop(liot_http_client_t *client);
  1. 参数

client:

[In] HTTP请求客户端句柄。

  1. 返回值

执行结果码,请参考 liot_httpc_result_code_e。

4.4 liot_httpc_release

该函数用于释放HTTP请求客户端。

  1. 声明

int liot_httpc_release(liot_http_client_t *client);
  1. 参数

client:

[In] HTTP请求客户端句柄。

  1. 返回值

执行结果码,请参考 liot_httpc_result_code_e。

4.5 liot_httpc_setopt

该函数用于设置HTTP相关属性。

  1. 声明

int liot_httpc_setopt(liot_http_client_t *client, int opt_tag, ...);
  1. 参数

client:

[In] HTTP请求客户端句柄。

opt_tag:

[In] HTTP属性标签。参考第5.5.3章,相关liot_httpc_option_e说明。

[In] HTTP属性值。

  1. 返回值

执行结果码,请参考 liot_httpc_result_code_e。

4.5.1 liot_http_client_write_data_cb_t

收到 HTTP 响应数据后,会自动调用该回调函数进行数据处理。

  1. 声明

typedef int (*liot_http_client_write_data_cb_t)(
    liot_http_client_t *client, void *arg, char *data, int size, unsigned char end);
  1. 参数

client:

[In] HTTP客户端句柄。

arg:

[In] HTTP回调处理函数的参数。

data:

[In] HTTP请求响应的数据。

size:

[In] HTTP请求响应数据的长度。

end:

[In] HTTP请求响应结束符。

false:数据接收未结束。

true:数据接收完毕。

  1. 返回值

接收处理的数据长度。

4.5.2 liot_http_client_read_data_cb_t

当发生 HTTP POST/PUT 请求时,会自动调用该回调函数读取待上传的数据。。

  1. 声明

typedef int (*liot_http_client_read_data_cb_t)(
            liot_http_client_t *client, void *arg, char *data, int size);
  1. 参数

client:

[In] HTTP客户端句柄。

arg:

[In] HTTP回调处理函数的参数。

data:

[Out] 用于存储待上传数据的空间。

size:

[In] 指定长度。

  1. 返回值

实际读取的数据长度。

4.5.3 liot_httpc_option_e

HTTP相关属性。

  1. 声明

typedef enum
{
    LIOT_HTTP_CLIENT_OPT_PDPCID = 1,
    LIOT_HTTP_CLIENT_OPT_BASIC_AUTH,
    LIOT_HTTP_CLIENT_OPT_REQUEST_HEADER,
    LIOT_HTTP_CLIENT_OPT_WRITE_HEADER,
    LIOT_HTTP_CLIENT_OPT_INTERVAL_TIME,
    LIOT_HTTP_CLIENT_OPT_METHOD,
    LIOT_HTTP_CLIENT_OPT_WRITE_FUNC,
    LIOT_HTTP_CLIENT_OPT_WRITE_DATA,
    LIOT_HTTP_CLIENT_OPT_READ_FUNC,
    LIOT_HTTP_CLIENT_OPT_READ_DATA,
    LIOT_HTTP_CLIENT_OPT_UPLOAD_LEN,
    LIOT_HTTP_CLIENT_OPT_URL,
    LIOT_HTTP_CLIENT_OPT_URI,
    LIOT_HTTP_CLIENT_OPT_SIM_ID,
    LIOT_HTTP_CLIENT_OPT_RAW_REQUEST,
    LIOT_HTTP_CLIENT_OPT_RAW_FILE,
    LIOT_HTTP_CLIENT_OPT_AUTH_INFO,
    LIOT_HTTP_CLIENT_OPT_RESPONSE_TIME,
    LIOT_HTTP_CLIENT_OPT_BODY_DATA_TYPE,
    LIOT_HTTP_CLIENT_OPT_FORM_OPTION,
    LIOT_HTTP_CLIENT_OPT_CUSTOME_HEADER,
    LIOT_HTTP_CLIENT_OPT_SEND_TIMEOUT,
    LIOT_HTTP_CLIENT_OPT_RECV_TIMEOUT,
    LIOT_HTTP_CLIENT_OPT_SSLCTXID,
    LIOT_HTTP_CLIENT_OPT_SSL_VERIFY_LEVEL,
    LIOT_HTTP_CLIENT_OPT_SSL_CACERT_PATH,
    LIOT_HTTP_CLIENT_OPT_SSL_OWNCERT_PATH,
    LIOT_HTTP_CLIENT_OPT_SSL_SNI,
    LIOT_HTTP_CLIENT_OPT_SSL_VERSION,
    LIOT_HTTP_CLIENT_OPT_SSL_HS_TIMEOUT,
    LIOT_HTTP_CLIENT_OPT_SSL_IGNORE_LOCALTM,
    LIOT_HTTP_CLIENT_OPT_SSL_IGNORE_INVALID_CERT_SIGN,
    LIOT_HTTP_CLIENT_OPT_SSL_IGNORE_CERT_ITEM,
    LIOT_HTTP_CLIENT_OPT_SSL_IGNORE_MULTI_CERTCHAIN_VERIFY,
} liot_httpc_option_e;
  1. 参数

参数

说明

LIOT_HTTP_CLIENT_OPT_PDPCID

设置 HTTP 客户端使用的数据通道号,即执行数据拨号操作时使用的PDP上下文ID。
参数类型:int,范围0到7。

LIOT_HTTP_CLIENT_OPT_BASIC_AUTH

设置 HTTP 基本认证的用户名和密码。
格式:Username:Password。
最大长度为 255字节。参数类型:char *。

LIOT_HTTP_CLIENT_OPT_REQUEST_HEADER

设置自定义 HTTP 请求头属性。
可以多次配置此选项设置多个自定义 HTTP 请求。
参数类型:char *。

LIOT_HTTP_CLIENT_OPT_WRITE_HEADER

设置HTTP响应头。
参数类型:char *。

LIOT_HTTP_CLIENT_OPT_INTERVAL_TIME

设置等待 HTTP 响应数据的最大间隔时间。
参数类型:int。单位:秒;范围:1~65536。

LIOT_HTTP_CLIENT_OPT_METHOD

设置 HTTP 请求方式。
参数类型:liot_httpc_method_e。

LIOT_HTTP_CLIENT_OPT_WRITE_FUNC

设置处理 HTTP 响应数据的回调函数。参数类型:http_client_write_data_cb_t

LIOT_HTTP_CLIENT_OPT_WRITE_DATA

设置处理 HTTP 响应数据的回调函数的参数。参数类型:void *

LIOT_HTTP_CLIENT_OPT_READ_FUNC

设置读取HTTP请求上传数据的回调函数。
http请求为LIOT_HTTPC_METHOD_POST和LIOT_HTTPC_METHOD_POST时有效。

LIOT_HTTP_CLIENT_OPT_READ_DATA

设置读取HTTP请求上传数据的回调函数的入参。参数类型:void *

LIOT_HTTP_CLIENT_OPT_UPLOAD_LEN

设置读取HTTP请求上传数据的长度。长度最新的SDK V05.03以及之后为不超过100K,之前的老版本为20kb。

LIOT_HTTP_CLIENT_OPT_URL

设置HTTP请求的URL,字符串类型,长度不超过512字节。

LIOT_HTTP_CLIENT_OPT_URI

设置HTTP请求的URI,字符串类型,长度不超过512字节。

LIOT_HTTP_CLIENT_OPT_SIM_ID

执行数据拨号操作时使用的(U)SIM 卡,当前不支持。

LIOT_HTTP_CLIENT_OPT_RAW_REQUEST

设置HTTP请求上传数据格式。
0:LIOT_HTTPC_RAW_DATA,RAW格式数据。
1:LIOT_HTTPC_FORM_DATA,Form表单格式数据。

LIOT_HTTP_CLIENT_OPT_RAW_FILE

设置HTTP请求文件名称。类型:char*。

LIOT_HTTP_CLIENT_OPT_AUTH_INFO

设置HTTP请求头中auth属性,暂不支持。

LIOT_HTTP_CLIENT_OPT_RESPONSE_TIME

设置HTTP请求响应时间。暂不支持。

LIOT_HTTP_CLIENT_OPT_BODY_DATA_TYPE

暂不支持。

LIOT_HTTP_CLIENT_OPT_FORM_OPTION

暂不支持。

LIOT_HTTP_CLIENT_OPT_CUSTOME_HEADER

暂不支持。

LIOT_HTTP_CLIENT_OPT_SEND_TIMEOUT

设置发送数据的超时时间,默认2s。(V05.04及之后版本支持)

LIOT_HTTP_CLIENT_OPT_RECV_TIMEOUT

设置接收数据的超时时间,默认20s。(V05.04及之后版本支持)

LIOT_HTTP_CLIENT_OPT_SSLCTXID

设置SSL上下文ID。范围:0~5。

LIOT_HTTP_CLIENT_OPT_SSL_VERIFY_LEVEL

设置SSL的校验等级。范围:0~2。参考第 [liot_https_verify_level_e]。

LIOT_HTTP_CLIENT_OPT_SSL_CACERT_PATH

设置SSL的CA证书路径。字符串类型,长度不超过255。

LIOT_HTTP_CLIENT_OPT_SSL_OWNCERT_PATH

设置SSL的本地证书的路径。字符串类型,长度不超过255。

LIOT_HTTP_CLIENT_OPT_SSL_SNI

设置SSL是否支持SNI扩展。
0:不支持SNI。
1:支持SNI。

LIOT_HTTP_CLIENT_OPT_SSL_VERSION

设置SSL上下文的SSL版本。范围0~4。
0:SSL 3.0
1:TLS 1.0
2:TLS 2.0
3:TLS 3.0
4:全部

LIOT_HTTP_CLIENT_OPT_SSL_HS_TIMEOUT

设置SSL上下文握手的超时时间。范围1~65535,单位秒。

LIOT_HTTP_CLIENT_OPT_SSL_IGNORE_LOCALTM

设置SSL上下文忽略本地时间与证书有效期之间的不匹配。暂不支持。

LIOT_HTTP_CLIENT_OPT_SSL_IGNORE_INVALID_CERT_SIGN

设置SSL上下文忽略证书签名无效。暂不支持。

LIOT_HTTP_CLIENT_OPT_SSL_IGNORE_CERT_ITEM

设置SSL上下文忽略证书项验证。暂不支持。

LIOT_HTTP_CLIENT_OPT_SSL_IGNORE_MULTI_CERTCHAIN_VERIFY

设置SSL上下文忽略证书链中存在多条证书的验证错误。暂不支持。

4.5.4 liot_https_verify_level_e

HTTPS 连接认证类型。

  1. 声明

typedef enum
{
    LIOT_HTTPS_VERIFY_NONE          = 0,
    LIOT_HTTPS_VERIFY_SERVER        = 1,
    LIOT_HTTPS_VERIFY_SERVER_CLIENT = 2,
} liot_https_verify_level_e;
  1. 参数

参数

说明

LIOT_HTTPS_VERIFY_NONE

无认证

LIOT_HTTPS_VERIFY_SERVER

单向认证,即服务器认证

LIOT_HTTPS_VERIFY_SERVER_CLIENT

双向认证,即客户端认证

4.6 liot_httpc_getinfo

该函数用于获取HTTP请求响应头部相关信息。

  1. 声明

int liot_httpc_getinfo(liot_http_client_t *client, int info, ...);
  1. 参数

client:

[In] HTTP请求客户端句柄。

opt_tag:

[In] HTTP属性标签。参考 liot_httpc_info_type_e说明。

[In] HTTP属性值。

  1. 返回值

执行结果码,请参考liot_httpc_result_code_e。

4.6.1 liot_httpc_info_type_e

  1. HTTP响应头信息结构体部分属性定义。

typedef enum
{
    LIOT_HTTPC_STATUS_CODE    = 1,
    LIOT_HTTPC_CHUNK_ENCODE   = 2,
    LIOT_HTTPC_CONTENT_LEN    = 3,
    LIOT_HTTPC_CONTENT_RANGE  = 4,
    LIOT_HTTPC_DATE           = 5,
    LIOT_HTTPC_LOCATION       = 6,
    LIOT_HTTPC_NREAD_DATA_LEN = 7,
} liot_httpc_info_type_e;
  1. 参数

参数

说明

LIOT_HTTPC_STATUS_CODE

HTTP请求响应码

LIOT_HTTPC_CHUNK_ENCODE

获取响应体数据是否为 chunk 编码格式。
参数类型:int *。
0 否
1 是

LIOT_HTTPC_CONTENT_LEN

获取内容长度。该值仅当 HTTP 响应头中带有内容长度时方可获取。
参数类型:int *。

LIOT_HTTPC_CONTENT_RANGE

分包下载时获取整包大小(4.01版本后支持)

LIOT_HTTPC_DATE

获取时间。参数类型:char*。

LIOT_HTTPC_LOCATION

获取重定向的 URL。该值仅当响应码为 3xx 时方可获取。
参数类型:char*。

LIOT_HTTPC_NREAD_DATA_LEN

暂不支持

4.7 liot_httpc_formadd

该函数用于配置HTTP表单属性。

  1. 声明

int liot_httpc_formadd(liot_http_client_t *client, int opt_tag, ...);
  1. 参数

client:

[In] HTTP请求客户端句柄。

opt_tag:

[In] HTTP表单属性标签。参考 liot_httpc_formopt_e说明。

[In] HTTP表单属性值。

  1. 返回值

执行结果码,请参考 liot_httpc_result_code_e。

4.7.1 liot_httpc_formopt_e

  1. HTTP请求表单属性定义。

typedef enum
{
    LIOT_HTTP_FORM_NAME         = 1,
    LIOT_HTTP_FORM_FILENAME     = 2,
    LIOT_HTTP_FORM_CONTENT_TYPE = 3,
} liot_httpc_formopt_e;
  1. 参数

参数

说明

LIOT_HTTP_FORM_NAME

设置上传数据在服务器上的存储格式为file或image等。
参数类型:char*。

LIOT_HTTP_FORM_FILENAME

设置上传数据在服务器保存的名字。仅在LIOT_HTTP_FORM_NAME 配置为 file 时有效。
参数类型:char*。

LIOT_HTTP_FORM_CONTENT_TYPE

设 置 上 传 数 据 对 应 的 内 容 类 型。仅LIOT_HTTP_FORM_NAME 配置为 file 时有效。
参数类型:char*。

4.8 liot_httpc_is_running

该函数用于判断当前HTTP客户端是否处于运行状态。

  1. 声明

bool liot_httpc_is_running(liot_http_client_t *client);
  1. 参数

client:

[In] HTTP请求客户端句柄。

  1. 返回值

true:HTTP客户端处于运行状态。

false:HTTP客户端处于非运行状态。

4.9 liot_httpc_url_parse

该函数用于解析HTTP请求URL。

  1. 声明

bool liot_httpc_url_parse(char *url_str, liot_httpc_url_s *url);
  1. 参数

url_str:

[In] 输入的HTTP请求URL。

url:

[Out] 解析后的数据格式。详情见 liot_httpc_url_s。

  1. 返回值

true:解析成功。

false:解析失败。

4.9.1 liot_httpc_url_s

  1. 选择的运营商信息结构体定义

typedef struct
{
    liot_httpc_scheme_e scheme;
    char *host;
    unsigned short port;
    char *uri;
} liot_httpc_url_s;
  1. 参数

类型

参数

描述

liot_httpc_scheme_e

scheme

HTTP请求类型,参考第5.9.2 liot_httpc_scheme_e

char *

host

HTTP请求host,最大长度不超过512字节

unsigned short

port

HTTP请求地址端口号,范围0~65535

char *

uri

HTTP请求的URI,最大长度不超过512字节

4.9.2 liot_httpc_scheme_e

定义HTTP请求类型。

  1. 声明

typedef enum
{
    LIOT_HTTPC_SCHEME_INVALID = 0,
    LIOT_HTTPC_SCHEME_HTTP    = 1,
    LIOT_HTTPC_SCHEME_HTTPS   = 2
} liot_httpc_scheme_e
  1. 参数

参数

说明

LIOT_HTTPC_SCHEME_INVALID

无效参数

LIOT_HTTPC_SCHEME_HTTP

HTTP协议

LIOT_HTTPC_SCHEME_HTTPS

HTTPS协议

5 代码示例

示例代码参考 examples/demo/src/demo_http.c 文件。


static liot_sem_t http_semp;
static liot_sem_t http_semp1;

// #define LIOT_HTTP_DEMO_SSL_TEST  1

char *liot_http_ca_cert_path   = "UFS:http_ca_cert.pem";
char *liot_http_user_cert_path = "UFS:http_user_cert.pem";
char *liot_http_user_key_path  = "UFS:http_user_key.pem";

char *liot_http_upload_path = "UFS:http_test.txt";
char *liot_http_upload_data = "http_upload_test";
int liot_http_upload_len    = 0;

char *liot_http_ca_cert_data ="...";//配置为相应CA证书内容

char *liot_http_user_cert_data ="...";//配置相应用户证书

char *liot_http_user_key_data ="...";//配置相应用户私钥

static int http_uploadfile_init(void)
{
    int ret  = 0;
    LFILE fp = -1;

    if (liot_file_exist(liot_http_upload_path) != LIOT_FS_NOT_EXIST)
    {
        liot_remove(liot_http_upload_path);
    }
    fp = liot_fopen(liot_http_upload_path, "w+");
    if (fp < 0)
    {
        liot_trace("open file:%s failed!!!!", liot_http_upload_path);
        return -1;
    }
    ret = liot_fwrite(liot_http_upload_data, strlen(liot_http_upload_data), 1, fp);
    liot_trace("%s:%d", __FUNCTION__, __LINE__);
    liot_trace("ret:%d,%s", ret, liot_http_upload_data);
    liot_http_upload_len = liot_fsize(fp);
    liot_trace("%s:%d  liot_http_upload_len:%d", __FUNCTION__, __LINE__, liot_http_upload_len);
    if (ret != strlen(liot_http_upload_data))
    {
        liot_trace("ret:%d", ret);
        liot_fclose(fp);
        return -1;
    }
    liot_fclose(fp);
    return 0;
}

static int http_ca_cert_init(void)
{
    int ret  = 0;
    LFILE fp = -1;

    if (liot_file_exist(liot_http_ca_cert_path) != LIOT_FS_NOT_EXIST)
    {
        liot_remove(liot_http_ca_cert_path);
    }
    fp = liot_fopen(liot_http_ca_cert_path, "w+");
    if (fp < 0)
    {
        liot_trace("open file:%s failed!!!!", liot_http_ca_cert_path);
        return -1;
    }
    ret = liot_fwrite(liot_http_ca_cert_data, strlen(liot_http_ca_cert_data), 1, fp);
    liot_trace("%s:%d", __FUNCTION__, __LINE__);
    liot_trace("ret:%d", ret);
    if (ret != strlen(liot_http_ca_cert_data))
    {
        liot_trace("ret:%d", ret);
        liot_fclose(fp);
        return -1;
    }
    liot_fclose(fp);
    return 0;
}

static int http_user_cert_init(void)
{
    int ret  = 0;
    LFILE fp = -1;

    if (liot_file_exist(liot_http_user_cert_path) != LIOT_FS_NOT_EXIST)
    {
        liot_remove(liot_http_user_cert_path);
    }
    fp = liot_fopen(liot_http_user_cert_path, "w+");
    if (fp < 0)
    {
        liot_trace("open file:%s failed!!!!", liot_http_user_cert_path);
        return -1;
    }
    ret = liot_fwrite(liot_http_user_cert_data, strlen(liot_http_user_cert_data), 1, fp);
    liot_trace("%s:%d", __FUNCTION__, __LINE__);
    liot_trace("ret:%d", ret);
    if (ret != strlen(liot_http_user_cert_data))
    {
        liot_trace("ret:%d", ret);
        liot_fclose(fp);
        return -1;
    }
    liot_fclose(fp);
    return 0;
}

static int http_user_key_init(void)
{
    int ret  = 0;
    LFILE fp = -1;

    if (liot_file_exist(liot_http_user_key_path) != LIOT_FS_NOT_EXIST)
    {
        liot_remove(liot_http_user_key_path);
    }
    fp = liot_fopen(liot_http_user_key_path, "w+");
    if (fp < 0)
    {
        liot_trace("open file:%s failed!!!!", liot_http_user_key_path);
        return -1;
    }
    ret = liot_fwrite(liot_http_user_key_data, strlen(liot_http_user_key_data), 1, fp);
    liot_trace("%s:%d", __FUNCTION__, __LINE__);
    liot_trace("ret:%d", ret);
    if (ret != strlen(liot_http_user_key_data))
    {
        liot_trace("ret:%d", ret);
        liot_fclose(fp);
        return -1;
    }
    liot_fclose(fp);
    return 0;
}

static void http_event_cb(liot_http_client_t *client, int evt, int evt_code, void *arg)
{
    liot_trace("===http_event_cb===  evt:%d,evt_code:%d,%p", evt, evt_code, client);
    switch (evt)
    {
        case LIOT_HTTPC_SESSION_OPEN:
        {
            if (evt_code != LIOT_HTTPC_SUCCESS)
            {
                liot_trace("http session open fail");
                liot_rtos_semaphore_release(http_semp);
            }
        }
        break;
        case LIOT_HTTPC_UPLOAD_START:
        {
            liot_httpc_user_notify(client, LIOT_HTTPC_READ);
        }
        break;
        case LIOT_HTTPC_UPLOAD_END:
        {
        }
        break;
        case LIOT_HTTPC_RESPONSE_STATUS:
        {
            if (evt_code == LIOT_HTTPC_SUCCESS)
            {
                int resp_code      = 0;
                int content_length = 0;
                int chunk_encode   = 0;
                char *location     = NULL;
                char *date         = NULL;
                liot_httpc_getinfo(client, LIOT_HTTPC_STATUS_CODE, &resp_code);
                liot_httpc_getinfo(client, LIOT_HTTPC_CHUNK_ENCODE, &chunk_encode);
                liot_httpc_getinfo(client, LIOT_HTTPC_DATE, &date);
                if (date != NULL)
                {
                    liot_trace("===http_event_cb=== Date:%s", date);
                    free(location);
                }
                liot_trace("===http_event_cb=== resp_code:%d,chunk_encode:%d", resp_code, chunk_encode);
                if (chunk_encode == 0)
                {
                    liot_httpc_getinfo(client, LIOT_HTTPC_CONTENT_LEN, &content_length);
                    liot_trace("===http_event_cb=== content_length:%d", content_length);
                }
                else
                {
                    liot_trace("http chunk encode");
                }

                if (resp_code >= 300 && resp_code < 400)
                {
                    liot_httpc_getinfo(client, LIOT_HTTPC_LOCATION, &location);
                    liot_trace("===http_event_cb=== location:%s", location);
                    free(location);
                }
            }
        }
        break;
        case LIOT_HTTPC_RESPONSE_COMPLETE:
        {
            if (evt_code == LIOT_HTTPC_SUCCESS)
            {
                liot_trace("http transfer success");
            }
            else
            {
                liot_trace("http transfer fail");
            }
            liot_rtos_semaphore_release(http_semp);
        }
        break;
        case LIOT_HTTPC_SESSION_CLOSE:
        {
            liot_trace("http LIOT_HTTPC_SESSION_CLOSE success");
            liot_rtos_semaphore_release(http_semp1);
        }
        break;
    }
}

static int http_response_write_data_cb(liot_http_client_t *client, void *arg, char *data, int size, unsigned char end)
{
    liot_trace(">>>>>client:%p", client);
    liot_trace("===http_response_write_data_cb=== size:%d", size);
    unsigned char *recv_buf = NULL;
    recv_buf                = malloc(size + 1);
    if (recv_buf != NULL)
    {
        memset(recv_buf, 0, size + 1);
        memcpy(recv_buf, data, size);
        liot_trace("===http_response_write_data_cb=== recv_buf:%s", recv_buf);
        free(recv_buf);
        recv_buf = NULL;
    }
    return size;
}

static int http_request_read_data_cb(liot_http_client_t *client, void *arg, char *data, int size)
{
    int ret  = 0;
    LFILE fp = -1;
    liot_trace(">>>>>client:%p", client);

    if (client == NULL)
    {
        return 0;
    }

    fp = liot_fopen(liot_http_upload_path, "r+");
    if (fp < 0)
    {
        liot_trace("open file:%s failed!!!!", liot_http_upload_path);
        return 0;
    }
    ret = liot_fread(data, 1, size, fp);
    liot_fclose(fp);
    liot_trace("http_request_read_data_cb  data:%s", data);
    liot_trace("http_request_read_data_cb  size:%d", size);
    return ret;
}

void liot_http_demo_thread(void *arg)
{
    liot_http_client_t http_client = 0;
    int ret                        = 0;
    int cid                        = 1;
    liot_data_call_info_t info;
    uint8_t nSim = 0;

    int times = 0;
    while (LIOT_DATACALL_SUCCESS != (ret = liot_network_register_wait(nSim, 120)) && times < 10)
    {
        times++;
        liot_rtos_task_sleep_s(1);
    }

    if (LIOT_DATACALL_SUCCESS != ret)
    {
        liot_trace("====network register failure!!!!!====");
        if (LIOT_OSI_SUCCESS != liot_rtos_task_delete(NULL))
        {
            liot_trace("task deleted failed");
        }
        return;
    }

    ret = liot_start_data_call(nSim, cid, LIOT_DATA_TYPE_IP, "APNTEST", "", "", LIOT_DATA_AUTH_TYPE_NONE);
    if (ret != 0)
    {
        liot_trace("====data call failure!!!!=====");
    }

    // liot_rtos_task_sleep_ms(1000);

    ret = liot_get_data_call_info(nSim, cid, &info);
    if (ret != 0)
    {
        liot_trace("liot_get_data_call_info ret: %d", ret);
        liot_stop_data_call(nSim, cid);
        goto exit;
    }

    liot_rtos_semaphore_create(&http_semp, 0);
    liot_rtos_semaphore_create(&http_semp1, 0);

    liot_trace("info->profile_idx: %d", info.cid);
    liot_trace("info->ip_version: %d", info.ip_version);

    liot_trace("info->v4.state: %d", info.v4.state);

    liot_ip4addr_ntoa(&info.v4.addr.ip);
    liot_trace("info.v4.addr.ip: %s\r\n", liot_ip4addr_ntoa(&info.v4.addr.ip));

    liot_ip4addr_ntoa(&info.v4.addr.pri_dns);
    liot_trace("info.v4.addr.pri_dns: %s\r\n", liot_ip4addr_ntoa(&info.v4.addr.pri_dns));

    liot_ip4addr_ntoa(&info.v4.addr.sec_dns);
    liot_trace("info.v4.addr.sec_dns: %s\r\n", liot_ip4addr_ntoa(&info.v4.addr.sec_dns));

    http_ca_cert_init();
    http_user_cert_init();
    http_user_key_init();
    http_uploadfile_init();

    int http_method       = LIOT_HTTPC_METHOD_POST;
    liot_httpc_url_s *url = NULL;

    url = malloc(sizeof(liot_httpc_url_s));

#if LIOT_HTTP_DEMO_SSL_TEST
    int verify_level = LIOT_HTTPS_VERIFY_SERVER_CLIENT;

    url->host   = "112.31.84.164";
    url->scheme = LIOT_HTTPC_SCHEME_HTTPS;

    if (verify_level == LIOT_HTTPS_VERIFY_SERVER_CLIENT)
    {
        url->port = 8303;
        url->uri  = "/1K.txt";
    }
    else
    {
        url->port = 8301;
        url->uri  = "/9X07-QAT/1K.txt";
    }
#else
    url->host   = "cmp-net-monitor.xiot.senthink.com";
    url->port   = 0;
    url->scheme = LIOT_HTTPC_SCHEME_HTTP;
    url->uri    = "/getData-1";
#endif
    if (liot_httpc_new(&http_client, http_event_cb, NULL) != LIOT_HTTPC_SUCCESS)
    {
        liot_trace("http client create failed!!!!");
        goto exit;
    }
    liot_trace("%s:%d  %p,%p", __FUNCTION__, __LINE__, &http_client, http_client);

    if (http_method == LIOT_HTTPC_METHOD_POST)
    {
        url->host = "cmp-net-monitor.xiot.senthink.com";
        url->port = 0;
        url->uri  = "/pushData-1";

        liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_REQUEST_HEADER, "Content-type: multipart/form-data");
        liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_READ_FUNC, http_request_read_data_cb);
        // liot_trace("%s:%d  %p  %p", __FUNCTION__, __LINE__,&http_client,(void *)&http_client);
        liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_READ_DATA, (void *)&http_client);
        liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_UPLOAD_LEN, liot_http_upload_len);
        liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_BODY_DATA_TYPE, LIOT_HTTPC_FORM_DATA);
        liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_RAW_REQUEST, 0);
        liot_httpc_formadd(&http_client, LIOT_HTTP_FORM_NAME, "file");
        liot_httpc_formadd(&http_client, LIOT_HTTP_FORM_FILENAME, "http_upload.txt", liot_http_upload_len);
        //设置上传数据在服务器保存的名字 和本地文件的名字无关
        liot_httpc_formadd(&http_client, LIOT_HTTP_FORM_CONTENT_TYPE, "text/plain");
    }

    liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_SIM_ID, nSim);
    liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_PDPCID, cid);
    liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_METHOD, http_method);
    liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_URL, url);
    liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_WRITE_FUNC, http_response_write_data_cb);

#if LIOT_HTTP_DEMO_SSL_TEST
    unsigned short hs_timeout    = 300;
    char *ca_cert_path           = liot_http_ca_cert_path;
    liot_ssl_user_cert user_cert = {liot_http_user_cert_path, liot_http_user_key_path, NULL};

    liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_SSLCTXID, 1);
    liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_SSL_VERSION, LIOT_SSL_VERSION_3);
    liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_SSL_HS_TIMEOUT, hs_timeout);
    // liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_SSL_SNI, 0);

    liot_trace("%s:%d  verify_level:%d ", __FUNCTION__, __LINE__, verify_level);
    switch (verify_level)
    {
        case LIOT_HTTPS_VERIFY_SERVER:
        {
            liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_SSL_VERIFY_LEVEL, LIOT_HTTPS_VERIFY_SERVER);
            liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_SSL_CACERT_PATH, ca_cert_path);
            liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_SSL_IGNORE_INVALID_CERT_SIGN, 1);
            liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_SSL_IGNORE_CERT_ITEM, MBEDTLS_X509_BADCERT_FUTURE);
        }
        break;
        case LIOT_HTTPS_VERIFY_SERVER_CLIENT:
        {
            liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_SSL_VERIFY_LEVEL, LIOT_HTTPS_VERIFY_SERVER_CLIENT);
            liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_SSL_CACERT_PATH, ca_cert_path);
            liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_SSL_OWNCERT_PATH, user_cert);
            liot_httpc_setopt(&http_client, LIOT_HTTP_CLIENT_OPT_SSL_IGNORE_INVALID_CERT_SIGN, 1);
            liot_httpc_setopt(&http_client,
                              LIOT_HTTP_CLIENT_OPT_SSL_IGNORE_CERT_ITEM,
                              MBEDTLS_X509_BADCERT_FUTURE | MBEDTLS_X509_BADCERT_NOT_TRUSTED);
        }
        break;
    }
    liot_trace(">>>>>verify_level:%d ", verify_level);

#endif

    if (liot_httpc_perform(&http_client) == LIOT_HTTPC_SUCCESS)
    {
        liot_trace(">>>>>%p", http_semp);
        liot_rtos_semaphore_wait(http_semp, LIOT_WAIT_FOREVER);
        liot_trace("http perform success");
    }
    else
    {
        liot_trace("http perform fail");
    }

    liot_httpc_stop(&http_client);
    liot_rtos_semaphore_wait(http_semp1, LIOT_WAIT_FOREVER);
    liot_httpc_release(&http_client);

exit:
    liot_rtos_semaphore_delete(http_semp);
    liot_rtos_semaphore_delete(http_semp1);
    liot_trace("===liot_http_app_thread exit===");
    liot_rtos_task_delete(NULL);
}

运行结果:

_images/http-guide/image_1.png

其他疑问补充需确认