ESP8266: Setting a simple HTTP web server

The objective of this post is to explain how to set a HTTP web server on a ESP8266 and how to make some requests to it using a web browser.


Introduction

The objective of this post is to explain how to set an HTTP web server on a ESP8266 and how to make some requests to it using a web browser.

We assume the use of the ESP8266 libraries for the Arduino IDE. You can check here how to configure the Arduino IDE to support the ESP8266.

The tests were performed using a NodeMCU board, a very cheap and easy to use ESP8266 board. The board can be bought at eBay here.


The code

First of all, we include the ESP8266WiFi library, which will make available the functionality needed for the ESP8266 to connect to a WiFi network. You can check a more detailed explanation on how to connect to a WiFi network from the ESP8266 on this previous post.

Then, we include the ESP8266WebServer library, which will make available the class ESP8266WebServer that we will use during this post. Naturally, this class has some methods available that will help us setting up a server and handle incoming HTTP requests without needing to worry about low level implementation details. You can check the implementation of the library here.

#include "ESP8266WiFi.h"
#include "ESP8266WebServer.h"

Next, we declare a global object variable from the previously mentioned class, so we will be able to access it in our functions.

As argument for the constructor of this class, we will pass the port where the server will be listening to. Since 80 is the default port for HTTP [1], we will use this value, so we will not need to specify it in the URL when accessing to our ESP8266 server using a browser.

ESP8266WebServer server(80);

Since we need to pre-configure our HTTP server before actually running it, we will do most of the coding in the setup function.

First of all, we open a serial connection for debugging.

Serial.begin(115200);

Then, we will need to connect to the WiFi network, as shown with the code below. If you need a detailed explanation on how to connect to a WiFi network with the ESP8266, check here.

WiFi.begin("Network name", "Password");

while (WiFi.status() != WL_CONNECTED) {   //Wait for connection

   delay(500);
   Serial.println("Waiting to connect...");

}

Since we are not going to do any domain name resolution, we need to know the IP where the ESP8266 is listening to incoming requests, which will be the local IP assigned in the WiFi network.

To get this value, we just call the localIP method on the WiFi global variable and then print it to the serial port, so we will know which URL to call on our web browser.

Serial.println(WiFi.localIP());

Then, we will start to specify which code to execute when an HTTP request is performed to each path. To do so, we call the on method on our previously declared server global object.

The more elegant method consists on defining a handling function somewhere in our code and passing it to the on function, alongside the URL that will trigger the execution of that function. This is exemplified below.

server.on("/", handleRootPath);

So, the code mentioned bellow indicates that when an HTTP request is received on the root (“/”) path, it will trigger the execution of the handleRootPath function. Note that we don’t specify the IP or port where the ESP8266 is listening, but only the path of the URL from that point onward.

For the sake of simplicity, let’s assume that our handleRootPath only answers with the text “Hello World” to the incoming HTTP request. So, to define an answer to a request, we call the send method on our server object.

Although the method can be called with a different set of arguments, its simplest form consists on receiving the HTTP response code, the content type and the content. Check the code below.

void handleRootPath() {

   server.send(200, "text/plain", "Hello world");

}

In this case, we are sending the code 200, which corresponds to the “OK” response [2]. Then, we are specifying the content type as “text/plain“, since we are only responding with a simple “Hello world”, and finally the actual response text.

Naturally, this function needs to be declared outside the setup function.

We can also specify the handling function when calling the on method. In this case, we don’t need to declare a separate function and we can do everything in the setup function, as demonstrated bellow.

server.on("/other", [](){

   server.send(200, "text/plain", "Other URL");

});

In this case, if we receive an HTTP request in the path “/other”, we will answer with a “Other URL” sentence.

Now, to start our server, we call the begin method on the server object. This is the last line of code we need to include in our setup function.

server.begin();

Finally, to handle the actual incoming of HTTP requests, we need to call the handleClient method on the server object, on the main loop function.

void loop() {

   server.handleClient();

}

The complete code can be seen bellow.

#include "ESP8266WiFi.h"
#include "ESP8266WebServer.h"

ESP8266WebServer server(80);

void setup() {

  Serial.begin(115200);
  WiFi.begin("Network name", "Password");  //Connect to the WiFi network

  while (WiFi.status() != WL_CONNECTED) {  //Wait for connection

    delay(500);
    Serial.println("Waiting to connect…");

  }

  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());  //Print the local IP

  server.on("/other", []() {   //Define the handling function for the path

    server.send(200, "text / plain", "Other URL");

  });

  server.on("/", handleRootPath);    //Associate the handler function to the path
  server.begin();                    //Start the server
  Serial.println("Server listening");

}

void loop() {

  server.handleClient();         //Handling of incoming requests

}

void handleRootPath() {            //Handler for the rooth path

  server.send(200, "text/plain", "Hello world");

}


Testing the code

To test the code we just need to open our browser and make an HTTP request to the IP of the ESP8266, on a path we defined early. The format is shown bellow:

http://serverIP:port/path

Since, as stated before, we are listening on the 80 port, the browser will assume it by default, so we don’t need to specify it:

http://serverIP/path

So, we substitute the serverIP by the IP printed on the serial console, and we make a request as shown in figure 1.

http-server-esp8266-root

Figure 1 – HTTP request via browser on the root path (Google Chrome).

In this case, only the IP is shown because the browser removed the “/” from the root path. Also, the http:// was removed by the browser. Although some browsers perform the request when we only specify the IP, others assume that we want to search something in a search engine. So, the safest way is to always specify the http:// before the IP.

The example from figure 2 shows a request on the path “/other” that we also defined.

esp8266-http-webserver

Figure 2 – HTTP request via browser on the “/other” path (Firefox).

Finally, note that if we specify a path not defined, the ESP will return a message indicating that the resource was not found, as we can see in figure 3, where we sent an HTTP request to the path “/notdefined”.

esp8266-http-server-path-not-defined

Figure 3 – HTTP request via browser on a path not defined.

Important: The IP that will be printed by the ESP8266 will be its private IP on the network. It won’t be possible for a client outside the network to contact it on that IP (and thus, the URL will not work). In order for a client to be able to contact the ESP8266 from outside its network, it would need to use the external IP of the network and the router would need to be configured to forward the requests on its public IP for that port to the private IP of the ESP8266. Since port forwarding depends on the router used, explaining how to do it is outside of the scope of this post.


Related posts


References

[1] http://searchnetworking.techtarget.com/definition/port-80

[2] http://www.restapitutorial.com/httpstatuscodes.html


Technical details

ESP8266 libraries: v2.3.0

39 thoughts on “ESP8266: Setting a simple HTTP web server”

  1. Pingback: ESP32 Arduino: Asynchronous HTTP webserver – Arduino Boards News

  2. Pingback: ESP32 Arduino: Asynchronous HTTP webserver – Arduino Boards News

  3. hello, thanks for awesome tutorial

    I have very strange problem in the code, when modem is turned off and then turned on, I cannot send request to esp anymore it says site cant be reached but I am sure that ESP reconnects to modem because in modem Dashboard I can see connected devices.

    Is the problem reason handleCLient might be still waiting for clients for old server ?
    I am calling server.begin again when reconnects can it be reason, and what should i do???

    Please help

    1. Hi! Thanks for the feedback 🙂

      At the time I played with the HTTP server, I never tested it for those disconnect / reconnect conditions, so I’m not sure what may be causing the problem.

      Maybe it is something related with binding the server with the network interface when the device reconnects.

      Nonetheless, my recommendation is that you share the issue in the GitHub page of the Arduino core for the ESP8266, since somebody may already have found the same issue and found a solution:
      https://github.com/esp8266/Arduino

      Just as an additional note, there’s a new async HTTP server library for the ESP32 / ESP8266 that may be more reliable than the original one. I haven’t tested it yet for the ESP8266, but it works pretty well for the ESP32:
      https://github.com/me-no-dev/ESPAsyncWebServer

      Best regards,
      Nuno Santos

  4. hello, thanks for awesome tutorial
    I have very strange problem in the code, when modem is turned off and then turned on, I cannot send request to esp anymore it says site cant be reached but I am sure that ESP reconnects to modem because in modem Dashboard I can see connected devices.
    Is the problem reason handleCLient might be still waiting for clients for old server ?
    I am calling server.begin again when reconnects can it be reason, and what should i do???
    Please help

    1. Hi! Thanks for the feedback 🙂
      At the time I played with the HTTP server, I never tested it for those disconnect / reconnect conditions, so I’m not sure what may be causing the problem.
      Maybe it is something related with binding the server with the network interface when the device reconnects.
      Nonetheless, my recommendation is that you share the issue in the GitHub page of the Arduino core for the ESP8266, since somebody may already have found the same issue and found a solution:
      https://github.com/esp8266/Arduino
      Just as an additional note, there’s a new async HTTP server library for the ESP32 / ESP8266 that may be more reliable than the original one. I haven’t tested it yet for the ESP8266, but it works pretty well for the ESP32:
      https://github.com/me-no-dev/ESPAsyncWebServer
      Best regards,
      Nuno Santos

  5. I’m facing the same issue as mamacker ie my 2 tested esp-01 halt daily and no more respond to the requests till i reset the device manually. Don’t know if it’s a software or hardware issue.
    Note : a lot of people over internet are facing the same issue of web server halting and no more responding after some hours without any solution . Strange…

    1. Hi! Unfortunately I haven’t yet came across any solution, but it is indeed a strange problem, specially in a feature that should be used a lot, such as setting a HTTP server.

      Nonetheless, there’s a new implementation of a HTTP server for the ESP8266 / ESP32 that you may give a try to check if works more reliably.

      The implementation of this solution is asynchronous and thus should be more flexible, at least in terms of software development.

      I haven’t had the change to test it on the ESP8266 yet, but it works pretty well on the ESP32.

      GitHub Page:
      https://github.com/me-no-dev/ESPAsyncWebServer

      Let me know if this helps.

      Best regards,
      Nuno Santos

  6. I’m facing the same issue as mamacker ie my 2 tested esp-01 halt daily and no more respond to the requests till i reset the device manually. Don’t know if it’s a software or hardware issue.
    Note : a lot of people over internet are facing the same issue of web server halting and no more responding after some hours without any solution . Strange…

    1. Hi! Unfortunately I haven’t yet came across any solution, but it is indeed a strange problem, specially in a feature that should be used a lot, such as setting a HTTP server.
      Nonetheless, there’s a new implementation of a HTTP server for the ESP8266 / ESP32 that you may give a try to check if works more reliably.
      The implementation of this solution is asynchronous and thus should be more flexible, at least in terms of software development.
      I haven’t had the change to test it on the ESP8266 yet, but it works pretty well on the ESP32.
      GitHub Page:
      https://github.com/me-no-dev/ESPAsyncWebServer
      Let me know if this helps.
      Best regards,
      Nuno Santos

  7. Pingback: ESP8266 Arduino: Asynchronous HTTP web server | techtutorialsx

  8. Pingback: ESP8266 Arduino: Asynchronous HTTP web server | techtutorialsx

Leave a Reply