The objective of this ESP32 Arduino Tutorial is to explain how to serve HTML content from an asynchronous HTTP webserver running on the Arduino core, on the ESP32. The tests of this ESP32 tutorial were performed using a DFRobot’s ESP-WROOM-32 device integrated in a ESP32 development board.
Introduction
The objective of this ESP32 Arduino Tutorial is to explain how to serve HTML content from an asynchronous HTTP webserver running on the Arduino core, on the ESP32.
For a getting started tutorial which contains the installation instructions for the libraries needed to run the HTTPs server, please consult this previous post.
For this tutorial we will be serving a simple line of text enclosed in a HTML tag. Thus, we will need to tell our client that the content we are serving is of type HTML, so it knows how to interpret it. As a client, we will use a web browser.
The tests of this ESP32 tutorial were performed using a DFRobot’s ESP-WROOM-32 device integrated in a ESP32 FireBeetle board.
The code
First of all, we will need to include some libraries. We will need the WiFi.h for connecting the ESP32 to a Wireless Network and the ESPAsyncWebServer.h for accessing the class that exposes to us the methods needed to set the HTTP server.
Additionally, we will need the AsyncTCP.h, which is used under the hood for handling the server clients. We will also need the FS.h, which is needed for the code to compile, although we are not going to use any of the file system functionalities available on the HTTP server.
Since we are going to connect to a WiFi network, we will declare the credentials needed in two global variables, so we can easily change them. We will need both the network name (SSID) and the password.
We will also need an instance of the AsyncWebServer class, which we will use to set the webserver. Note that the constructor of this class receives as input the port where the server will be listening. We will be using port 80, which is the default HTTP port.
#include <WiFi.h>
#include <FS.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
const char* ssid = "yourNetworkName";
const char* password = "yourNetworkPassword";
AsyncWebServer server(80);
Moving on to the setup function, we will start by opening a serial connection and then connecting the ESP32 to the WiFi network to which the credentials were previously provided in global variables. You can check here a detailed tutorial on how to connect the ESP32 to a WiFi network.
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
Serial.println(WiFi.localIP());
Note that after the connection finishes, we are printing the local IP of the ESP32 on the network, since we are going to need it to connect to the server using a web browser.
Now that we have the ESP32 connected to a network and our server object instantiated, we will define a route where it will be listening for incoming HTTP requests. This route will be associated with a handling function that will be executed whenever a request to that route is performed by a client.
So, to bind a route to a handling function, we simply call the on method on our server object.
As first input, it receives a string with the route where the server should be listening. We are going to use the “/html” route.
As second input, it receives an enum of type WebRequestMethod, which indicates the HTTP methods allowed on that route. We will limit the requests to GET, so we should use the HTTP_GET value.
As third argument, the on method receives the handling function that will be executed when requests are received. The signature of this function is fixed and it needs to return void and receive as input a pointer to an object of type AsyncWebServerRequest.
For keeping the code compact and due to the simplicity of the handling function we are going to need, we will declare it as a C++ lambda function.
server.on("/html", HTTP_GET, [](AsyncWebServerRequest *request){
// Handling function code
});
Inside our lambda function we can use the object of class AsyncWebServerRequest to specify the answer to send back to the HTTP client. We do this using the send method, which receives as first input the HTTP response code, as second argument the response content-type and as third the actual content.
We will return a HTTP OK code, which corresponds to 200. Since we are going to return HTML, we define the content-type as “text/html“. Finally, we specify our HTML content as a string.
server.on("/html", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, "text/html", "<p>This is HTML!</p>");
});
To finalize the setup function, we need to call the begin method on our server object, so it starts listening and handling clients. Since the library we are using implements an asynchronous solution for the webserver, we don’t need to periodically call any client handling function on the main loop, and thus we can leave it empty.
The final source code can be seen below.
#include <WiFi.h>
#include <FS.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
const char* ssid = "yourNetworkName";
const char* password = "yourNetworkPassword";
AsyncWebServer server(80);
void setup(){
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
Serial.println(WiFi.localIP());
server.on("/html", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, "text/html", "<p>This is HTML!</p>");
});
server.begin();
}
void loop(){
}
Testing the code
To test the code, simply compile it and upload it to your ESP32 board using the Arduino IDE. Then, open the serial monitor and copy the IP that gets printed once the connection to the WiFi network finishes.
Then, open a web browser and write the following on the address bar, changing {yourEspIp} by the IP that was printed on the serial console.
http://{yourEspIp}/html
You should get an output similar to figure 1, which shows the HTML content being returned. Note that the HTML is indeed being interpreted as such by the browser, since the tags are not getting printed, since they are part of the markup and not of the content.
Figure 1 – HTML returned to the browser is rendered.