1.前言
本文引用地址:在前面的文章中,介绍了 WiFi库 Tcp client的用法,并且用TCP模拟了Http请求。单缺点也很明显请求头需要我们自己来封装,一不留神就会出错,那么有没有一种好的方法来处理呢?那么是有的,我们可以使用提供的HTTPClient库,这样我们就可以方便的来处理HTTPClient请求。
HTTPClient库不属于WiFi库的一部分,所以需要引入#include <ESP8266HTTPClient.h>这个库
2.HTTPClient库
总的来说根据功能来分的话可以分为两类请求和响应。大家也可以下载HTTPclient库的源码进行分析研究。
POST / HTTP1.1
Host:www.wrox.com
User-Agent:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)
Content-Type:application/x-www-form-urlencoded
Content-Length:40
Connection: Keep-Alive
2.1请求的相关函数
2.1.1 begin封装请求的URL
bool begin(String url)
自动解析url以获得所有参数,默认port是80端口,,返回值为布尔类型,可以选读, 参数URL可以为以下几种格式,使用哪种格式按需求决定:
1. http://192.168.1.18/test.html
2. http://user:password@192.168.1.18/test.html
后面两种是需要验证的user:用户名, password是密码;
如果不带有端口号的话默认是80,不是80的话可以在host后面加上如:192.168.1.14:80;
bool begin(String host, uint16_t port, String uri = "/test.html");
设置host,port以及URL,特别需要注意的是在设置host时不要加http://
2.1.2 setReuse —— 封装请求头keep-alive
void setReuse(bool reuse);
设置connect属性是否为keep-alive,reuse为true时设置为keep-alive;
2.1.3.setUserAgent —— 封装User-Agent请求头
void setUserAgent(const String& userAgent);
封装User-Agent 的内容如:User-Agent:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)将User-Agent:的内容传给userAgent即可;
2.1.4. setAuthorization
Authorization 是采用 basic auth 授权方式验证客户端请求,Authorization 请求头对应的值是 (basic base64编码) 忽略括号,其中 base64编码是将 用户名:密码 这种格式进行处理生成**的,并且自动在 header 中添加 Authorization。
1.void setAuthorization(const char * user, const char * password);
2.void setAuthorization(const char * auth);
封装标准请求头Authorization(访问权限认证请求头信息)
2.1.5 addHeader
void addHeader(const String& name, const String& value, bool first = false, bool replace = true);
封装自定义请求头,name 自定义请求头的名字,value 自定义请求头的参数值,first 是否要把当前请求头放在请求头的最前面,replace 是否需要替换之前已经存在该请求头的参数值,默认就是覆盖旧值。在使用时需要注意的是自定义请求头,请求头不能为 Connection、User-Agent、Host、Authorization。
void HTTPClient::addHeader(const String& name, const String& value, bool first, bool replace)
{
// 过滤请求头
if(!name.equalsIgnoreCase(F("Connection")) &&
!name.equalsIgnoreCase(F("User-Agent")) &&
!name.equalsIgnoreCase(F("Host")) &&
!(name.equalsIgnoreCase(F("Authorization")) && _base64Authorization.length())){
String headerLine = name;
headerLine += ": ";
if (replace) {
int headerStart = _headers.indexOf(headerLine);
if (headerStart != -1) {
int headerEnd = _headers.indexOf('n', headerStart);
_headers = _headers.substring(0, headerStart) + _headers.substring(headerEnd + 1);
}
}
headerLine += value;
headerLine += "rn";
if(first) {
_headers = headerLine + _headers;
} else {
_headers += headerLine;
}
}
}
2.1.6 GET 请求
int GET();
发送一个get请求并返回http 状态码
2.1.7 POST 请求
该方法有两种形式:
1.int POST(uint8_t * payload, size_t size);
2.int POST(String payload);
第一种是义字符数组的形式发送请求,需要传递数组长度,第二种是以字符串形式的发送,两者返回的都是HTTP的状态码。
2.1.8 PUT 请求
该方法也有两种形式:
int PUT(uint8_t * payload, size_t size);
int PUT(String payload);
参数和返回值同上。
2.1.8 PATCH 请求
int PATCH(uint8_t * payload, size_t size);
int PATCH(String payload);
参数和返回值同上。
2.1.9 sendRequest 发送请求
GET、POST、PUT、PATCH最终都会调用sendRequest方法。三种形式如下:
int sendRequest(const char * type, String payload);
type:请求类型POST、GET、PUT……….
payload:请求要携带的数据
int sendRequest(const char * type, uint8_t * payload = NULL, size_t size = 0);
type:请求类型POST、GET、PUT……….
payload:请求要携带的数据
size:数据长度
int sendRequest(const char * type, Stream * stream, size_t size = 0);
type:请求类型POST、GET、PUT……….
payload:请求要携带的数据流
size:数据流长度
2.1.10 setTimeout
void setTimeout(uint16_t timeout);
设置请求超时时间,时间单位为ms,如果不设置默认为5000ms.
2.1.11 useHTTP10
void useHTTP10(bool usehttp10 = true);
设置HTTP协议的版本,是1.0的话为true,否则为false
2.1.12 end
void end(void);
结束请求,需要注意的是在keep-alive情况下不会断开连接,只会清除接收缓冲区;
2.2 http响应方法
2.2.1 collectHeaders
void collectHeaders(const char* headerKeys[], const size_t headerKeysCount);
设置需要收集的响应头,
headerKeys[]:响应头的名字
headerKeysCount:响应头的个数
2.2.2 header(name)
String header(const char* name);
获取具体响应头参数值,name:响应头的名字,返回参数值。
2.2.3 header(index)
String header(size_t i);
获取第i个响应头参数值,参数响应头的索引号,返回索引号对应的参数值。
2.2.4 headerName(index)
函数说明:
String headerName(size_t i);
获取第i个响应头名字,参数为响应头索引值,返回响应头名字。
注意点:
如果没有调用collectHeaders(),那就会默认返回空字符串;
2.2.5 headers()
int headers();
获取收集响应头个数
2.2.6 hasHeader(name)
bool hasHeader(const char* name);
判断某一个响应头是否存在,name:响应头名字,存在返回true,否则返回false.
2.2.7 handleHeaderResponse
int handleHeaderResponse()
读取从服务器返回的响应头数据,返回http的状态码。
2.2.8 getString
String getString(void);
获取响应数据
2.2.9 getStream
WiFiClient& getStream(void);
获取响应数据的流
2.2.10 getStreamPtr
WiFiClient* getStreamPtr(void);
获取响应数据的流
2.2.11 writeToStream
int writeToStream(Stream* stream);
获取响应数据的流,并写到其他流对象。Stream:流对象,返回写成功的字节数。
在讲解该函数之前,先简单介绍一下 分块编码(Transfer-Encoding: chunked):Transfer-Encoding,是一个 HTTP 头部字段(响应头域),字面意思是「传输编码」。最新的 HTTP 规范里,只定义了一种编码传输:分块编码(chunked)。
分块传输编码(Chunked transfer encoding)是超文本传输协议(HTTP)中的一种数据传输机制,允许HTTP由网页服务器发送给客户端的数据可以分成多个部分。分块传输编码只在HTTP协议1.1版本(HTTP/1.1)中提供。
数据分解成一系列数据块,并以一个或多个块发送,这样服务器可以发送数据而不需要预先知道发送内容的总大小。
具体方法
在头部加入 Transfer-Encoding: chunked 之后,就代表这个报文采用了分块编码。这时,报文中的实体需要改为用一系列分块来传输。
每个分块包含十六进制的长度值和数据,长度值独占一行,长度不包括它结尾的 CRLF(rn),也不包括分块数据结尾的 CRLF。
最后一个分块长度值必须为 0,对应的分块数据没有内容,表示实体结束。
2.2.12 getSize
int getSize(void);
获取响应数据字节数,返回响应数据字节数。
对于有 Content-Length,会把Content-Length赋值给size;
如果存在 Transfer-Encoding:chunked,size是通过计算响应内存长度来获得;
2.2.13 errorToString
static String errorToString(int error);
获取请求失败响应信息,根据错误码error返回具体错误信息,error 错误码
返回的是错误码对应的错误信息。