ESP32 访问 HTTP 服务(GET / POST 基础)

「C++ 40 周年」主题征文大赛(有机会与C++之父现场交流!) 10w+人浏览 457人参与

前提:你已经会让 ESP32 连上 WiFi(第一章内容:WiFi.begin()WiFi.localIP() 那套)。

这一章只回答一个问题:

“ESP32 联上网之后,怎么去访问一个网址 / 接口,拿回数据?”


2.1 先搞清楚 HTTP 在这件事里的角色

简单画一下关系:

  • ESP32:HTTP 客户端(client)

  • 服务器:HTTP 服务端(server),可能是:

    • 一个网站(http://example.com)

    • 一个 REST API(http://api.xxx.com/data)

ESP32 做的事就是:

  1. 跟服务器建立 TCP 连接(通常端口 80 / 443)

  2. 按 HTTP 规范发一段文本请求(GET / POST)

  3. 收到服务器返回的一段文本响应(状态码 + 头部 + 内容)

  4. 把你关心的那一部分(比如 JSON 字符串)取出来处理

HTTP 常用两种方法:

  • GET:向服务器“要数据”,例如查询天气、获取配置

  • POST:向服务器“发数据”,例如上报传感器值、发送 JSON


2.2 在 Arduino-ESP32 里,常用的两个类:WiFiClientHTTPClient

你可以这样理解这两个角色:

  1. WiFiClient

    • 类似“TCP 原始连接

    • 你可以用它直接连到某个 IP:port,然后手写 HTTP 报文:

      GET /path HTTP/1.1 Host: example.com

    • 灵活,但费脑子

  2. HTTPClient(我们本章重点)

    • 是封装在上面的高级接口

    • 帮你把 HTTP 报文构造、解析都做好了

    • 你只需要:

      • 填 URL

      • GET()POST()

      • 看返回值、取响应体

入门和一般项目,直接用 HTTPClient 就够用 + 好用

使用前需要引头文件:


#include <WiFi.h> #include <HTTPClient.h>


2.3 用 HTTPClient 发一个最基础的 GET 请求

步骤拆解(知识点版)

  1. 确认 WiFi 已连接(非常重要)

    • 只有 WiFi.status() == WL_CONNECTED 才去请求

  2. 创建 HTTPClient 对象

  3. http.begin(url):设置要访问的 URL

  4. http.GET():真正发起 GET 请求

  5. 检查返回码:大于 0 表示请求发出并有响应,HTTP 状态码 200 表示成功

  6. http.getString() 拿响应体内容

  7. http.end():关闭连接,释放资源

模板函数(你以后可以直接拷贝改)

这个函数的作用是:

给定一个 URL,发 GET 请求,把响应内容打印出来,并返回是否成功。

#include <WiFi.h>
#include <HTTPClient.h>

// 假设此时 WiFi 已经连上(第一章的流程已经做完)

bool httpGetOnce(const char* url) {
  // 1. 先确认 WiFi 是连着的
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("[HTTP] WiFi not connected!");
    return false;
  }

  HTTPClient http;  // 2. 创建 HTTP 客户端对象

  Serial.print("[HTTP] begin: ");
  Serial.println(url);

  // 3. 指定请求的 URL
  http.begin(url);  // 对于 http://... 这样明文的 URL,这样写就够了

  // 4. 发起 GET 请求
  int httpCode = http.GET();

  // 5. 判断是否请求成功(有没有收到有效的 HTTP 响应)
  if (httpCode > 0) {
    Serial.printf("[HTTP] GET... code: %d\n", httpCode);

    if (httpCode == HTTP_CODE_OK) {  // 200
      // 6. 读取响应体内容(整个 body 作为一个 String)
      String payload = http.getString();
      Serial.println("[HTTP] Response payload:");
      Serial.println(payload);
    } else {
      Serial.println("[HTTP] Server returned non-200 code");
    }
  } else {
    // httpCode <= 0 说明连不上 / 超时 / DNS 失败等
    Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
    http.end();  // 别忘了结束
    return false;
  }

  // 7. 关闭连接,释放资源
  http.end();
  return true;
}

你可以在 loop() 或某个任务里这样用:

void loop() {
  static unsigned long lastReq = 0;
  unsigned long now = millis();

  if (now - lastReq > 10000) {  // 每 10 秒请求一次
    lastReq = now;
    httpGetOnce("http://example.com/");
  }
}

这一套就是“GET 模块”,你现在先记住步骤和调用方式。


2.4 用 HTTPClient 发一个基础的 POST 请求

POST 请求常见用途:

  • 向服务器上传传感器数据(JSON / 表单)

  • 提交一些设置 / 控制指令

POST 的关键知识点:

HTTPClient 里,POST 的流程和 GET 很像,只是:

  1. 需要先设置一个 请求头(常见的是 Content-Type)

  2. http.POST(数据字符串)

  3. 一样检查返回码,按需读取响应体

常见两种 Content-Type:

  • application/x-www-form-urlencoded:表单格式,例如 key1=value1&key2=value2

  • application/json:JSON,例如 {"temp":25.3,"hum":60}

模板函数:POST JSON

bool httpPostJson(const char* url, const String& jsonBody) {
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("[HTTP-POST] WiFi not connected!");
    return false;
  }

  HTTPClient http;

  Serial.print("[HTTP-POST] begin: ");
  Serial.println(url);

  http.begin(url);

  // 1. 告诉服务器:我发的是 JSON
  http.addHeader("Content-Type", "application/json");

  // 2. 发出 POST 请求,参数是要发送的 body
  int httpCode = http.POST(jsonBody);

  if (httpCode > 0) {
    Serial.printf("[HTTP-POST] code: %d\n", httpCode);

    if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_CREATED) {
      String resp = http.getString();
      Serial.println("[HTTP-POST] Response:");
      Serial.println(resp);
    }
  } else {
    Serial.printf("[HTTP-POST] failed, error: %s\n",
                  http.errorToString(httpCode).c_str());
    http.end();
    return false;
  }

  http.end();
  return true;
}

使用示例(知识点):

String body = "{\"temp\":25.3,\"hum\":60.1}";
httpPostJson("http://your-server.com/api/upload", body);

以后你要对接 OneNet / 自己写的后端 / WebHook,大概率就是这个模式。


2.5 HTTP 状态码,你至少要认识几个

当你 GET()POST() 后:

  • 如果返回 httpCode > 0:说明有收到服务器的 HTTP 响应

  • 这个值就是 HTTP 状态码(不是 TCP 级别错误)

常见的:

  • 200 OK:成功

  • 201 Created:创建成功(常见于 POST 新建资源)

  • 301/302:重定向(需要再访问别的 URL)

  • 400:请求参数有问题

  • 401 / 403:未授权 / 禁止访问

  • 404:路径错了(服务器不存在这个接口)

  • 500:服务器内部错误

如果 httpCode <= 0

说明是 连不上 / 超时 / DNS 等错误HTTPClient 内部会用负数编码。
你可以用:

http.errorToString(httpCode)

把错误码翻译成可读字符串(比如 connection refusedtimed out 等)。


2.6 常见坑点(理论上知道就行)

  1. 必须先连 WiFi

    • WiFi.status() != WL_CONNECTED 时去 GET/POST,大概率失败

    • 所以一开始都加一层判断,失败就直接返回,不要乱请求

  2. 频率别太高

    • HTTP 是基于 TCP 的,每次 GET() / POST() 都可能建立/断开连接

    • 你要是每 100ms 请求一次,很容易把服务器 / 自己搞崩

    • 一般建议:秒级别甚至更久,比如 1s / 5s / 10s 以上

  3. HTTPS(https://)会多一层“证书问题”

    • HTTP(80 端口)简单,直接能用

    • HTTPS(443 端口)涉及 TLS 证书校验,严格写要配证书或设为不校验

    • 入门阶段可以先用 http:// 的接口练手,后面再说 HTTPS 细节


这一章你需要“掌握到什么程度”?

对你现在这个阶段,第二章的“达标标准”可以是:

  • 能说出:

    • WiFiClient 是底层 TCP

    • HTTPClient 是高级 HTTP 封装

  • 知道 GET 和 POST 的用法区别

  • 会看懂这两套模板函数的大致逻辑:

    • http.begin(url)http.GET() / http.POST() → 检查 httpCode → http.getString()http.end()

  • 以后要访问某个 HTTP 接口时,知道把 URL、参数填在哪个地方改。

<think> 我们正在处理一个关于ESP32作为HTTP服务器时如何区分GETPOST请求的问题。根据提供的引用内容,虽然引用主要关注的是ESP32作为客户端发起HTTP请求,但我们可以从中提取关于HTTP方法处理的相关知识,并结合ESP32HTTP服务器功能来回答。 关键点: 1. ESP32可以作为HTTP服务器,接收来自客户端的请求(如GETPOST等)。 2. 在服务器端,我们需要解析传入的HTTP请求,以确定请求方法(GETPOST等)并相应地处理。 根据引用[2]和[4],我们了解到GETPOST请求的主要区别在于数据传递的位置: - GET请求:通常将数据附加在URL的查询字符串(QueryString)中。 - POST请求:通常将数据放在请求体(Body)中。 在ESP32作为服务器时,我们需要解析请求行(包含请求方法)和请求头,对于POST请求还需要读取请求体。 由于引用中没有直接给出ESP32作为服务器区分GETPOST的代码,我们可以根据常见的ESP32 HTTP服务器实现方法(如使用ESP-IDF中的httpd组件)来回答。 步骤: 1. 使用ESP-IDF的httpd组件创建HTTP服务器。 2. 注册URI处理函数时,可以指定处理的HTTP方法(如HTTP_GET, HTTP_POST等)。 3. 在处理函数中,通过检查请求对象(httpd_req_t)的method字段来确定请求方法。 下面是一个示例代码框架: ```c #include <esp_http_server.h> // GET请求处理函数 esp_err_t get_handler(httpd_req_t *req) { // 处理GET请求 httpd_resp_send(req, "这是GET请求", HTTPD_RESP_USE_STRLEN); return ESP_OK; } // POST请求处理函数 esp_err_t post_handler(httpd_req_t *req) { // 首先,我们需要读取请求体(如果有的话) char content[100]; int ret = httpd_req_recv(req, content, sizeof(content)); if (ret <= 0) { // 处理错误或连接关闭 return ESP_FAIL; } // 处理POST数据 // ... httpd_resp_send(req, "这是POST请求", HTTPD_RESP_USE_STRLEN); return ESP_OK; } // 注册URI处理函数 void start_webserver() { httpd_handle_t server = NULL; httpd_config_t config = HTTPD_DEFAULT_CONFIG(); // 启动HTTP服务器 if (httpd_start(&server, &config) == ESP_OK) { // 注册GET处理函数 httpd_uri_t get_uri = { .uri = "/example", .method = HTTP_GET, .handler = get_handler, .user_ctx = NULL }; httpd_register_uri_handler(server, &get_uri); // 注册POST处理函数 httpd_uri_t post_uri = { .uri = "/example", .method = HTTP_POST, .handler = post_handler, .user_ctx = NULL }; httpd_register_uri_handler(server, &post_uri); } } ``` 在这个示例中: - 我们为同一个URI `/example` 注册了两个不同的处理函数,分别处理GETPOST请求。 - 当收到GET请求时,调用`get_handler`;当收到POST请求时,调用`post_handler`。 - 在POST处理函数中,我们使用`httpd_req_recv`来读取请求体数据。 注意:在实际应用中,我们需要根据请求头中的Content-Length来读取完整的请求体,并处理可能的分块传输等。 另外,引用[5]中提到了HTTP事件回调,但那是针对客户端的情况。在服务器端,我们使用注册的处理函数来区分不同的请求方法。 总结:ESP32作为HTTP服务器时,可以通过为同一个URI注册不同的处理函数(每个处理函数指定不同的HTTP方法)来区分GETPOST请求。在处理函数中,我们可以进一步处理请求参数(GET请求从查询字符串中获取,POST请求从请求体中获取)。 §§相关问题§§ 1. ESP32 HTTP服务器如何处理PUT和DELETE请求? 2. 在ESP32 HTTP服务器中如何获取GET请求的查询参数? 3. 在ESP32 HTTP服务器中如何解析POST请求的JSON数据? </think> ### ESP32作为HTTP服务器区分GETPOST请求的方法 在ESP32作为HTTP服务器时,可以通过以下两种主要方式区分GETPOST请求: #### 方法1:注册独立处理函数(推荐) 在ESP-IDF的`httpd`组件中,可以为同一个URI路径注册不同的处理函数,通过`method`字段指定HTTP方法类型: ```c // GET请求处理函数 esp_err_t get_handler(httpd_req_t *req) { httpd_resp_send(req, "处理GET请求", HTTPD_RESP_USE_STRLEN); return ESP_OK; } // POST请求处理函数 esp_err_t post_handler(httpd_req_t *req) { // 接收POST数据 char buffer[100]; httpd_req_recv(req, buffer, sizeof(buffer)); httpd_resp_send(req, "处理POST请求", HTTPD_RESP_USE_STRLEN); return ESP_OK; } // 注册路由 httpd_uri_t get_uri = { .uri = "/api", .method = HTTP_GET, // 指定GET方法 .handler = get_handler }; httpd_uri_t post_uri = { .uri = "/api", .method = HTTP_POST, // 指定POST方法 .handler = post_handler }; httpd_register_uri_handler(server, &get_uri); httpd_register_uri_handler(server, &post_uri); ``` #### 方法2:在统一处理函数中判断 在单个处理函数内检查请求方法类型: ```c esp_err_t api_handler(httpd_req_t *req) { switch(req->method) { // 判断请求方法 case HTTP_GET: // 处理GET逻辑 break; case HTTP_POST: // 读取POST数据 char content[100]; httpd_req_recv(req, content, sizeof(content)); // 处理POST逻辑 break; default: return ESP_FAIL; } return ESP_OK; } ``` #### 关键区别说明 1. **GET请求**: - 数据通过URL的查询字符串传递(如`/path?key=value`) - 使用`httpd_query_key_value()`获取参数 - 适合数据量小的请求[^2] 2. **POST请求**: - 数据通过请求体(Body)传输 - 必须使用`httpd_req_recv()`读取数据 - 适合表单提交或JSON数据传输[^4] - 需要检查`Content-Length`头部确定数据长度 > 提示:对于RESTful API,还可扩展支持`PUT`/`DELETE`等方法,原理相同[^1][^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

热爱嵌入式的乌鸦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值