HttpResponse has a send() method and expects to be assigned a Stream containing the message

feature/UrlUtils
Kenneth Barbour 2018-04-01 10:37:19 -04:00
parent fd1019e1fa
commit 43ccbf4a52
11 changed files with 73 additions and 111 deletions

View File

@ -9,6 +9,11 @@ int Buffer::availableForWrite()
return size - num;
}
int Buffer::available() const
{
return num;
}
int Buffer::available()
{
return num;
@ -23,21 +28,6 @@ size_t Buffer::write(uint8_t byte)
return 1;
}
/*
size_t Buffer::write(const uint8_t * buff, size_t len)
{
size_t avail = availableToWrite();
size_t toWrite = (avail < len) ? avail : len;
for (size_t i = 0; i < toWrite; i++) {
if (w_ptr >= start + size) w_ptr = start;
*(w_ptr++) = buff[i];
}
num += toWrite;
return toWrite;
}
*/
int Buffer::read()
{
if (available() == 0) return 0;
@ -53,7 +43,20 @@ int Buffer::peek()
return *(r_ptr);
}
void Buffer::flush()
size_t Buffer::printTo(Print& stream) const
{
size_t av = available();
size_t written = 0;
uint8_t * ptr = r_ptr;
while (written < av) {
if (ptr >= start + size) ptr = start;
written += stream.write(*(ptr++));
}
return written;
}
void Buffer::clear()
{
w_ptr = start;
r_ptr = start;

View File

@ -5,18 +5,21 @@
#else
#include "Arduino.h"
#endif
#include "Printable.h"
class Buffer: public Stream
class Buffer: public Stream, public Printable
{
public:
Buffer(uint8_t*, size_t);
virtual size_t write(uint8_t);
int availableForWrite();
int available() const;
int available();
int peek();
int read();
virtual void flush();
void clear();
using Print::write;
size_t printTo(Print& stream) const;
private:
uint8_t * start;

View File

@ -3,22 +3,22 @@
/**
* TODO: this is the only constructor really needed unless _TEST_
*/
HttpResponse::HttpResponse(Buffer & buffer):
buffer(&buffer),
HttpResponse::HttpResponse(Stream& buffer):
content(&buffer),
code(200),
reason(),
httpver()
{};
HttpResponse::HttpResponse(Buffer & buffer, unsigned int code):
buffer(&buffer),
HttpResponse::HttpResponse(Stream& buffer, unsigned int code):
content(&buffer),
code(code),
reason(),
httpver()
{};
HttpResponse::HttpResponse(Buffer & buffer, unsigned int code, const char * reason):
buffer(&buffer),
HttpResponse::HttpResponse(Stream& buffer, unsigned int code, const char * reason):
content(&buffer),
code(code),
reason(),
httpver()
@ -27,21 +27,21 @@ HttpResponse::HttpResponse(Buffer & buffer, unsigned int code, const char * reas
}
HttpResponse::HttpResponse():
buffer(),
content(),
code(200),
reason(),
httpver()
{};
HttpResponse::HttpResponse(unsigned int code):
buffer(),
content(),
code(code),
reason(),
httpver()
{}
HttpResponse::HttpResponse(unsigned int code, const char * reason):
buffer(),
content(),
code(code),
reason(),
httpver()
@ -129,17 +129,7 @@ const char * HttpResponse::getDefaultReason(unsigned int code)
}
}
size_t HttpResponse::write(uint8_t data)
{
return buffer->write(data);
}
size_t HttpResponse::write(uint8_t * data, size_t len)
{
return buffer->write(data, len);
}
size_t HttpResponse::printTo(Print& client) const
size_t HttpResponse::send(Print& client)
{
size_t len = 0;
len += client.print(getHttpVersion());
@ -148,8 +138,9 @@ size_t HttpResponse::printTo(Print& client) const
len += client.print(' ');
len += client.println(getReason());
len += client.println(headers);
for (size_t i = buffer->available(); i > 0; i--)
len += client.print((char)buffer->read());
while (content->available()) {
len += client.write(content->read());
}
return len;
}

View File

@ -8,17 +8,16 @@
#include "Arduino.h"
#endif
#include "Print.h"
#include "Printable.h"
#define HTTPRESPONSE_HTTPVER_SIZE 9
class HttpResponse: public Print, public Printable
class HttpResponse
{
public:
HttpResponse(Buffer&); // TODO: only cnstr needed by WebKernel, add httpver param
HttpResponse(Buffer&, unsigned int); // TODO: remove unnecessary constructors
HttpResponse(Buffer&, unsigned int, const char *);
HttpResponse(Stream&); // TODO: only cnstr needed by WebKernel, add httpver param
HttpResponse(Stream&, unsigned int); // TODO: remove unnecessary constructors
HttpResponse(Stream&, unsigned int, const char *);
HttpResponse();
HttpResponse(unsigned int code);
HttpResponse(unsigned int code, const char *);
@ -30,14 +29,11 @@ class HttpResponse: public Print, public Printable
const char * setReason(const char * reason);
const char * getReason() const;
static const char * getDefaultReason(unsigned int);
void send(Stream &client);
size_t write (uint8_t);
size_t write (uint8_t *, size_t);
using Print::write;
Stream * content;
size_t send(Print&);
size_t printTo(Print&) const;
private:
Buffer * buffer;
char * reason;
char httpver[HTTPRESPONSE_HTTPVER_SIZE];
};

View File

@ -30,14 +30,12 @@ void RouteDispatcher::handleNotFound(HttpRequest& request, HttpResponse& respons
{
response.code = 404;
response.headers.set("Content-Type","text/plain");
response.print(response.getReason());
}
void RouteDispatcher::handleMethodNotAllowed(HttpRequest& request, HttpResponse& response)
{
response.code = 405;
response.headers.set("Content-Type","text/plain");
response.print(response.getReason());
}
void RouteDispatcher::responseSetAllowedHeader(HttpResponse& response, uint8_t allowed)

View File

@ -36,13 +36,11 @@ void WebKernel::handleClients()
_stateChange = millis();
_client.flush();
case S_DISPATCHING:
HttpResponse response(_resp_buffer);
response.setHttpVersion(_request.getHttpVersion());
if (!_parser.error()) {
_dispatcher.handle(_request, response);
response.headers.set("Connection","close");
_client.print(response);
if (_parser.error()) {
keepClient = false;
break;
}
dispatchRequest();
keepClient = false;
break;
}
@ -56,7 +54,6 @@ void WebKernel::handleClients()
#endif
_client.stop();
_state = S_IDLE;
_resp_buffer.flush();
}
// if (shouldYield)
@ -64,4 +61,10 @@ void WebKernel::handleClients()
}
void WebKernel::dispatchRequest()
{
HttpResponse response;
response.setHttpVersion(_request.getHttpVersion());
_dispatcher.handle(_request, response);
response.send(_client);
}

View File

@ -26,17 +26,11 @@ class WebKernel
_router(routes, num),
_state(S_IDLE),
_dispatcher(_router),
_parser(_request, _client),
_resp_buffer(_resp_data, WEBKERNEL_RESPONSE_SIZE),
_badRequestHandler(handleBadRequest)
_parser(_request, _client)
{};
void begin() { _server.begin(); }
void handleClients();
static void handleBadRequest(HttpRequest& req, HttpResponse& resp) {
resp.code = 400;
}
void setNotFoundHandler(void (*handler)(HttpRequest&, HttpResponse&))
{
_dispatcher.notFoundHandler = handler;
@ -63,9 +57,6 @@ class WebKernel
WebKernelState _state;
unsigned long int _stateChange;
uint8_t _resp_data[WEBKERNEL_RESPONSE_SIZE];
Buffer _resp_buffer;
void (*_badRequestHandler)(HttpRequest&, HttpResponse&);
void dispatchRequest();
};

View File

@ -124,14 +124,14 @@ TEST_CASE("Buffer is a Stream","[Buffer][Stream]")
}
TEST_CASE("Test flush","[Buffer]")
TEST_CASE("Test clear","[Buffer]")
{
uint8_t ptr[8];
Buffer buffer(ptr, 8);
buffer.write("Foo");
REQUIRE(buffer.available() == 3);
buffer.flush();
buffer.clear();
REQUIRE(buffer.available() == 0);
buffer.write("Bar");
REQUIRE(buffer.available() == 3);

View File

@ -32,7 +32,7 @@ TEST_CASE("Unset reason", "[HttpResponse]")
REQUIRE_THAT(response.getReason(), Equals("OK")); // unsetting reason should restore default
}
TEST_CASE("HttpResponse printTo", "[HttpResponse]")
TEST_CASE("HttpResponse send", "[HttpResponse]")
{
uint8_t response_buffer[100];
uint8_t print_buffer[100];
@ -42,11 +42,12 @@ TEST_CASE("HttpResponse printTo", "[HttpResponse]")
r.setHttpVersion("HTTP/1.1");
r.code = 200;
r.write("Response Body");
message.write("AAAABBBBCCCCDDDD");
r.headers.set("Cookie","1234");
client.print(r);
r.content = &message;
r.send(client);
CHECK_THAT((char *)print_buffer, Equals("HTTP/1.1 200 OK\r\nCookie: 1234\r\n\r\nResponse Body"));
CHECK_THAT((char *)print_buffer, Equals("HTTP/1.1 200 OK\r\nCookie: 1234\r\n\r\nAAAABBBBCCCCDDDD"));
}
TEST_CASE("HttpResponse get/setHttpVersion", "[HttpResponse]")

View File

@ -1,31 +0,0 @@
#include "catch.hpp"
#include "WebKernel.h"
#include <iostream>
using Catch::Matchers::Equals;
void index(HttpRequest& request, HttpResponse& response)
{
response.write("Site Index");
}
void save(HttpRequest& request, HttpResponse& response)
{
response.write("You sent post data");
response.code = 201;
}
void create(HttpRequest& request, HttpResponse& response)
{
response.write("Foo form");
}
uint8_t requestData[256];
uint8_t responseData[256];
Route routes[] = {
{ GET, "/", index },
{ POST, "/foo", save },
{ GET, "/foo", create }
};

View File

@ -7,18 +7,25 @@ unsigned int bar;
char error_message[24] = {};
char response_buffer[100] = {};
Buffer message((uint8_t*)response_buffer, 100);
void do_foo(HttpRequest& request, HttpResponse& response)
{
foo++;
response.code = 200;
response.print("Foo");
response.content = &message;
message.clear();
message.print("Foo");
}
void do_bar(HttpRequest& request, HttpResponse& response)
{
bar++;
response.code = 201;
response.print("Bar");
response.content = &message;
message.clear();
message.print("Bar");
}
void handle_notFound(HttpRequest& request, HttpResponse& response)