HttpResponse has a send() method and expects to be assigned a Stream containing the message
parent
fd1019e1fa
commit
be794a9cd8
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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];
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]")
|
||||
|
|
|
@ -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 }
|
||||
};
|
||||
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue