Webserver hangs only when accessed by CHrome

I have created (well modified) my first sketch using the esp8266 as a webserver. I plan on making this drive a DC motor with limit switches and using the webserver component to tell the motor to go clockwise or counter clockwise.

Problem is the code below seems to work fine when my phone accesses the webserver and I click on the buttons. It also works from microsoft edge on my laptop. However fro some reason after clicking the buttons a few times the webserver seems to disappear and I need to reboot the esp8266. It only seems to happen when I access it from chrome on my laptop (its fine when accessed from chrome on my phone or edge on my laptop.

Any ideas?

#include <ESP8266WiFi.h>

const char* ssid = "PeLa";
const char* password = "molly197";
const char* host = "192.168.43.230"; //it will tell you the IP once it starts up
                                        //just write it here afterwards and upload
int CcwPin = D1;
int CwPin = D2;

WiFiServer server(301); //just pick any port number you like

void setup() {
  Serial.begin(115200);
  delay(10);
Serial.println(WiFi.localIP());
  // prepare GPIO2
  pinMode(CcwPin, OUTPUT);
    pinMode(CwPin, OUTPUT);
  digitalWrite(D1, LOW);
   digitalWrite(D2, LOW);

  // Connect to WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");

  // Start the server
  server.begin();
  Serial.println("Server started");

  // Print the IP address
  Serial.println(WiFi.localIP());
}

void loop() {
  // Check if a client has connected
  
  WiFiClient client = server.available();
  if (!client) {
    return;
  }

  // Wait until the client sends some data
  while (!client.available()) {
    delay(1);
  }

  // Read the first line of the request
  String req = client.readStringUntil('\r');
  client.flush();

  // Match the request
  if (req.indexOf("") != -10) {  //checks if you're on the main page

    
        if (req.indexOf("/CW") != -1) { //checks if you clicked ON
      digitalWrite(CcwPin, LOW);
          digitalWrite(CwPin, HIGH); 
      Serial.println("Opening the Projector Door Blinds");
    }
            if (req.indexOf("/CCW") != -1) { //checks if you clicked ON
      digitalWrite(CcwPin, HIGH);
        digitalWrite(CwPin, LOW); 
      Serial.println("Closing the Projector Door Blinds");
    }
  }

  else {
    Serial.println("invalid request");
   client.stop();
    return;
  }

  // Prepare the response
  String s = "HTTP/1.1 200 OK\r\n";
  s += "Content-Type: text/html\r\n\r\n";
  s += "<!DOCTYPE HTML>\r\n<html>\r\n";
  s += "
<input type=\"button\" name=\"bl\" value=\"Open Projector Door Blinds \" onclick=\"location.href='/CCW'\">";
  s += "


";
  s += "
<input type=\"button\" name=\"bl\" value=\"Close Projector Door Blinds\" onclick=\"location.href='/CW'\">";
  s += "</html>\n";

  client.flush();


  // Send the response to the client
  client.print(s);
  delay(1);


  
}

I would be suspicious of the html-code in that event, though at first glance i could find anything obvious. On closer look , first let's remove all \r & \n, since they do nothing within html (and it's confusing enough as it is.)

String s = "HTTP/1.1 200 OK";
  s += "Content-Type: text/html";
  s += "<!DOCTYPE HTML><html>";
  s += "
<input type=\"button\" name=\"bl\" value=\"Open Projector Door Blinds \" onclick=\"location.href='/CCW'\">";
  s += "


";
  s += "
<input type=\"button\" name=\"bl\" value=\"Close Projector Door Blinds\" onclick=\"location.href='/CW'\">";
  s += "</html>";

and let's see if we modify the header a little

String s = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">";
  s += "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" ></head>";
  s += "
<input type=\"button\" name=\"bl\" value=\"Open Projector Door Blinds \" onclick=\"location.href='/CCW'\">";
  s += "


";
  s += "
<input type=\"button\" name=\"bl\" value=\"Close Projector Door Blinds\" onclick=\"location.href='/CW'\">";
  s += "</html>";
WiFiServer server(301); //just pick any port number you like

Just use port 80 (port 301 may be used as a service port)

Now what is going on here ?

// prepare GPIO2
  pinMode(CcwPin, OUTPUT);
    pinMode(CwPin, OUTPUT);
  digitalWrite(D1, LOW);
   digitalWrite(D2, LOW);

GPIO2 ? we are not using that and are not preparing it, we are using D1 & D2. and although functionally it doesn't matter, if we reference the pins (using CcWPin) then we should be consistent.

btw i am not sure what this

const char* host = "192.168.43.230"; //it will tell you the IP once it starts up
                                        //just write it here afterwards and upload

is for, but it's never used as far as i can tell, your router may assign a different IP to the ESP every time it connects (though it will usually assign the same one again)

Thanks. I've made the changes, and hoped the port change might help... however it seems if I click one of the buttons multipe times it will eventually hang the websever.. By hang I mean it is not accessible, I can still ping the esp8266.

Its not the end of the world as I am using the webserver to change the state of the D1 and D2 digital outputs using a http post from my home automation (hubitat) so hopefully it won't matter that only chrome on my laptop (windows 10) seems to hang it.

what shows up in your address bar ? the correct IP and then /CCW just once ? I don't use your method (meaning i never use href ), but i have had this sort of experience and in the end i found a small part of html to be responsible (i opened but never closed it using </body.) Can you still access the page using your phone once Chrome can't anymore ? iow does chrome crash or does the ESP ?

Deva_Rishi:
what shows up in your address bar ? the correct IP and then /CCW just once ?

Yes the ip then /CCW. If I click again the same button again it reloads the same address.

Deva_Rishi:
i found a small part of html to be responsible (i opened but never closed it using </body.)

Oh ok I'll have a look at that.

Deva_Rishi:
Can you still access the page using your phone once Chrome can't anymore ? iow does chrome crash or does the ESP ?

No I can't access it from any device once it wasn't responding in chrome on Windows, as in just the Web servers not responding as Chrome is still fine. I can ping the esp however. Rebooting the esp fixes it and I have no problems until I try accessing it from Chrome in Windows again.

No I can't access it from any device once it wasn't responding in chrome on Windows, as in just the Web servers not responding as Chrome is still fine. I can ping the esp however. Rebooting the esp fixes it and I have no problems until I try accessing it from Chrome in Windows again.

So maybe the ESP gets stuck within a loop. maybe here :

 // Wait until the client sends some data
  while (!client.available()) {
    delay(1);
  }

The delay(1) makes sure the esp background processes are continued, but unlike in the earlier part no return; is executed to destroy the object if there is no response,
from the WifiCiient example

unsigned long timeout = millis();
  while (client.available() == 0) {
    yield(); // this line is missing in the example btw
    if (millis() - timeout > 5000) {
      Serial.println(">>> Client Timeout !");
      client.stop();
      return;
    }
  }

which accepts the possibility of a client not responding. (and destroys the object after 5 secs)