I'm running a simple HTTP webserver on the Portenta Control (based on the Ethernet library) but requests from Chromium based browsers (Edge, Chrome, Vivaldi) lock up the webserver. This issue does not occur with Firefox or curl requests. In Wireshark I see the following when I enter the ip address of the Arduino http://192.168.5.5
For Firefox everything looks normal. In the second image I selected follow HTTP conversation.
I don't really follow your post, but I do know it is extremely common for programmers to determine which browser they are communicating with as there are a great number of cases where they don't all respond the same way. This sounds like that situation. Are you saying the arduino library code is not accommodating every kind of browser?
Specific browser issues are more with the actual HTML/javascript. What I seem to have is an issue on the lower TCP layer. You can see in the wireshark screenshots that Edge is opening a second connection to the Arduino which doesn't seem to be handled properly by the Arduino Ethernet library and ends in a RESET
Clients are happier when they know they've got the entire response payload. This can be done by setting the Content-Length header for the response (when you know it in advance), or using Transfer-Encoding: chunked, which sends a final "all done" chunk. Try
String payload = "<html><head><title>test</title></head><body>test page</body></html>";
client.println("HTTP/1.1 200 OK");
client.println("Connection: close");
client.println("Content-Type: text/html; charset=utf-8");
client.print("Content-Length: ");
client.println(payload.length());
client.println();
client.print(payload); // not println -- don't need those extra bytes
Doing that should also allow you to stop lying that you're HTTP 1.1, and be honest that you're going to close the connection, even though the client asked for Connection: keep-alive. You'll also save about twenty bytes
client.println("HTTP/1.0 200 OK");
client.println("Content-Type: text/html; charset=utf-8");
client.print("Content-Length: ");
client.println(payload.length());
client.println();
client.print(payload); // not println -- don't need those extra bytes
ETA: chunked only available with 1.1 (and not with HTTP/2 either)
Some browsers will make 2 requests back-to-back, a request for the page, then request favicon. Are you returning "HTTP/1.1 200 OK" to both? If no favicon, return 404 to that request.
You decided to ignore the second connection rather than reading the GET header line?
My approach is different. I return "HTTP/1.1 404 File Not Found" unless the GET line has an existing file or in your case "GET / HTTP/1.1" (default file)
Then it will return the 404 message to the client browser when it asks for favicon.ico. That will also prevent the problem in the correct way.
Just my opinion.
The thing is there is no GET header. That second TCP connection is never used and makes the Arduino hang. It returns client.connected()=true but client.available()=false forever. Or maybe it times out or closes on certain conditions because in the past these browsers locked up my arduino after a few requests. But now that I implemented a watchdog to reset on 30sec timeout, it resets my Arduino basically on every request (unless I use the connection_timeout check in the code above)
I installed the opensource PC program SimpleWebServer and checked Wireshark. In Edge I perform a request to http://127.0.0.1:8080/test.html
Also here we see Edge opening 2 tcp connections but never use the second one. There is no GET /favicon. After a while SimpleWebServer responds with "400 bad request"
I don't get why this is happening and how is not locking up everyones Arduino when using these browsers since all the Arduino code examples I found don't have this connection_timeout check. I checked this now on different networks and different PCs with different Windows version.
If it's Chromium or Firefox, they send a GET header. "GET /filename HTTP/1.1"
They will also send several more lines of header.
I have a web server on a Mega2560 with an ethernet shield, and mine does not freeze. It will send favicon.ico to the client if it is on my SD card.
It serves all kinds of files. Text, html, ico, css, jpg, and more. Whatever the client requires to build the webpage.
If the request to my server does not include a GET line, my server returns "HTTP/1.1 400 Bad Request"