Kernel/Parser handles sequential requests better

feature/UrlUtils
Kenneth Barbour 2018-03-17 13:51:16 -04:00 committed by Kenneth Barbour
parent 91440090b2
commit d1f99c069c
6 changed files with 80 additions and 12 deletions

View File

@ -1,5 +1,9 @@
#include "RequestParser.h"
void RequestParser::reset() {
_state = S_IN_METHOD;
}
bool RequestParser::parse() {
unsigned int content_length = 0, available = 0, writable = 0;

View File

@ -28,6 +28,7 @@ class RequestParser
bool parse();
bool error() { return _state == S_ERROR; };
void reset();
private:

View File

@ -2,27 +2,27 @@
void WebKernel::handleClients()
{
bool shouldYield = true;
bool keepClient = false;
bool shouldYield = false;
bool keepClient = true;
if (_state == S_IDLE) {
WiFiClient client = _server.available();
if (!client) return;
_client = _server.available();
if (!_client) return;
_client = client;
_request = HttpRequest();
_parser.reset();
_state = S_RECEIVING;
_stateChange = millis();
}
if (_client.connected()) {
if (millis() - _stateChange >= WEBKERNEL_MAX_WAIT) {
keepClient = false;
} else if (_client.connected()) {
switch (_state) {
case S_IDLE:
break;
case S_RECEIVING:
if (!_parser.parse()) {
if (millis() - _stateChange <= WEBKERNEL_MAX_WAIT)
keepClient = false;
shouldYield = true;
break;
}
@ -40,8 +40,6 @@ void WebKernel::handleClients()
keepClient = false;
}
if (millis() - _stateChange <= WEBKERNEL_MAX_WAIT) keepClient = false;
if (!keepClient) {
_client.stop();
_state = S_IDLE;

View File

@ -33,6 +33,7 @@ class WebKernel
#ifdef _TEST_
void mock_nextClient(const char * next) { _server._next = next; }
WiFiClient& mock_currentClient() { return _client; }
#endif
protected:

View File

@ -42,3 +42,23 @@ TEST_CASE("Test message data","[RequestParser]")
CHECK(request.getMessageLength() == 10);
CHECK_THAT(request.getMessage(), Equals("1234567890"));
}
TEST_CASE("Test parse multiple requests","[RequestParser]")
{
uint8_t buff[256] = {};
Buffer client(buff, 256);
HttpRequest request;
RequestParser parser(request, client);
client.write("GET /foo HTTP/1.1\r\nHost: localhost\r\n\r\n");
CHECK(parser.parse());
CHECK_THAT(request.getUrl(), Equals("/foo"));
parser.reset();
client = Buffer(buff, 256);
request = HttpRequest();
client.write("GET /bar HTTP/1.1\r\nHost: localhost\r\n\r\n");
CHECK(parser.parse());
CHECK_THAT(request.getUrl(), Equals("/bar"));
}

View File

@ -28,6 +28,9 @@ TEST_CASE("Test WebKernel", "[WebKernel]")
WebKernel kernel(80, routes, sizeof routes / sizeof routes[0]);
foo = 0;
bar = 0;
SECTION("No client") {
kernel.handleClients();
}
@ -43,10 +46,51 @@ TEST_CASE("Test WebKernel", "[WebKernel]")
SECTION("Request for bar") {
kernel.mock_nextClient("GET /bar HTTP/1.1\r\nHost: localhost\r\n\r\n");
REQUIRE(foo == 1);
REQUIRE(foo == 0);
REQUIRE(bar == 0);
kernel.handleClients();
CHECK(foo == 1);
CHECK(foo == 0);
CHECK(bar == 1);
}
}
TEST_CASE("Test Partial requests", "[WebKernel]")
{
Route routes[] = {
{ GET, "/foo", do_foo },
{ GET, "/bar", do_bar }
};
WebKernel kernel(80, routes, 2);
foo = bar = 0;
SECTION("Partial GET") {
kernel.mock_nextClient("GET /foo");
kernel.handleClients();
REQUIRE(foo == 0);
REQUIRE(bar == 0);
WiFiClient& client = kernel.mock_currentClient();
CHECK(client.available() == 0);
delay(100);
client.write(" HTTP/1.1\r\nHost:localhost\r\n\r\n");
kernel.handleClients();
CHECK(foo == 1);
CHECK(client.available() > 0);
}
SECTION("Timeout") {
REQUIRE(foo == 0);
kernel.mock_nextClient("GET /foo");
kernel.handleClients();
WiFiClient& client = kernel.mock_currentClient();
kernel.mock_nextClient("GET /bar HTTP/1.1\r\nHost: localhost\r\n\r\n");
delay(WEBKERNEL_MAX_WAIT);
kernel.handleClients(); //
REQUIRE(foo == 0);
REQUIRE(bar == 0);
CHECK(client.connected() == false);
kernel.handleClients();
REQUIRE(foo == 0);
REQUIRE(bar == 1);
}
}