ESP32 Arduino HTTP server: Serving a favicon

In this tutorial we will check how to serve a favicon, using the ESP32 and the Arduino core. We will use the async web server libraries in order to setup the server and we will use the SPIFFS file system to store the favicon and serve it from the ESP32. The tests were performed using a DFRobot’s ESP32 module integrated in a ESP32 development board.

Introduction

In this tutorial we will check how to serve a favicon, using the ESP32 and the Arduino core. We will use the async web server libraries in order to setup the server and we will use the SPIFFS file system to store the favicon and serve it from the ESP32.

A favicon is the small website icon that typically appears on the tabs of web browsers. So, when accessing a website, the browser will do a HTTP request to try to obtain a resource called favicon.ico, on the root path. It will be a GET request that will be performed to the “/favicon.ico” endpoint.

In my case, I will be serving the testing icon shown in figure 1.

Testing favicon

Figure 1 – Testing favicon.

To have the file available to be served, we will be using this Arduino IDE plugin, which allows us to upload files to the SPIFFS file system. You can check in detail on this previous post the procedure to upload files.

In short, we simply need to create a folder called “data” in the folder of the Arduino sketch where we will write the code. Then, we simply place the file to upload in the “data” folder and, under the Arduino IDE Tools menu, click the “ESP32 Sketch Data Upload” option.

Since the file I’m uploading is called “favicon.png“, it will be available in the SPIFFS file system in the following path: “/favicon.png“.

The tests were performed using a DFRobot’s ESP32 module integrated in a ESP32 development board.

The code

We will start our code by importing the libraries needed. We will need the following three libraries:

  • WiFi.h: To connect the ESP32 to a WiFi network;
  • ESPAsyncWebServer.h: To setup the async HTTP web server on the ESP32;
  • SPIFFS.h: For the file system related functionalities.
#include "WiFi.h"
#include "ESPAsyncWebServer.h"
#include "SPIFFS.h"

We will also need to declare the credentials of the WiFi network, in order for the ESP32 to be able to connect to it.

const char* ssid = "yourNetworkName";
const char* password = "yourNetworkPass";

To finalize the global variables declaration, we will need an object of class AsyncWebServer, which we will later use to configure the routes of our server.

AsyncWebServer server(80);

Moving on to the Arduino setup, we will first open a serial connection, so we can output some messages from our program.

After that, we will initialize the SPIFFS file system, so we are able to later interact with it to serve the favicon file to the clients requesting it.

We will also connect the ESP32 to the WiFi network, using the previously declared WiFi credentials.

Serial.begin(115200);

if(!SPIFFS.begin()){
     Serial.println("An Error has occurred while mounting SPIFFS");
     return;
}

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
}

Serial.println(WiFi.localIP());

After these initialization procedures, we will take care of configuring the server routes. First, we will configure the index route (“/”), which will serve a simple HTML paragraph with a “Hello World” message.

server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/html", "<p>Hello World</p>");
});

Then we will setup the route that will serve the favicon. This route will be called “/favicon.ico“, to match the endpoint that the browsers will send a GET request to in order to obtain the favicon.

This route will only listen to HTTP GET requests, as its only purpose is to serve the favicon. The route handling function implementation will consist on calling the send method on the AsyncWebServerRequest object pointer.

As first input, we will pass the SPIFFS extern variable, which will be used by the async HTTP web server framework under the hood to obtain the file to serve to the clients.

As second input, we will specify the path to the file we want to serve. In our case, the path will be “/favicon.png“.

Finally, we should pass a string with the content-type of the response. In my case, it should be “image/png“, since I’ve saved my image as a .png,

server.on("/favicon.ico", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/favicon.png", "image/png");
});

After setting the routes, we simply need to call the begin method on our server object, so it starts listening to incoming HTTP requests.

server.begin();

The final source code can be seen below.

#include "WiFi.h"
#include "ESPAsyncWebServer.h"
#include "SPIFFS.h"

const char* ssid = "yourNetworkName";
const char* password =  "yourNetworkPassword";

AsyncWebServer server(80);

void setup(){
  Serial.begin(115200);

  if(!SPIFFS.begin()){
        Serial.println("An Error has occurred while mounting SPIFFS");
        return;
  }

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }

  Serial.println(WiFi.localIP());

  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/html", "<p>Hello World</p>");
  });

  server.on("/favicon.ico", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/favicon.png", "image/png");
  });

  server.begin();
}

void loop(){}

Testing the code

To test the previous code, simply compile it and upload it using the Arduino IDE. Once the procedure finishes, open the Arduino IDE serial monitor and copy the IP that gets printed.

Then, open a web browser of your choice and type the following in the address bar, changing #yourDeviceIP# by the IP you have just copied.

http://#yourDeviceIP#/

After that, you should obtain a result similar to figure 1. As can be seen, the “Hello World” message is returned, since this was the content we configured to be returned when accessing to the index route.

Additionally, if we look into the tab at the top of the browser window, we can see the favicon we have uploaded to the SPIFFS file system. Also, if we check the Network tab of the developer tools, we can confirm that the favicon request was correctly answered by the ESP32 server.

Serving a favicon with the ESP32 and the Arduino core

Figure 2 – Serving a favicon with the ESP32.

Leave a Reply