Second entry dedicated to the ESP8266 and ESP32 as a server. This time we are going to delve into the treatment of different types of requests, and obtaining parameters.
We will refer to the ESP8266, but the same code is compatible for the ESP32, adjusting the name of the libraries. At the end you have the code for both the ESP8266 and the ESP32.
In the previous entry we saw how to set up a server with the ESP8266, anticipating that it would take up a few entries. Previously we had seen how to use the ESP8266 as a client.
When we saw the web server in the previous entry, we only used methods (request) of type GET. And there it would stay for many internet tutorials. But we like to go a little deeper, don’t we?
For this we are going to see the different types of requests and their parameters. As we saw, an HTTP request can be of different types (GET, POST, PATH, DELETE…).
Long ago, when the internet “was young”, there was a lot of confusion about what the different types of functions were for. But in this REST API and M2M interface era, the reason for the existence of different types of requests should be very clear. Typically each type corresponds to ‘actions’ that you want to perform on the server.
So it is logical that the HTTP request that tells you if a LED is on should be of type GET. But the one that turns it on and off should use a PATCH (at most, a POST could be used).
In order to understand the requests and what action they want us to take, it is not enough to route a URI to a callback action, but we must also be able to launch different actions depending on the type of request we receive.
Similarly, we have parameters. Remember that in an HTTP request we can send parameters, either in the URL (in GET requests) or encoded in some of the various ways in the body of the request.
Differentiate request type
To differentiate the type of request, the ESP8266WebServer library has the method ‘on(…)’, which allows indicating the method we need
void on(const String &uri, HTTPMethod method, THandlerFunction fn);
Where,
- URI, resource address.
- method, the method we want to associate (HTTP_ANY, HTTP_GET, HTTP_POST, HTTP_PUT, HTTP_PATCH, HTTP_DELETE, HTTP_OPTIONS)
- fn, the callback function to execute.
Get parameters
On the other hand, to obtain the parameters, the ESP8266WebServer library has the following methods.
const String& arg(String name) const; // get request argument value by name
const String& arg(int i) const; // get request argument value by number
const String& argName(int i) const; // get request argument name by number
int args() const; // get arguments count
bool hasArg(const String& name) const; // check if argument exists
Let’s see an example
As always, it is best to see it in a simple example. Suppose we have an ESP8266 with a series of LEDs, which we identify by their ID. On the one hand, we want to be able to check the status of each LED, and also want to be able to turn the LED on or off.
First, let’s see how NOT to do it. What is not done is to use a GET request to both turn on and off the LED, nor do “weird things” with the String class to create a request to a URI in the following form.
/led?Id=10&Status=ON
No, that is not done. The correct thing to do is to make two routings. One of type GET to the URI ‘/led’ that receives the ID of the LED we want to check, and one of type POST that receives the ID of the LED, and its new status.
This, we could do it in the following way, where we simply create two routings and associate a function that, in this example, simply shows the received parameters.
The main program has not changed from the previous entry, which we should remember was,
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
ESP8266WebServer server(80);
#include "config.h" // Replace with your network data
#include "ESP8266_Utils.hpp"
#include "Server.hpp"
void setup(void)
{
Serial.begin(115200);
ConnectWiFi_STA();
InitServer();
}
void loop()
{
server.handleClient();
}
We modify the ‘Server.hpp’ file that we created in the previous entry with the following content
// Function when receiving a GET request
void getLED()
{
// return response
server.send(200, "text/plain", String("GET ") + server.arg(String("Id")));
}
// Function when receiving a POST request
void setLED()
{
// show on serial port
Serial.println(server.argName(0));
// return response
server.send(200, "text/plain", String("POST ") + server.arg(String("Id")) + " " + server.arg(String("Status")));
}
// Function to be executed in the URI '/'
void handleRoot()
{
server.send(200, "text/plain", "Hello world!");
}
void handleNotFound()
{
server.send(404, "text/plain", "Not found");
}
void InitServer()
{
// Routing for '/'
server.on("/", handleRoot);
// We define two routings
server.on("/led", HTTP_GET, getLED);
server.on("/led", HTTP_POST, setLED);
server.onNotFound(handleNotFound);
server.begin();
Serial.println("HTTP server started");
}
Result
Now, if we use Postman to send requests to the ESP8266 and check that we are correctly reading the type and parameter of the request.
For the GET request we would do,
And for the POST request we would have,
In this example, we would also see the request in the serial port. In a real case, we would take the appropriate actions (in this case, probably turn the LED on or off).
That’s all for today. We have learned to read the type and parameters of an HTTP request from an ESP8266 when it acts as a server. Although for now, we only return simple responses.
In the next entry we will expand our server, starting to serve more complex content, typically a web page. See you soon!
Download the code
All the code for this post is available for download on Github.
Version for ESP8266: https://github.com/luisllamasbinaburo/ESP8266-Examples
Version for ESP32: https://github.com/luisllamasbinaburo/ESP32-Examples