diff --git a/15.pro b/15.pro index 5154b82..e273920 100644 --- a/15.pro +++ b/15.pro @@ -13,11 +13,12 @@ SOURCES += \ uSockets/src/loop.c HEADERS += \ - src/Http.h \ src/uWS.h \ src/HttpRouter.h \ src/Loop.h \ - src/App.h + src/App.h \ + src/HttpRequest.h \ + src/HttpSocket.h INCLUDEPATH += uSockets/src src #QMAKE_CXXFLAGS += -fsanitize=address diff --git a/main.cpp b/main.cpp index 950d059..0de0a4a 100644 --- a/main.cpp +++ b/main.cpp @@ -22,7 +22,15 @@ int main() { app.onGet("/", [](auto *s, auto *req, auto *args) { - s->writeStatus("200 OK")->writeHeader("Hello", "World")->end(buffer); + // this one is simple and okay for small sends + /*s->writeStatus("200 OK") + ->writeHeader("Server", "uWebSockets") + ->end(buffer);*/ + + // for large sends you want a stream! + s->writeStatus("200 OK")->write([](int offset) { + return std::string_view(buffer.data() + offset, buffer.length() - offset); + }, buffer.length()); }).onWebSocket("/wsApi", []() { diff --git a/src/App.h b/src/App.h index eb699bb..ad7d036 100644 --- a/src/App.h +++ b/src/App.h @@ -4,8 +4,9 @@ #include "libusockets.h" #include #include "Loop.h" -#include "Http.h" +#include "HttpSocket.h" #include "HttpRouter.h" +#include "HttpRequest.h" namespace uWS { diff --git a/src/HttpRequest.h b/src/HttpRequest.h new file mode 100644 index 0000000..fbc0525 --- /dev/null +++ b/src/HttpRequest.h @@ -0,0 +1,68 @@ +#ifndef HTTPREQUEST_H +#define HTTPREQUEST_H + +// holds the header pointers and wrappers +struct HttpRequest { + + struct Header { + char *key, *value; + unsigned int keyLength, valueLength; + }; + + #define MAX_HEADERS 100 + Header headers[MAX_HEADERS]; + + // UNSAFETY NOTE: assumes *end == '\r' (might unref end pointer) + char *getHeaders(char *buffer, char *end, struct Header *headers, size_t maxHeaders) { + for (unsigned int i = 0; i < maxHeaders; i++) { + for (headers->key = buffer; (*buffer != ':') & (*buffer > 32); *(buffer++) |= 32); + if (*buffer == '\r') { + if ((buffer != end) & (buffer[1] == '\n') & (i > 0)) { + headers->key = 0; + return buffer + 2; + } else { + return 0; + } + } else { + headers->keyLength = (unsigned int) (buffer - headers->key); + for (buffer++; (*buffer == ':' || *buffer < 33) && *buffer != '\r'; buffer++); + headers->value = buffer; + buffer = (char *) memchr(buffer, '\r', end - buffer); //for (; *buffer != '\r'; buffer++); + if (buffer /*!= end*/ && buffer[1] == '\n') { + headers->valueLength = (unsigned int) (buffer - headers->value); + buffer += 2; + headers++; + } else { + return 0; + } + } + } + return 0; + } + + std::string_view url; + + HttpRequest(char *data, int length) { + // parse the shit + data[length] = '\r'; + + if (getHeaders(data, data + length, headers, MAX_HEADERS)) { + + headers->valueLength = std::max(0, headers->valueLength - 9); + + // headers should really just be string_view from the start! + url = std::string_view(headers[0].value, headers[0].valueLength); + } + } + + std::string_view getUrl() { + return url; + } + + bool isComplete() { + return url.length(); + } + +}; + +#endif // HTTPREQUEST_H diff --git a/src/Http.h b/src/HttpSocket.h similarity index 63% rename from src/Http.h rename to src/HttpSocket.h index 4485e9d..f67a067 100644 --- a/src/Http.h +++ b/src/HttpSocket.h @@ -6,71 +6,6 @@ #include #include -// holds the header pointers and wrappers -struct HttpRequest { - - struct Header { - char *key, *value; - unsigned int keyLength, valueLength; - }; - - #define MAX_HEADERS 100 - Header headers[MAX_HEADERS]; - - // UNSAFETY NOTE: assumes *end == '\r' (might unref end pointer) - char *getHeaders(char *buffer, char *end, struct Header *headers, size_t maxHeaders) { - for (unsigned int i = 0; i < maxHeaders; i++) { - for (headers->key = buffer; (*buffer != ':') & (*buffer > 32); *(buffer++) |= 32); - if (*buffer == '\r') { - if ((buffer != end) & (buffer[1] == '\n') & (i > 0)) { - headers->key = 0; - return buffer + 2; - } else { - return 0; - } - } else { - headers->keyLength = (unsigned int) (buffer - headers->key); - for (buffer++; (*buffer == ':' || *buffer < 33) && *buffer != '\r'; buffer++); - headers->value = buffer; - buffer = (char *) memchr(buffer, '\r', end - buffer); //for (; *buffer != '\r'; buffer++); - if (buffer /*!= end*/ && buffer[1] == '\n') { - headers->valueLength = (unsigned int) (buffer - headers->value); - buffer += 2; - headers++; - } else { - return 0; - } - } - } - return 0; - } - - std::string_view url; - - HttpRequest(char *data, int length) { - // parse the shit - data[length] = '\r'; - - if (getHeaders(data, data + length, headers, MAX_HEADERS)) { - - headers->valueLength = std::max(0, headers->valueLength - 9); - - // headers should really just be string_view from the start! - url = std::string_view(headers[0].value, headers[0].valueLength); - } - } - - std::string_view getUrl() { - return url; - } - - bool isComplete() { - return url.length(); - } - -}; - - // HttpSocket is an alias for us_socket template struct HttpSocket { @@ -160,6 +95,13 @@ struct HttpSocket { writeToCorkBufferAndReset(data.data(), data.length()); } + // stream out (todo: fix up large sends and benchmark it again) + void write(std::function cb, int length) { + std::string_view chunk = cb(0); + + writeToCorkBufferAndReset(chunk.data(), chunk.length()); + } + // can't create this! HttpSocket() = delete; diff --git a/uSockets b/uSockets index 88ff2b1..834ac39 160000 --- a/uSockets +++ b/uSockets @@ -1 +1 @@ -Subproject commit 88ff2b1f35af8e8633cc410c2413dc631bf38ca6 +Subproject commit 834ac39aa313efe9e6cefb5c90dca2cd0cc2d0e8