Compare commits
2 Commits
master
...
feature/Ur
Author | SHA1 | Date |
---|---|---|
Kenneth Barbour | da788a4860 | |
Kenneth Barbour | 9c2520dcf3 |
|
@ -1,5 +1,5 @@
|
|||
#include "Buffer.h"
|
||||
// a comment
|
||||
|
||||
Buffer::Buffer(uint8_t * ptr, size_t len)
|
||||
: start(ptr), size(len), num(0), w_ptr(ptr), r_ptr(ptr)
|
||||
{}
|
||||
|
|
|
@ -3,17 +3,6 @@
|
|||
|
||||
HttpRequest::HttpRequest(): method(), url(), httpver(), message(), message_length(0) {}
|
||||
|
||||
HttpRequest& HttpRequest::operator=(const HttpRequest& other)
|
||||
{
|
||||
if (&other == this) return *this;
|
||||
this->setMethod(other.getMethod());
|
||||
this->setUrl(other.getUrl());
|
||||
this->setHttpVersion(other.getHttpVersion());
|
||||
this->setMessage(other.getMessage());
|
||||
memcpy(&this->headers, &other.headers, sizeof(HttpHeaders));
|
||||
return *this;
|
||||
}
|
||||
|
||||
const char * HttpRequest::setMethod(const char * method)
|
||||
{
|
||||
strncpy(this->method, method, HTTPREQUEST_METHOD_SIZE);
|
||||
|
@ -38,7 +27,7 @@ const char * HttpRequest::getHttpVersion() const
|
|||
|
||||
const char * HttpRequest::setUrl(const char * url, size_t n)
|
||||
{
|
||||
if (this->url != nullptr) free(this->url);
|
||||
if (this->url) free(this->url);
|
||||
this->url = (char *) malloc(n + 1);
|
||||
strncpy(this->url, url, n+1);
|
||||
return this->url;
|
||||
|
@ -46,13 +35,8 @@ const char * HttpRequest::setUrl(const char * url, size_t n)
|
|||
|
||||
const char * HttpRequest::setUrl(const char * url)
|
||||
{
|
||||
if (url == nullptr) {
|
||||
if (this->url != nullptr) free(this->url);
|
||||
this->url = nullptr;
|
||||
return this->url;
|
||||
}
|
||||
size_t len = strlen(url);
|
||||
return this->setUrl(url, len);
|
||||
size_t len = strlen(url);
|
||||
return this->setUrl(url, len);
|
||||
}
|
||||
|
||||
const char * HttpRequest::getUrl() const
|
||||
|
@ -60,44 +44,34 @@ const char * HttpRequest::getUrl() const
|
|||
return this->url;
|
||||
}
|
||||
|
||||
const char * HttpRequest::setMessage(const char * str)
|
||||
const char * HttpRequest::setMessage(const char * message)
|
||||
{
|
||||
if (str == nullptr) {
|
||||
if (this->message != nullptr) free(this->message);
|
||||
this->message = nullptr;
|
||||
message_length = 0;
|
||||
return this->message;
|
||||
}
|
||||
size_t len = strlen(str);
|
||||
return this->setMessage(str, len);
|
||||
size_t len = strlen(message);
|
||||
return this->setMessage(message, len);
|
||||
}
|
||||
|
||||
const char * HttpRequest::setMessage(const char * str, unsigned int n)
|
||||
const char * HttpRequest::setMessage(const char * message, unsigned int n)
|
||||
{
|
||||
if (this->message == nullptr) {
|
||||
this->message = (char *) malloc(n + 1);
|
||||
} else if (n > this->message_length) {
|
||||
this->message = (char *) realloc(this->message, n + 1);
|
||||
}
|
||||
if (this->message) free(this->message);
|
||||
this->message = (char *) malloc(n + 1);
|
||||
message_length = n;
|
||||
strncpy(this->message, str, n);
|
||||
this->message[n] = '\0';
|
||||
strncpy(this->message, message, n+1);
|
||||
return this->message;
|
||||
}
|
||||
|
||||
const char * HttpRequest::getMessage() const
|
||||
const char * HttpRequest::getMessage()
|
||||
{
|
||||
return this->message;
|
||||
}
|
||||
|
||||
HttpRequest::~HttpRequest()
|
||||
{
|
||||
if (this->url) {
|
||||
free(this->url);
|
||||
this->url = nullptr;
|
||||
if (url) {
|
||||
free(url);
|
||||
url = nullptr;
|
||||
}
|
||||
if (this->message != nullptr) {
|
||||
free(this->message);
|
||||
this->message = nullptr;
|
||||
if (message) {
|
||||
free(message);
|
||||
url = nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,9 +28,8 @@ class HttpRequest
|
|||
const char * getHttpVersion() const;
|
||||
const char * setMessage(const char *);
|
||||
const char * setMessage(const char *, unsigned int);
|
||||
const char * getMessage() const;
|
||||
const char * getMessage();
|
||||
unsigned int getMessageLength() { return message_length; };
|
||||
HttpRequest& operator=(const HttpRequest& other);
|
||||
char method [HTTPREQUEST_METHOD_SIZE];
|
||||
char * url;
|
||||
char httpver [HTTPREQUEST_HTTPVER_SIZE]; // TODO: private
|
||||
|
|
|
@ -3,17 +3,17 @@
|
|||
/**
|
||||
* TODO: this is the only constructor really needed unless _TEST_
|
||||
*/
|
||||
HttpResponse::HttpResponse(Stream& buffer):
|
||||
content(&buffer),
|
||||
code(200),
|
||||
reason(),
|
||||
httpver()
|
||||
HttpResponse::HttpResponse(Stream& buffer):
|
||||
content(&buffer),
|
||||
code(200),
|
||||
reason(),
|
||||
httpver()
|
||||
{};
|
||||
|
||||
HttpResponse::HttpResponse():
|
||||
code(200),
|
||||
HttpResponse::HttpResponse():
|
||||
code(200),
|
||||
reason(),
|
||||
httpver()
|
||||
httpver()
|
||||
{};
|
||||
|
||||
|
||||
|
@ -21,7 +21,7 @@ const char * HttpResponse::setReason(const char * reason)
|
|||
{
|
||||
if (this->reason != nullptr) free(this->reason);
|
||||
if (reason == nullptr) return this->reason = nullptr;
|
||||
this->reason = (char *) malloc(strlen(reason) + 1);
|
||||
this->reason = (char *) malloc(strlen(reason));
|
||||
strcpy(this->reason, reason);
|
||||
|
||||
return this->reason;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
QueryString::QueryString(const char* query) : n(0)
|
||||
{
|
||||
if (query[0] == '\0') return;
|
||||
if (query == nullptr || query[0] == '\0') return;
|
||||
|
||||
// create buffer
|
||||
buffer_length = urlenc::decoded_length(query) + 2;
|
||||
|
@ -116,6 +116,8 @@ size_t QueryString::str_count_fields(const char* query)
|
|||
|
||||
QueryString::~QueryString()
|
||||
{
|
||||
free(buffer);
|
||||
free(fields);
|
||||
if (n) {
|
||||
free(buffer);
|
||||
free(fields);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,92 +0,0 @@
|
|||
#include "ResponseParser.h"
|
||||
|
||||
void ResponseParser::reset() {
|
||||
_state = S_IN_HTTPVER;
|
||||
_i = _buffer;
|
||||
}
|
||||
|
||||
bool ResponseParser::parse() {
|
||||
char in;
|
||||
while (server.available() && _state != S_ERROR) {
|
||||
switch (_state) {
|
||||
case S_IN_HTTPVER:
|
||||
in = server.read();
|
||||
if (in == ' ') {
|
||||
*(_i++) = '\0';
|
||||
response.setHttpVersion(_buffer);
|
||||
_i = _buffer;
|
||||
_state = S_IN_CODE;
|
||||
break;
|
||||
}
|
||||
*(_i++) = in;
|
||||
break;
|
||||
case S_IN_CODE:
|
||||
in = server.read();
|
||||
// skip preceding whitespace
|
||||
if (in == ' ') {
|
||||
if (_i == _buffer) continue;
|
||||
*(_i) = '\0';
|
||||
response.code = atoi(_buffer);
|
||||
_i = _buffer;
|
||||
_state = S_IN_REASON;
|
||||
break;
|
||||
}
|
||||
*(_i++) = in;
|
||||
break;
|
||||
case S_IN_REASON:
|
||||
in = server.read();
|
||||
if (in == '\r') continue;
|
||||
if (in == '\n') {
|
||||
*(_i) = '\0';
|
||||
response.setReason(_buffer);
|
||||
_i = _buffer;
|
||||
_state = S_IN_HEADER;
|
||||
break;
|
||||
}
|
||||
*(_i++) = in;
|
||||
break;
|
||||
case S_IN_HEADER:
|
||||
in = server.read();
|
||||
if (in == '\r') continue;
|
||||
if (in == '\n') {
|
||||
if (_i == _buffer) {
|
||||
_state = S_IN_MESSAGE;
|
||||
_i = _buffer;
|
||||
break;
|
||||
}
|
||||
*(_i) = '\0';
|
||||
char * name = _buffer;
|
||||
char * value = _buffer;
|
||||
bool s = 0;
|
||||
while (value < _i) {
|
||||
if (s) {
|
||||
if (*value == ' ') value++;
|
||||
else break;
|
||||
} else {
|
||||
if (*value == ':') {
|
||||
s = true;
|
||||
*(value++) = '\0';
|
||||
} else value++;
|
||||
}
|
||||
}
|
||||
response.headers.set(name, value);
|
||||
_i = _buffer;
|
||||
break;
|
||||
}
|
||||
*(_i++) = in;
|
||||
break;
|
||||
case S_IN_MESSAGE:
|
||||
while (server.available()) {
|
||||
response.content->write(server.read());
|
||||
}
|
||||
_state = S_COMPLETE;
|
||||
case S_COMPLETE:
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
_state = S_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return (_state == S_COMPLETE || _state == S_ERROR);
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
#pragma once
|
||||
#include "HttpResponse.h"
|
||||
#include "Arduino.h"
|
||||
#include "Stream.h"
|
||||
|
||||
#ifndef RESPONSEPARSER_BUFFER
|
||||
#define RESPONSEPARSER_BUFFER 512
|
||||
#endif
|
||||
|
||||
enum ResponseParserState {
|
||||
S_IN_HTTPVER,
|
||||
S_IN_CODE,
|
||||
S_IN_REASON,
|
||||
S_IN_HEADER,
|
||||
S_IN_MESSAGE,
|
||||
S_COMPLETE,
|
||||
S_ERROR
|
||||
};
|
||||
|
||||
class ResponseParser
|
||||
{
|
||||
public:
|
||||
ResponseParser(HttpResponse& res, Stream& server):
|
||||
response(res),
|
||||
server(server),
|
||||
_state(S_IN_HTTPVER)
|
||||
{};
|
||||
|
||||
bool parse();
|
||||
bool error() { return _state == S_ERROR; };
|
||||
void reset();
|
||||
|
||||
|
||||
private:
|
||||
char _buffer[RESPONSEPARSER_BUFFER] = {};
|
||||
char * _i = _buffer;
|
||||
HttpResponse& response;
|
||||
Stream& server;
|
||||
ResponseParserState _state;
|
||||
};
|
|
@ -17,8 +17,6 @@ size_t Print::print(int i)
|
|||
i = (unsigned int) i << 1;
|
||||
i = (unsigned int) i >> 1;
|
||||
len += printNumber(i, 10);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t Print::print(const Printable& x)
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
class WiFiServer
|
||||
{
|
||||
public:
|
||||
WiFiServer(uint16_t port) : port(port), _next(nullptr) {}
|
||||
WiFiServer(uint16_t port) : port(port) {}
|
||||
WiFiClient available() {
|
||||
if (!_next) return WiFiClient();
|
||||
const char * client = _next;
|
||||
|
|
|
@ -122,8 +122,6 @@ TEST_CASE("Buffer is a Stream","[Buffer][Stream]")
|
|||
|
||||
buffer->write("Foo");
|
||||
|
||||
delete buffer;
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE("Test clear","[Buffer]")
|
||||
|
|
|
@ -101,7 +101,7 @@ TEST_CASE("Copy constructor", "[HttpHeaders]")
|
|||
TEST_CASE("HttpHeaders printTo", "[HttpHeaders]")
|
||||
{
|
||||
HttpHeaders h;
|
||||
uint8_t buff[100] = {};
|
||||
uint8_t buff[100];
|
||||
Buffer buffer(buff, 100);
|
||||
|
||||
buffer.print(h);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include "DummyStream.h"
|
||||
|
||||
using Catch::Matchers::Equals;
|
||||
|
||||
|
||||
|
||||
TEST_CASE("Test get/set method","[HttpRequest]")
|
||||
{
|
||||
|
@ -20,22 +20,6 @@ TEST_CASE("Test get/set url","[HttpRequest]")
|
|||
CHECK_THAT(req.getUrl(), Equals("/foo"));
|
||||
}
|
||||
|
||||
TEST_CASE("Set url to nullptr", "[HttpRequest]")
|
||||
{
|
||||
HttpRequest req;
|
||||
req.setUrl(nullptr);
|
||||
bool isnull = (req.getUrl() == nullptr);
|
||||
CHECK(isnull);
|
||||
}
|
||||
|
||||
TEST_CASE("Set url multiple times", "[HttpRequest][HttpRequest::setUrl]")
|
||||
{
|
||||
HttpRequest req;
|
||||
req.setUrl("/foo");
|
||||
req.setUrl("/barbaz");
|
||||
CHECK_THAT(req.getUrl(), Equals("/barbaz"));
|
||||
}
|
||||
|
||||
TEST_CASE("Test get/set short url", "[HttpRequest]")
|
||||
{
|
||||
HttpRequest req;
|
||||
|
@ -51,52 +35,12 @@ TEST_CASE("Test get/set message","[HttpRequest]")
|
|||
CHECK(req.getMessageLength() == 9);
|
||||
}
|
||||
|
||||
TEST_CASE("HttpRequest empty reassignment", "[HttpRequest][HttpRequest-reassign]")
|
||||
TEST_CASE("HttpRequest reassignment", "[HttpRequest]")
|
||||
{
|
||||
HttpRequest req;
|
||||
req.setUrl("/");
|
||||
req.setMethod("GET");
|
||||
|
||||
req = HttpRequest();
|
||||
bool isnull = (req.getUrl() == nullptr);
|
||||
CHECK(isnull);
|
||||
}
|
||||
|
||||
TEST_CASE("HttpRequest reassignment", "[HttpRequest][HttpRequest-reassign]")
|
||||
{
|
||||
HttpRequest req;
|
||||
req.setUrl("/foo/bar");
|
||||
req.setMethod("POST");
|
||||
req.setMessage("foo=bar&baz=qux");
|
||||
req.headers.set("Accept","*/*");
|
||||
|
||||
HttpRequest req2;
|
||||
req2.setUrl("/not/foo");
|
||||
req2.setMethod("GET");
|
||||
req2.headers.set("Content-Type","bar");
|
||||
req2 = req;
|
||||
CHECK_THAT(req2.getMethod(), Equals("POST"));
|
||||
CHECK_THAT(req2.getMessage(), Equals("foo=bar&baz=qux"));
|
||||
CHECK_THAT(req2.getUrl(), Equals("/foo/bar"));
|
||||
CHECK(req2.headers.has("Accept"));
|
||||
CHECK(!req2.headers.has("Content-Type"));
|
||||
CHECK_THAT(req2.headers.get("Accept"), Equals("*/*"));
|
||||
}
|
||||
|
||||
TEST_CASE("Set message multiple times", "[HttpRequest]")
|
||||
{
|
||||
HttpRequest req;
|
||||
|
||||
req.setMessage("foo=bar");
|
||||
CHECK_THAT(req.getMessage(), Equals("foo=bar"));
|
||||
|
||||
req.setMessage("foo=bar&baz");
|
||||
CHECK_THAT(req.getMessage(), Equals("foo=bar&baz"));
|
||||
|
||||
req.setMessage("");
|
||||
CHECK_THAT(req.getMessage(), Equals(""));
|
||||
|
||||
req.setMessage(nullptr);
|
||||
bool isNull = (req.getMessage() == nullptr);
|
||||
CHECK(isNull);
|
||||
CHECK(req.getUrl() == nullptr);
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ TEST_CASE("Unset reason", "[HttpResponse]")
|
|||
TEST_CASE("HttpResponse send", "[HttpResponse]")
|
||||
{
|
||||
uint8_t response_buffer[100] = "AAAABBBBCCCCDDDDEEEE";
|
||||
uint8_t print_buffer[100] = {};
|
||||
uint8_t print_buffer[100];
|
||||
Buffer message(response_buffer, 100);
|
||||
Buffer client(print_buffer, 100);
|
||||
HttpResponse r(message);
|
||||
|
|
|
@ -91,3 +91,15 @@ TEST_CASE("str_count_fields", "[QueryString][str_count_fields]")
|
|||
CHECK(QueryString::str_count_fields("foo=bar&baz=qux") == 2);
|
||||
CHECK(QueryString::str_count_fields("foo&bar&foo&bar") == 4);
|
||||
}
|
||||
|
||||
TEST_CASE("empty string", "[QueryString][QueryString-empty]")
|
||||
{
|
||||
QueryString qs("");
|
||||
CHECK(qs.count() == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("constructor with nullptr", "[QueryString-nullptr]")
|
||||
{
|
||||
QueryString qs(nullptr);
|
||||
CHECK(qs.count() == 0);
|
||||
}
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
#include "catch.hpp"
|
||||
#include "ResponseParser.h"
|
||||
#include <HttpResponse.h>
|
||||
#include <Buffer.h>
|
||||
|
||||
using Catch::Matchers::Equals;
|
||||
|
||||
TEST_CASE("Test parsing a response with headers and content")
|
||||
{
|
||||
uint8_t _reqbuff[100];
|
||||
Buffer server(_reqbuff, 100);
|
||||
uint8_t _resbuff[100];
|
||||
Buffer buffer(_resbuff, 100);
|
||||
HttpResponse response;
|
||||
ResponseParser parser(response, server);
|
||||
|
||||
response.content = &buffer;
|
||||
|
||||
server.print("HTTP/1.0 200 OK\r\nCookie: foo=bar; baz=qux;\r\nContent-Length:10\r\n\r\nABCDEFGHIJ");
|
||||
|
||||
bool result = parser.parse();
|
||||
|
||||
CHECK_THAT(response.getHttpVersion(), Equals("HTTP/1.0"));
|
||||
CHECK(response.code == 200);
|
||||
CHECK_THAT(response.getReason(), Equals("OK"));
|
||||
|
||||
CHECK(response.headers.count() == 2);
|
||||
CHECK(response.headers.has("Cookie") == true);
|
||||
CHECK_THAT(response.headers.get("Cookie"), Equals("foo=bar; baz=qux;"));
|
||||
CHECK(response.headers.has("Content-Length") == true);
|
||||
CHECK_THAT(response.headers.get("Content-Length"), Equals("10"));
|
||||
CHECK_THAT((char*)_resbuff, Equals("ABCDEFGHIJ"));
|
||||
|
||||
}
|
Loading…
Reference in New Issue