ESP32 HTTPS server: Specifying HTTP response status code

Introduction

In this tutorial we will check how to specify the HTTP status code to be returned to clients from the routes of a HTTPS server hosted on the ESP32. We will be using the Arduino core.

For an introduction on how to get started using the library needed to setup the HTTPS server, please check this previous tutorial.

As mentioned on the previous tutorial, by default, the HTTPS web server framework will return a 200 status code to the client, if we don’t explicitly set this value. Naturally, for different use cases, we might want to return different status codes. Thus, we will learn how to do it on this tutorial.

The tests shown here were performed using an ESP32 board from DFRobot.

The code

We will start our code by the library includes, so we have access to all the functionality needed to connect the ESP32 to a WiFi network and to setup the HTTPS web server.

We will also declare the using of the httpsserver namespace, so we can avoid having to use the scope resolution operator.

#include <WiFi.h>
#include <HTTPSServer.hpp>
#include <SSLCert.hpp>
#include <HTTPRequest.hpp>
#include <HTTPResponse.hpp>
  
using namespace httpsserver;

After this, we will declare the credentials of the WiFi network (name and password) as two global variables.

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

We will also need a pointer to an object of class SSLCert, to hold the certificate information, and a pointer to an object of class HTTPSServer, which will be used to setup the server.

SSLCert * cert;
HTTPSServer * secureServer;

Moving on to the Arduino setup, we will start by opening a serial connection, to be able to output messages from our program.

Then, we will take care of generating a self signed certificate for our server. Naturally, this should be used only for testing purposes.

Serial.begin(115200);
 
 
//----Generating the certificate----
Serial.println("Creating certificate...");
    
cert = new SSLCert();
  
int createCertResult = createSelfSignedCert(
    *cert,
    KEYSIZE_2048,
    "CN=myesp.local,O=acme,C=US");
    
if (createCertResult != 0) {
    Serial.printf("Error generating certificate");
    return; 
}
  
Serial.println("Certificate created with success"); 

Then we will connect the ESP32 to the WiFi network, using the previously declared credentials.

//----Connect to WiFi----
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 create an instance of the HTTPSServer class. This will be used below for configuring the HTTPS server.

secureServer = new HTTPSServer(cert);

Then we will declare ResourceNodes for two routes, where we will exemplify how to return HTTP response codes other than 200.

We will start by a route that will return a Not Found (404) status code. We will assume this route is called “/notfound” and listens to HTTP GET requests.

Then, we will specify the status code to be returned to the client inside the route handling function.

So, to specify a returning HTTP status code, we simply need to call the setStatusCode method on the HTTPResponse object pointer that we receive as input of the route handling function.

As input of this method, we pass an integer with the status code we want to return back to the client.

After than, we can return a message to the client (as we did in previous tutorials) by calling the println method on the same HTTPResponse object pointer.

ResourceNode * notFoundRoute = new ResourceNode("/notfound", "GET", [](HTTPRequest * req, HTTPResponse * res){
    res->setStatusCode(404);
    res->println("Not found");
});

Now we will do the same for the other route, but we will return a Created (201) status code instead. This status code indicates a new resource as been created in the server. Naturally, we won’t create anything since we are just testing how to set the status code.

ResourceNode * createdRoute = new ResourceNode("/created", "GET", [](HTTPRequest * req, HTTPResponse * res){
    res->setStatusCode(201);
    res->println("Created");
});

After this, we simply need to register the ResourceNodes on our server object and then start the server.

secureServer->registerNode(notFoundRoute);
secureServer->registerNode(createdRoute);

secureServer->start();
    
 if (secureServer->isRunning()) {
    Serial.println("Server ready.");
}else{
    Serial.println("Server could not be started.");
}

To finalize, we need to call the loop method periodically on our server object, so it handles incoming client requests.

void loop() {
   
  secureServer->loop();  
  delay(10);
}

The final complete source code can be seen below.

#include <WiFi.h>
#include <HTTPSServer.hpp>
#include <SSLCert.hpp>
#include <HTTPRequest.hpp>
#include <HTTPResponse.hpp>
  
using namespace httpsserver;
  
const char* ssid = "yourNetworkName";
const char* password =  "yourNetworkPassword";
 
SSLCert * cert;
HTTPSServer * secureServer;
  
void setup() {
  
  Serial.begin(115200);
 
 
  //----Generating the certificate----
  Serial.println("Creating certificate...");
    
  cert = new SSLCert();
  
  int createCertResult = createSelfSignedCert(
    *cert,
    KEYSIZE_2048,
    "CN=myesp.local,O=acme,C=US");
    
  if (createCertResult != 0) {
    Serial.printf("Error generating certificate");
    return; 
  }
  
  Serial.println("Certificate created with success");
 
 
  //----Connect to WiFi----
  WiFi.begin(ssid, password);
   
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }  
   
  Serial.println(WiFi.localIP());
 
 
  //----Configure server----
  secureServer = new HTTPSServer(cert);
  
  ResourceNode * notFoundRoute = new ResourceNode("/notfound", "GET", [](HTTPRequest * req, HTTPResponse * res){
    res->setStatusCode(404);
    res->println("Not found");
  });

  ResourceNode * createdRoute = new ResourceNode("/created", "GET", [](HTTPRequest * req, HTTPResponse * res){
    res->setStatusCode(201);
    res->println("Created");
  });
  
  secureServer->registerNode(notFoundRoute);
  secureServer->registerNode(createdRoute);

    
  secureServer->start();
    
  if (secureServer->isRunning()) {
    Serial.println("Server ready.");
  }else{
    Serial.println("Server could not be started.");
  }
}
  
void loop() {
   
  secureServer->loop();  
  delay(10);
}

Testing the code

To test the code, simply compile it and upload it to your device, using the Arduino IDE. When the procedure finishes, open the IDE serial monitor and wait for the generation of the certificate and for the connection to the WiFi network. Please note that these procedures may take a while.

When the ESP32 finishes the connection to the WiFi network, an IP address should get printed to the serial monitor. Copy it.

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

https://#yourDeviceIp#/notfound

Your browser should warn you about security issues regarding the certificate of the server, which is expected since the ESP32 is using a self signed certificate. You should choose to advance.

Then, you should get an output similar to figure 1. As can be seen, the message we defined as output of the “/notfound” route gets printed. If we open the browser networking tab, we should see that the request returned a 404 status code.

Sending a HTTPS request to a ESP32 route which is returning a 404 code.
Figure 1 – Contacting the “/notfound” route of the ESP32 HTTPS web server.

Then, repeat the same procedure but this time to access the “/created” route:

https://#yourDeviceIp#/created

You should get an output similar to figure 2. As can be seen, the server is returning a 201 code, as expected.

Sending a HTTPS request to a ESP32 route which is returning a 201 code.
Figure 2 – Contacting the “/created” route of the ESP32 HTTPS web server.

Related Posts

Leave a Reply

Discover more from techtutorialsx

Subscribe now to keep reading and get access to the full archive.

Continue reading