玩转 ESP32 + Arduino (十四) HTTPClient库访问网络资源

我们使用ESP32_Arduino自带库: HTTPClient

一. 请求相关API函数

首先,创建一个客户端对象

1. 初始化HTTP客户端 http_client.begin()

/**
 * 解析url以获得所有参数,默认port是80端口
 * @param url String
 */
bool begin(String url);

/**
 * 解析url以获得所有参数,默认port是80端口
 * @param client : 传入一个网络连接客户端
 * @param url String
 */
bool begin(WiFiClient &client, String url);

/**
 * 设置host port 以及uri
 * @param host String(192.168.1.12,不需要带上http://前缀)
 * @param port uint16_t
 * @param uri  String
 */
bool begin(String host, uint16_t port, String uri = "/");

/**
 * 设置host port 以及uri
 * @param client 传入一个网络连接客户端
 * @param host String(192.168.1.12,不需要带上http://前缀)
 * @param port uint16_t
 * @param uri  String
 * @param https bool 是否启用https
 */
bool begin(WiFiClient &client, String host, uint16_t port, String uri = "/", bool https = false);

/**
 * 设置host port 以及uri
 * @param host String(192.168.1.12,不需要带上http://前缀)
 * @param port uint16_t
 * @param uri  String
 * @param CAcert CA证书(https)
 */
bool begin(String host, uint16_t port, String uri, const char* CAcert);
bool begin(String host, uint16_t port, String uri, const char* CAcert, const char* cli_cert, const char* cli_key);

2. 设置长连接 http_client.setReuse(true);

/**
 * try to reuse the connection to the server
 * keep-alive 请求头
 * @param reuse bool
 */
void setReuse(bool reuse); // keep-alive

3. setUserAgent —— 封装标准请求头User-Agent

/**
 * set User Agent
 * User Agent请求头:使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。
 * @param userAgent const char *
 */
void setUserAgent(const String& userAgent);

4. addHeader —— 封装自定义请求头

函数说明:

/**
 * adds Header to the request
 * @param name  自定义请求头的名字
 * @param value 自定义请求头的参数值
 * @param first 是否要把当前请求头放在请求头的最前面
 * @param replace 是否需要替换之前已经存在该请求头的参数值,默认就是覆盖旧值
 */
void addHeader(const String& name, const String& value, bool first = false, bool replace = true);

5. GET 请求

函数说明:

/**
 * 发送一个get请求
 * @return http 状态码
 */
int GET();

6. POST 请求

函数说明:

/**
 * 发送一个post请求
 * @param payload uint8_t * 需要提交的数据
 * @param size size_t 提交的数据的字节数
 * @return http 状态码
 */
int POST(uint8_t * payload, size_t size);
 
/**
 * 发送一个post请求
 * @param payload String 需要提交的数据
 * @return http 状态码
 */
int POST(String payload);

7. PUT 请求

函数说明:

/**
 * 发送一个PUT请求(博主也没有用过PUT)
 * @param payload uint8_t * 需要提交的数据
 * @param size size_t 提交的数据的字节数
 * @return http 状态码
 */
int PUT(uint8_t * payload, size_t size);
/**
 * 发送一个PUT请求(博主也没有用过PUT)
 * @param payload String 需要提交的数据
 * @return http 状态码
 */
int PUT(String payload);

8. PATCH 请求

函数说明:

/**
 * 发送一个PATCH请求(博主也没有用过PATCH)
 * @param payload uint8_t * 需要提交的数据
 * @param size size_t 提交的数据的字节数
 * @return http 状态码
 */
int PATCH(uint8_t * payload, size_t size);
/**
 * 发送一个PATCH请求(博主也没有用过PATCH)
 * @param payload String 需要提交的数据
 * @return http 状态码
 */
int PATCH(String payload);

9. sendRequest 发送请求

GET、POST、PUT、PATCH最终都会调用sendRequest方法。
函数说明:

/**
 * GET、POST、PUT、PATCH最终都会调用sendRequest方法
 * sendRequest
 * @param type const char * 请求类型    "GET", "POST", ....
 * @param payload String  请求携带的数据  data for the message body
 * @return
 */
int sendRequest(const char * type, String payload);
/**
 * sendRequest
 * @param type const char * 请求类型 "GET", "POST", ....
 * @param payload uint8_t * 请求携带的数据  data for the message body if null not send
 * @param size size_t  请求携带的数据字节数 size for the message body if 0 not send
 * @return -1 if no info or > 0 when Content-Length is set by server
 */
int sendRequest(const char * type, uint8_t * payload = NULL, size_t size = 0);
/**
 * sendRequest
 * @param type const char *  请求类型 "GET", "POST", ....
 * @param stream Stream *  请求携带的数据流 data stream for the message body
 * @param size size_t   数据流大小 size for the message body if 0 not Content-Length is send
 * @return -1 if no info or > 0 when Content-Length is set by server
 */
int sendRequest(const char * type, Stream * stream, size_t size = 0);

10. setTimeout —— 设置请求超时

函数说明:

/**
 * 请求超时时间配置 ms为单位
 * @param timeout unsigned int  默认500ms
 */
void setTimeout(uint16_t timeout);

11. useHTTP10 —— http协议版本

函数说明:

/**
 * http协议版本
 * @param usehttp10 true表示用http1.0,默认是false,用http1.1
 */
void useHTTP10(bool usehttp10 = true);

12. end —— 结束请求

函数说明:

/**
 * 结束请求
 * called after the payload is handled
 */
void end(void);

二. 响应相关API

1. collectHeaders —— 设置需要收集的响应头

函数说明:

/**
 * 设置需要收集的响应头(1-n个)
 * @param headerKeys[] const char *   响应头的名字
 * @param headerKeysCount const size_t 响应头的个数
 * 注意点:headerKeys数组元素个数需要大于等于 headerKeysCount
 */
void collectHeaders(const char* headerKeys[], const size_t headerKeysCount);

RequestArgument定义如下:

struct RequestArgument {
    String key;//键值对里面的key
    String value;//键值对里面的value
};

注意点:

这个方法收集的headerKeys会在响应数据处理函数中应用到;

2. header(name) —— 获取具体响应头参数值

函数说明:

/**
 * 获取响应头参数值
 * @param name   const char *   响应头的名字
 * @return value of headerkey(name)
 */
String header(const char* name);

如果没有调用collectHeaders(),那就会默认返回空字符串;

3. header(index) —— 获取第index个响应头参数值

函数说明:

/**
 * 获取第i个响应头参数值
 * @param i   size_t   响应头索引值
 * @return value of header index
 */
String header(size_t i);

如果没有调用collectHeaders(),那就会默认返回空字符串;

4. headerName(index) —— 获取第i个响应头名字

函数说明:

/**
 * 获取第i个响应头名字
 * @param i   size_t   响应头索引值
 * @return name of header index
 */
String headerName(size_t i);

如果没有调用collectHeaders(),那就会默认返回空字符串;

5. headers() —— 获取收集响应头个数

函数说明:

/**
 * 获取收集响应头个数
 * @return count int
 */
int headers();                     // get header count

6. hasHeader(name) —— 判断是否存在某一个响应头

函数说明:

/**
 * 判断是否存在某一个响应头
 * @param name   const char*   响应头名字
 * @return bool
 */
bool hasHeader(const char* name);  // check if header exists

7. handleHeaderResponse —— 处理响应头数据

函数说明:

/**
 * 读取从服务器返回的响应头数据
 * @return int http状态码
 */
int handleHeaderResponse()

8. getString —— 获取响应数据

函数说明:

/**
 * 把响应数据转成字符串 (可能需要很大内存空间)
 * @return String 响应数据转成字符串
 */
String getString(void);

9. getStream —— 获取响应数据的流

函数说明:

/**
 * 获取响应数据的流
 * @return WiFiClient& tcp响应数据的流
 */
WiFiClient& getStream(void);

10. getStreamPtr —— 获取响应数据的流

函数说明:

/**
 * 获取响应数据的流
 * @return WiFiClient& tcp响应数据的流
 */
WiFiClient* getStreamPtr(void);

11. writeToStream —— 获取响应数据的流,并写到其他流对象

在讲解该函数之前,博主先给读者简单介绍一下 分块编码(Transfer-Encoding: chunked):

Transfer-Encoding,是一个 HTTP 头部字段(响应头域),字面意思是「传输编码」。最新的 HTTP 规范里,只定义了一种编码传输:分块编码(chunked)。
分块传输编码(Chunked transfer encoding)是超文本传输协议(HTTP)中的一种数据传输机制,允许HTTP由网页服务器发送给客户端的数据可以分成多个部分。分块传输编码只在HTTP协议1.1版本(HTTP/1.1)中提供。
数据分解成一系列数据块,并以一个或多个块发送,这样服务器可以发送数据而不需要预先知道发送内容的总大小。
具体方法

  1. 在头部加入 Transfer-Encoding: chunked 之后,就代表这个报文采用了分块编码。这时,报文中的实体需要改为用一系列分块来传输。
  2. 每个分块包含十六进制的长度值和数据,长度值独占一行,长度不包括它结尾的 CRLF(\r\n),也不包括分块数据结尾的 CRLF。
  3. 最后一个分块长度值必须为 0,对应的分块数据没有内容,表示实体结束。
/**
 * 把响应数据的流写到其他流对象
 * @param Stream* 其他流对象
 * @return int 写成功的字节数
 */
int writeToStream(Stream* stream);

12. getSize —— 获取响应数据的字节数

函数说明:

/**
 * 获取响应数据字节数
 * @return int 响应数据字节数
 */
int getSize(void);

13. errorToString —— 获取请求失败响应信息

函数说明:

/**
 * 根据错误码error返回具体错误信息
 * @param error 错误码
 * @return String 错误码对应的错误信息
 */
static String errorToString(int error);
#include <Arduino.h>
#include "WiFi.h"
#include "HTTPClient.h"

const char *ssid = "anny";                      //wifi名
const char *password = "20141208";              //wifi密码
const char *host = "https://api.seniverse.com"; //心知天气APIhost
const char *apiKey = "SZihSaRrzq6LclO30";       //API key 私钥
const char *city = "taian";                     //查询的城市
//示例: https://api.seniverse.com/v3/weather/now.json?key=your_private_key&location=beijing&language=zh-Hans&unit=c

WiFiClient wifi_Client;
HTTPClient http_client;
String req;
String rsp;

class cityWeather
{
public:
  char cityName[16];
  char weather[32];
  char temp[16];
  char update[32];
};

//Wifi连接
void setupWifi()
{
  delay(10);
  Serial.println("connecting WIFI");
  WiFi.begin(ssid, password);
  while (!WiFi.isConnected())
  {
    Serial.print(".");
    delay(500);
  }
  Serial.println("OK");
  Serial.println("Wifi connected");
}

void setUpHttpClient()
{
  req = (String)host + "/v3/weather/now.json?key=";
  req += apiKey;
  req += "&location=";
  req += city;
  req += "&language=zh-Hans&unit=c";
  Serial.println(req);
  if (http_client.begin(req))
  {
    Serial.println("HTTPclient setUp done!");
  }
}

void setup()
{
  Serial.begin(115200);
  delay(3000);
  setupWifi();
  setUpHttpClient();
}

void loop()
{
  int http_code = http_client.GET();
  Serial.println(http_code);
  if (http_code > 0)
  {
    Serial.printf("HTTP get code: %d\n", http_code);
    if (http_code == HTTP_CODE_OK)
    {
      rsp = http_client.getString();
      Serial.println(rsp);
    }
    else
    {
      Serial.printf("fail to get cityWeather,code:%d\n", http_code);
    }
  }
  delay(5000);
}
  • 7
    点赞
  • 69
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值