Arduino for ESP8266&ESP32适用库ESPAsyncWebServer:请求与响应

2023-10-27

目的

WebServer功能很多,最主要的一块就是解析来自用户的HTTP请求,然后根据功能需求将响应的消息发送给客户。这篇文章将粗略介绍ESPAsyncWebServer中HTTP通讯相关的请求和响应的处理。

本文中各例程演示均在ESP32中进行。

解析客户端请求

用户从浏览器输入网址或者通过其他程序等访问服务器的时候会向服务器发送消息,这就是HTTP请求,它的格式如下:
在这里插入图片描述
下面是个请求的示例:
在这里插入图片描述
请求即是用户希望服务器做的事,而服务器则解读该请求,然后进行响应,这里对ESPAsyncWebServer请求解析相关方法进行说明。

ESPAsyncWebServer中对于请求的调取实在回调函数中进行的,回调函数传入一个 AsyncWebServerRequest 对象,该对象就是用户的请求,我们可以通过该对象获取到很多信息,比如下面这些基础信息:

request->version();       // uint8_t: 0 = HTTP/1.0, 1 = HTTP/1.1
request->method();        // enum:    HTTP_GET, HTTP_POST, HTTP_DELETE, HTTP_PUT, HTTP_PATCH, HTTP_HEAD, HTTP_OPTIONS
// HTTP_GET = 0b00000001, HTTP_POST = 0b00000010, HTTP_DELETE = 0b00000100, HTTP_PU = 0b00001000, HTTP_PATCH = 0b00010000, HTTP_HEAD = 0b00100000, HTTP_OPTIONS = 0b01000000, HTTP_ANY = 0b01111111
request->url();           // String:  URL of the request (not including host, port or GET parameters)
request->host();          // String:  The requested host (can be used for virtual hosting)
request->contentType();   // String:  ContentType of the request (not avaiable in Handler::canHandle)
request->contentLength(); // size_t:  ContentLength of the request (not avaiable in Handler::canHandle)
request->multipart();     // bool:    True if the request has content type "multipart"

在这里插入图片描述
除了上面几个基础信息我们也可以通过遍历获取请求头中的所有信息:

int headers = request->headers();
int i;
for(i=0;i<headers;i++){
  AsyncWebHeader* h = request->getHeader(i);
  Serial.printf("HEADER[%s]: %s\n", h->name().c_str(), h->value().c_str());
  // 下面行功能同上面两行
  //Serial.printf("HEADER[%s]: %s\n", request->headerName(i).c_str(), request->header(i).c_str()); 
}

在这里插入图片描述
我们也可以通过指定头部字段名来获取对应的值:

if(request->hasHeader("MyHeader")){
  AsyncWebHeader* h = request->getHeader("MyHeader");
  Serial.printf("MyHeader: %s\n", h->value().c_str());
  // 下面行功能同上面两行
  // Serial.printf("MyHeader: %s\n", request->header("MyHeader").c_str());
}

除了上面内容外,请求中很多时候还会带入参数,比如GET方法中url中会有 ?key=value&key=value 这类字样的内容(问号后的就是参数,参数为键值对形式,不同参数间用&分隔),POST方法中参数通常放在请求数据中,参数可以用下面方式获取:

int params = request->params();
for(int i=0;i<params;i++){
  AsyncWebParameter* p = request->getParam(i);
  if(p->isFile()){ //p->isPost() is also true
    Serial.printf("FILE[%s]: %s, size: %u\n", p->name().c_str(), p->value().c_str(), p->size());
  } else if(p->isPost()){
    Serial.printf("POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
  } else { //GET
    Serial.printf("GET[%s]: %s\n", p->name().c_str(), p->value().c_str());
  }
}
// 下面语句功能同上面
//int args = request->args();
//for(int i=0;i<args;i++){
//  Serial.printf("ARG[%s]: %s\n", request->argName(i).c_str(), request->arg(i).c_str());
//}

在这里插入图片描述
我们也可以通过参数名来获取其对应的值:

if(request->hasParam("download")) //Check if GET parameter exists
  AsyncWebParameter* p = request->getParam("download");

if(request->hasParam("download", true)) //Check if POST (but not File) parameter exists
  AsyncWebParameter* p = request->getParam("download", true);

if(request->hasParam("download", true, true)) //Check if FILE was uploaded
  AsyncWebParameter* p = request->getParam("download", true, true);

// 下面语句功能同上面
//if(request->hasArg("download"))
//  String arg = request->arg("download");

上面出现了POST方法中主体数据中带有文件或其它数据的情况,这些数据可以通过专门的回调函数来处理,详细用法可以参考我ESPAsyncWebServer系列文章中对于事件处理绑定的介绍。

除了上面这些形式的参数外ESPAsyncWebServer库还提供了解析路径参数(Path variable)的方法,可以参考项目官方文档中 Setting up the server > Path variable 章结内容。

服务器进行响应

和请求一样响应也有一定的格式:
在这里插入图片描述
下面是个响应的示例:
在这里插入图片描述
响应简单来说就是根据上面的格式向客户端发送消息,最简单比如下面这样(ESPAsyncWebServer会严重遵循格式,未提供的内容会自动补足):

// 只发送状态码
request->send(404); //Sends 404 File Not Found

稍微增加点内容就变成下面这样:

// 发送状态码、报文主体数据类型、报文主题内容
request->send(200, "text/plain", "Hello World!");

我们也可以从文件系统向用户发送文件(发送文件并不推荐这么做,因为ESPAsyncWebServer库中提供了更好的方式,会在后面单独介绍):

request->send(SPIFFS, "/index.htm"); //Send index.htm with default content type

request->send(SPIFFS, "/index.htm", "text/plain"); //Send index.htm as text

request->send(SPIFFS, "/index.htm", String(), true); //Download index.htm

上面有的例子中我们向客户端发送了字符串,如果字符串比较长,那么在程序运行时会有不小的内存开销,这里可以用Arduino的特殊机制来处理:

// 下面用了PROGMEM修饰的字符串在用到时将直接从Flash读取,减轻对内存的开销
const char index_html[] PROGMEM = "..."; // large char array, tested with 14k
request->send_P(200, "text/html", index_html);

上面这些操作中没有在响应头中添加过内容,如果需要在响应头中添加内容可以使用AsyncWebServerResponse :

AsyncWebServerResponse *response = request->beginResponse(200, "text/plain", "Hello World!");
response->addHeader("Server","ESP Async Web Server");
request->send(response);

AsyncWebServerResponse通样支持PROGMEM:

const char index_html[] PROGMEM = "..."; // large char array, tested with 14k
AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", index_html);
response->addHeader("Server","ESP Async Web Server");
request->send(response);

直接使用 request->send() 可行的方式在用上AsyncWebServerResponse基本也都可行。除了这两类响应方式,还有别的方式可用,比如下面这个:

AsyncResponseStream *response = request->beginResponseStream("text/html");
// AsyncResponseStream支持print、printf等方式添加内容
response->print("Hello: ");
response->print(request->client()->remoteIP());
request->send(response);

在这里插入图片描述
上面的响应都是直接返回字符串或是文件,ESPAsyncWebServer中还提供了相对精细一些的返回方式——返回 json ,这也是非常常用的数据格式了,参考下面方式:

#include "AsyncJson.h"
#include "ArduinoJson.h"
//下面方式对4KB或以下内容支持较好
AsyncResponseStream *response = request->beginResponseStream("application/json");
DynamicJsonBuffer jsonBuffer;
JsonObject &root = jsonBuffer.createObject();
root["heap"] = ESP.getFreeHeap();
root["ssid"] = WiFi.SSID();
root.printTo(*response);
request->send(response);
#include "AsyncJson.h"
#include "ArduinoJson.h"
//下面方式对4KB以上内容支持较好,比如可以到40KB
AsyncJsonResponse * response = new AsyncJsonResponse();
response->addHeader("Server","ESP Async Web Server");
JsonObject& root = response->getRoot();
root["heap"] = ESP.getFreeHeap();
root["ssid"] = WiFi.SSID();
response->setLength();
request->send(response);

ESPAsyncWebServer中对于json的处理用到了ArduinoJson,需要另外安装,其安装使用说明可以参考下面文章:
《C++ Json库ArduinoJson介绍及使用说明》

URL重定向

除了直接进行响应外服务器也可以告诉客户端去访问别的链接,这就是url重定向:

request->redirect("/login"); //to local url

request->redirect("https://www.baidu.com/"); //to external url

在这里插入图片描述
url重定向支持过滤器功能,比如下面方式:

  String RedirectUrl = "http://";
  if (ON_STA_FILTER(request)) {
    RedirectUrl += WiFi.localIP().toString();
  } else {
    RedirectUrl += WiFi.softAPIP().toString();
  }
  RedirectUrl += "/index.htm";
  request->redirect(RedirectUrl);

总结

ESPAsyncWebServer请求与响应功能非常多,这是里只是挑选了一部分作为介绍,更多内容可以查看项目官方的文档和例程,或者我的其他ESPAsyncWebServer的文章:
ESPAsyncWebServer项目地址:https://github.com/me-no-dev/ESPAsyncWebServer
《Arduino for ESP8266&ESP32适用库ESPAsyncWebServer:快速入门》
《Arduino for ESP8266&ESP32适用库ESPAsyncWebServer:事件处理绑定》
《Arduino for ESP8266&ESP32适用库ESPAsyncWebServer:请求与响应》
《Arduino for ESP8266&ESP32适用库ESPAsyncWebServer:静态文件和模板引擎》
《Arduino for ESP8266&ESP32适用库ESPAsyncWebServer:WebSocket和EventSource》

HTTP请求和响应更多说明可以参考下面链接:
https://baijiahao.baidu.com/s?id=1662842929861521073

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Arduino for ESP8266&ESP32适用库ESPAsyncWebServer:请求与响应 的相关文章

  • arduino安装DHT11库

    步骤操作如下 打开Arduino IDE 在菜单栏中选择 项目 gt 加载库 gt 管理库 在库管理器的搜索框中 输入 DHT sensor library 找到 DHT sensor library by Adafruit 点击 安装 安
  • Arduino F()宏的实现

    我试图了解 Arduino 中的 F 宏实际上对 PGMEM 和 RAM 做了什么以及运行时的影响是什么 有人可以指出定义这个宏的文件吗 这可能是旧版本 但定义它的一个地方是Wstring h as in here http andybro
  • 如何使用 PHP 读取串口 [重复]

    这个问题在这里已经有答案了 如何使用 php 从连接到我的服务器 运行 kali linux 的旧笔记本电脑 上的 COM 端口的 arduino 读取串行数据 以便我可以在网页上显示数据 我读过有关同一问题的其他问题 所有这些问题要么超级
  • 2024年华数杯国际赛B题:光伏发电功率 思路模型代码解析

    2024年华数杯国际赛B题 光伏发电功率 Photovoltaic Power 一 问题描述 中国的电力构成包括传统能源发电 如煤 油和天然气 可再生能源发电 如水电 风能 太阳能和核能 以及其他形式的电力 这些发电模式在满足中国对电力的巨
  • 如何在Arduino上将int转换为字符串?

    如何转换 int n 到一个字符串 以便当我通过串行发送它时 它作为字符串发送 这是我到目前为止所拥有的 int ledPin 13 int testerPin 8 int n 1 char buf 10 void setup pinMod
  • Arduino Python3 脚本

    我正在尝试使用 Python3 脚本来控制 Arduino Mega 这是一个简单的脚本 用于从键盘获取一行并通过 Arduino 回显它 我从一个可用的 Python 2 脚本开始http petrimaki wordpress com
  • 蓝牙 HC-05 发送错误 1F 仅适用于 INQ 命令

    我的新蓝牙 HC 05 模块有问题 在 AT 模式下 它可以与我需要的所有命令完美配合 除了 INQ 我已经尝试事先发送一大堆其他命令 AT INIT OK AT ORGL OK AT ROLE 1 OK AT CLASS 0 OK 他们都
  • Arduino:使用串口和软件串口与蓝牙模块

    我的目的是使用 Arduino 通过 HC 05 蓝牙模块在 PC 和 Android 设备之间建立通信 我使用 PC 和 Arduino 串行监视器 之间的 USB 通信以及 SoftwareSerial 来连接到 HC 05 我的问题是
  • 如何将值从 Arduino 发送到 Python,然后使用该值

    我正在构建一个使用 Python 进行远程控制的机器人 通过简单的 GUI 通过互联网发送控制消息 我的部分代码 GUI 和控制系统 运行得很好 但我陷入了困境 我正在尝试使用视差平传感器来获取与物体的距离信息Arduino Mega ht
  • 如何将 ASCII char 转换为其 ASCII int 值?

    我想将 char 转换为它的ASCII http en wikipedia org wiki ASCIIint 值 我可以用所有可能的值填充一个数组并与其进行比较 但这对我来说似乎不正确 我想要类似的东西 char mychar k pub
  • 同时使用 GPRS 和 GSM

    我正在尝试使用 GSM GPRS 调制解调器的 GPRS 功能将数据发送到远程服务器 但我无法这样做 我在 Arduino 论坛上发布了一个问题 但没有得到任何回复 这是问题的链接 https robotics stackexchange
  • ESP32 上的 Web 服务器:如何自动更新和显示来自服务器的传感器值?

    我在 ESP32 上有一个网络服务器 在该服务器上有一个主页 我想每隔 x 秒自动更新主页上的传感器值 无需用户输入 我无法访问文件系统 该传感器直接连接到 ESP32 传感器值位于我的 C 程序中 存储在变量中并定期更新 变量是全局的 以
  • 在Python中快速绘制数据

    我正在尝试使用 arduino 绘制来自 mpu6050 imu 的数据 MPU6050 发送数据的速度比绘图快 Arduino 代码从串口提供 6 个数据 即偏航 俯仰 滚动 轴 ay 和 az 我需要快速情节的建议 Python代码 i
  • 终止导致设备或资源繁忙的进程:“/dev/ttyUSB0”?

    我使用以下 Python 代码连接到我的 Arduino 板 device glob glob dev ttyUSB 0 time sleep 1 arduino serial Serial device 115200 timeout 5
  • Arduino - 高效地迭代 C 数组

    我有以下数组 PROGMEM prog uint16 t show hide info 4216 8900 4380 580 500 600 500 580 1620 580 500 600 500 580 500 600 480 600
  • AVRDUDE Android Arduino ioctl 错误

    我之前的问题 Android 无法使用 AVRDUDE 与 Arduino 通信 https stackoverflow com questions 15596376 android cannot talk to arduino using
  • 是否可以在 Arduino 上运行 ZeroMQ

    我想知道是否可以通过 ZeroMQ 与 Arduino 进行通信 我想使用 Arduino 来控制一些设备 并希望将大部分应用程序放在计算机上 为此 如果 Arduino 和控制器可以通过 Zeromq 以及 WiFi 或以太网扩展板进行通
  • 在链接时合并全局数组/从多个编译单元填充全局数组

    我想定义一系列的东西 比如事件处理程序 的内容 该数组在编译时是完全已知的 但定义在 多个编译单元 分布在多个库中 至少在最终 静态 链接之前是相当解耦的 我想要 也保持这种方式 因此添加或删除编译单元将 还可以自动管理事件处理程序 而无需
  • 使用 Arduino 来操作 Android [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 有人尝试过让 Android 和 Arduino 相互通信吗 我在网上找到了几个项目 Amarino http www amarino tool
  • ESP32:dsb1820 温度传感器给出恒定的负 127 读数

    我正在尝试使用连接到 esp32 微控制器的单个 dsb1820 温度传感器来获取温度读数 传感器连接到 esp32 的 GPIO 4 我打算将温度读数发送到云端 我面临的问题是温度读数总是给出值 127 我在网上某处读到 当 dsb182

随机推荐

  • 《数值分析》-- 高斯求积公式

    文章目录 概述 一 高斯型求积公式的一般理论 1 1 高斯型求积公式和高斯点 1 2 高斯点的特征 二 常用的高斯求积公式 2 1 高斯 勒让德求积公式 Gauss Legendre 2 2 高斯 切比雪夫求积公式 Gauss Chebys
  • 让生产力加倍的ChatGPT快捷指令

    我的新书 Android App开发入门与实战 已于2020年8月由人民邮电出版社出版 欢迎购买 点击进入详情 Why use ChatGPT Shortcut 简化流程 ChatGPT Shortcut 提供了快捷指令表 可以快速筛选和搜
  • OpenGL视频资料(LearnOpenGL中文)经典教材讲解

    OpenGL视频资料 LearnOpenGL中文 经典教材讲解 1 是中文 台湾的傅老师 讲的非常好 而且还是免费的 感谢傅老师的分享 视频地址 2 视频目录 讲解的非常仔细 可以说是手把手教 而且是openGL经典入门教材LearnOpe
  • [Python] Python基础入门笔记

    本篇是B站Python基础视频 有C Java编程基础容易理解 120分钟入门Python的学习笔记 Python基础笔记 一 Python 简介 1 Python执行过程 2 执行模式 二 语法规则 三 函数 1 内置函数 range 2
  • java基础练习—逢七游戏、不死神兔、百钱百鸡、利滚利

    1 逢七游戏 逢七过 规则是 从任意一个数字开始报数 当你要报的数字包含7或者是7 的倍数时都要说 过 为了帮助大家更好的玩这个游戏 这里我们直接在控制台打印出1 100之间的满足逢七必过 规则的数据 package com bdit pu
  • ThinkCentre进入BIOS,设置intel virtualization technology

    VMware安装提示cpu虚拟化intel virtualization technology ThinkCentre重启长按F1 按enter 开启intel virtualization technology F10保存即可 转载于 h
  • git团队开发使用流程概述和注意点

    重新温习了一下git 这篇文章主要总结一下使用git做开发的整体流程 所以不会做过多的git指令的详细说明 整体流程 这里我在本地进行模拟 我希望模拟达到的效果是 一共有4个端 project是一个仓库 manager是项目负责人 zs和l
  • 【面试】Java 必知必会

    必知必会 1 面向对象可以解释下么 都有哪些特性 关于封装 关于继承 重写 Override 关于多态 重载 如果只有方法返回值不同 可以构成重载吗 在 Java 中 什么时候使用重载 什么时候使用重写 子类对象作为父类对象使用 向上转型
  • 【Antlr】识别常见的词法结构

    1 概述 语法分析器通过输入的词法符号流来识别特定的语言结构 词法分析器通过输入的字符流来识别特定的语言结构 词法规则以大写字母开头 文法规则以小写字母开头 例如 ID是一个词法规则名 而expr是一 个文法规则名 2 配置标识符 在语法的
  • 数据结构—顺序表的初始化与销毁(C语言详细解读版1/3)

    顺序表 顺序表 SqList Sequence List 即顺序线性表 顺序表是在计算机内存中以数组的形式保存的线性表 是指用一组地址连续的存储单元依次存储数据元素的线性结构 使得线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中
  • 自动售卖系统开发系列——人脸识别自动售卖机三代BrotherSharp

    大纲 售卖机三代BrotherSharp的简介 售卖机三代BrotherSharp的方案介绍 系统整体组成 软件平台 硬件平台 售卖机三代BrotherSharp的实现过程 功能实现论述 软件流程图 源码 售卖机三代BrotherSharp
  • ArcGIS Desktop 遇到严重的应用程序错误

    由于项目初验 忙了几个月 感觉忙得并不值 好久都没更新博客了 一 问题 在关闭ArcMap时 ArcGIS Desktop 遇到严重的应用程序错误 环境是Windows 10 新装的系统 以前出现这种问题 一般有两种情况 一是ArcGIS
  • Pycharm调试debug指导

    PyCharm的调试有两种显示模式 Debugger和Console Debugger处以列表形式 列出每个元素的内容 Console处与直接Run输出类似 Debugger模式 Step Over Step Into 区别 调试方式 快捷
  • FutureTask详解

    前些天发现了一个巨牛的人工智能学习网站 通俗易懂 风趣幽默 忍不住分享一下给大家 点击跳转到网站 FutureTask介绍 一个可取消的异步计算 FutureTask提供了对Future的基本实现 可以调用方法去开始和取消一个计算 可以查询
  • Line-in和Mic-in的区别和使用及Line-out

    Line in和Mic in的区别 http blog 163 com why ann 2001 blog static 331376200821391621467 我们的电脑声卡上 一般都会有Line in和Mic in两个接口 翻译成中
  • 【SAML2.0】概念盲扫

    目录 一 SAML是什么 二 SAML 1 SAML的构成 2 SAML的流程分析 3 SAML的优点 简介 安全断言标记语言 英语 Security
  • final的分析

    源自 http www cnblogs com dolphin0520 p 3736238 html 1 修饰类 当用final修饰一个类时 表明这个类不能被继承 2 修饰方法 使用final方法的原因有两个 第一个原因是把方法锁定 以防任
  • 寻找第k大元素,时间复杂度是多少?

    寻找第k大元素可以通过多种算法实现 其中时间复杂度最优的是基于快速排序的算法 称为快速选择 QuickSelect 算法 快速选择算法的基本思想是选择一个基准元素 然后将数组划分为比基准元素小和比基准元素大的两个子数组 如果第k大元素在比基
  • 关于图像的傅里叶变换的理解

    最近再学opencv关于图像的傅里叶变换的知识 自己感觉很难理解 查阅相关书籍和博客发现很多写的都比较含糊 下面是转载自知乎一个博主关于图像的傅里叶变换的通俗解释 通俗讲解 图像傅里叶变换 文末加了一点冈萨雷斯 数字图像处理 中的关于频谱中
  • Arduino for ESP8266&ESP32适用库ESPAsyncWebServer:请求与响应

    文章目录 目的 解析客户端请求 服务器进行响应 URL重定向 总结 目的 WebServer功能很多 最主要的一块就是解析来自用户的HTTP请求 然后根据功能需求将响应的消息发送给客户 这篇文章将粗略介绍ESPAsyncWebServer中