diff --git a/libraries/WebServer/src/Parsing.cpp b/libraries/WebServer/src/Parsing.cpp
index 200244e6848..453cae1e6e0 100644
--- a/libraries/WebServer/src/Parsing.cpp
+++ b/libraries/WebServer/src/Parsing.cpp
@@ -345,13 +345,41 @@ void WebServer::_uploadWriteByte(uint8_t b) {
 
 int WebServer::_uploadReadByte(NetworkClient &client) {
   int res = client.read();
-
+  
   if (res < 0) {
-    while (!client.available() && client.connected()) {
-      delay(2);
-    }
+    // keep trying until you either read a valid byte or timeout
+    const unsigned long startMillis = millis();
+    const long timeoutIntervalMillis = client.getTimeout();
+    bool timedOut = false;
+    for(;;) {
+      if (!client.connected()) return -1;
+      // loosely modeled after blinkWithoutDelay pattern
+      while(!timedOut && !client.available() && client.connected()){
+        delay(2);
+        timedOut = (millis() - startMillis) >= timeoutIntervalMillis;
+      }
 
-    res = client.read();
+      res = client.read();
+      if(res >= 0) {
+        return res; // exit on a valid read
+      }
+      // NOTE: it is possible to get here and have all of the following
+      //       assertions hold true
+      //
+      //       -- client.available() > 0
+      //       -- client.connected == true
+      //       -- res == -1
+      //
+      //       a simple retry strategy overcomes this which is to say the
+      //       assertion is not permanent, but the reason that this works
+      //       is elusive, and possibly indicative of a more subtle underlying
+      //       issue
+
+      timedOut = (millis() - startMillis) >= timeoutIntervalMillis;
+      if (timedOut) {
+        return res; // exit on a timeout
+      }
+    }
   }
 
   return res;
diff --git a/libraries/WebServer/src/WebServer.cpp b/libraries/WebServer/src/WebServer.cpp
index 92623b79c01..3996d3bdb0e 100644
--- a/libraries/WebServer/src/WebServer.cpp
+++ b/libraries/WebServer/src/WebServer.cpp
@@ -432,10 +432,8 @@ void WebServer::handleClient() {
       case HC_WAIT_READ:
         // Wait for data from client to become available
         if (_currentClient.available()) {
+          _currentClient.setTimeout(HTTP_MAX_SEND_WAIT); /* / 1000 removed, WifiClient setTimeout changed to ms */
           if (_parseRequest(_currentClient)) {
-            // because HTTP_MAX_SEND_WAIT is expressed in milliseconds,
-            // it must be divided by 1000
-            _currentClient.setTimeout(HTTP_MAX_SEND_WAIT); /* / 1000 removed, WifiClient setTimeout changed to ms */
             _contentLength = CONTENT_LENGTH_NOT_SET;
             _handleRequest();