Skip to content

Commit

Permalink
Feat: SSE (#158)
Browse files Browse the repository at this point in the history
  • Loading branch information
maddsua authored Feb 11, 2024
1 parent 3be6cab commit fe009b4
Show file tree
Hide file tree
Showing 42 changed files with 371 additions and 114 deletions.
3 changes: 2 additions & 1 deletion core/core.mk
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ include core/polyfill/polyfill.mk
include core/server/server.mk
include core/utils/utils.mk
include core/websocket/websocket.mk
include core/sse/sse.mk

LIB_CORE = core/core.a
LIB_CORE_DEPS = $(LIB_CORE_POLYFILL_DEPS) $(LIB_CORE_HTTP_DEPS) $(LIB_CORE_ENCODING_DEPS) $(LIB_CORE_NETWORK_DEPS) $(LIB_CORE_COMPRESS_DEPS) $(LIB_CORE_SERVER_DEPS) $(LIB_CORE_CRYPTO_DEPS) $(LIB_CORE_HTML_DEPS) $(LIB_CORE_JSON_DEPS) $(LIB_CORE_WEBSOCKET_DEPS) $(LIB_CORE_UTILS_DEPS)
LIB_CORE_DEPS = $(LIB_CORE_POLYFILL_DEPS) $(LIB_CORE_HTTP_DEPS) $(LIB_CORE_ENCODING_DEPS) $(LIB_CORE_NETWORK_DEPS) $(LIB_CORE_COMPRESS_DEPS) $(LIB_CORE_SERVER_DEPS) $(LIB_CORE_CRYPTO_DEPS) $(LIB_CORE_HTML_DEPS) $(LIB_CORE_JSON_DEPS) $(LIB_CORE_WEBSOCKET_DEPS) $(LIB_CORE_UTILS_DEPS) $(LIB_CORE_SSE_DEPS)

# target object
lambda.core: $(LIB_CORE)
Expand Down
2 changes: 1 addition & 1 deletion core/html/html.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ namespace Lambda::HTML {

typedef std::map<std::string, std::string> TemplateProps;
std::string renderTemplate(const std::string& templateSource, const TemplateProps& props);
}
};

#endif
2 changes: 1 addition & 1 deletion core/html/html.mk
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

LIB_CORE_html = core/html.a
LIB_CORE_HTML = core/html.a
LIB_CORE_HTML_PAGES = core/html/resources/servicepage.res
LIB_CORE_HTML_DEPS = core/html/renderer.o core/html/templatemap.o $(LIB_CORE_HTML_PAGES)

Expand Down
36 changes: 28 additions & 8 deletions core/http/body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,54 @@

using namespace Lambda::HTTP;

BodyBuffer::BodyBuffer(const BodyBuffer& other) {
BodyBuffer::BodyBuffer(const BodyBuffer& other) noexcept {
this->m_data = other.m_data;
}

BodyBuffer::BodyBuffer(const char* content) {
BodyBuffer::BodyBuffer(const char* content) noexcept {
if (content == nullptr) return;
this->m_data = std::vector<uint8_t>(content, content + strlen(content));
}

BodyBuffer::BodyBuffer(const std::string& content) {
BodyBuffer::BodyBuffer(const std::string& content) noexcept {
this->m_data = std::vector<uint8_t>(content.begin(), content.end());
}

BodyBuffer::BodyBuffer(const std::vector<uint8_t>& content) {
BodyBuffer::BodyBuffer(const std::vector<uint8_t>& content) noexcept {
this->m_data = content;
}

BodyBuffer::operator std::string () const {
BodyBuffer& BodyBuffer::operator=(const char* content) noexcept {

if (content != nullptr) {
this->m_data = std::vector<uint8_t>(content, content + strlen(content));
}

return *this;
}

BodyBuffer& BodyBuffer::operator=(const std::string& content) noexcept {
this->m_data = std::vector<uint8_t>(content.begin(), content.end());
return *this;
}

BodyBuffer& BodyBuffer::operator=(const std::vector<uint8_t>& content) noexcept {
this->m_data = content;
return *this;
}

BodyBuffer::operator std::string () const noexcept {
return this->text();
}

std::string BodyBuffer::text() const {
std::string BodyBuffer::text() const noexcept {
return std::string(this->m_data.begin(), this->m_data.end());
}

const std::vector<uint8_t>& BodyBuffer::buffer() const {
const std::vector<uint8_t>& BodyBuffer::buffer() const noexcept {
return this->m_data;
}

size_t BodyBuffer::size() const {
size_t BodyBuffer::size() const noexcept {
return this->m_data.size();
}
25 changes: 14 additions & 11 deletions core/http/http.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

#include <vector>
#include <string>
#include <unordered_map>
#include <map>
#include <optional>

Expand All @@ -17,7 +16,7 @@ namespace Lambda::HTTP {
*/
class KVContainer {
protected:
std::unordered_map<std::string, std::vector<std::string>> m_data;
std::map<std::string, std::vector<std::string>> m_data;

public:
KVContainer() = default;
Expand Down Expand Up @@ -87,7 +86,7 @@ namespace Lambda::HTTP {
std::vector<CookieParams> props;
};

std::unordered_map<std::string, std::string> m_data;
std::map<std::string, std::string> m_data;
std::map<std::string, CookieData> m_set_queue;

public:
Expand Down Expand Up @@ -119,27 +118,31 @@ namespace Lambda::HTTP {
* Creates HTTP Body object
*/
BodyBuffer() = default;
BodyBuffer(const BodyBuffer& other);
BodyBuffer(const char* content);
BodyBuffer(const std::string& content);
BodyBuffer(const std::vector<uint8_t>& content);
BodyBuffer(const BodyBuffer& other) noexcept;
BodyBuffer(const char* content) noexcept;
BodyBuffer(const std::string& content) noexcept;
BodyBuffer(const std::vector<uint8_t>& content) noexcept;

operator std::string () const;
BodyBuffer& operator=(const char* content) noexcept;
BodyBuffer& operator=(const std::string& content) noexcept;
BodyBuffer& operator=(const std::vector<uint8_t>& content) noexcept;

operator std::string () const noexcept;

/**
* Returns body text reoresentation
*/
std::string text() const;
std::string text() const noexcept;

/**
* Returns raw byte buffer
*/
const std::vector<uint8_t>& buffer() const;
const std::vector<uint8_t>& buffer() const noexcept;

/**
* Returns body buffer size
*/
size_t size() const;
size_t size() const noexcept;
};

enum struct Methods {
Expand Down
4 changes: 2 additions & 2 deletions core/http/http.mk
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

LIB_CORE_HTTP = core/http.a
LIB_CORE_HTTP_HYPERTEXT_DEPS = core/http/request.o core/http/response.o core/http/cookies.o core/http/kvcontainer.o core/http/url.o core/http/urlsearchparams.o core/http/method.o core/http/status.o core/http/body.o
LIB_CORE_HTTP_TRANSPORT_DEPS = core/http/auth.o core/http/transport_v1.o
LIB_CORE_HTTP_HYPERTEXT_DEPS = core/http/request.o core/http/response.o core/http/cookies.o core/http/kvcontainer.o core/http/url.o core/http/urlsearchparams.o core/http/method.o core/http/status.o core/http/body.o core/http/auth.o
LIB_CORE_HTTP_TRANSPORT_DEPS = core/http/transport_v1.o
LIB_CORE_HTTP_DEPS = $(LIB_CORE_HTTP_HYPERTEXT_DEPS) $(LIB_CORE_HTTP_TRANSPORT_DEPS)

# http stuff
Expand Down
19 changes: 15 additions & 4 deletions core/http/transport.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,12 @@ namespace Lambda::HTTP::Transport {
ProtocolError(const std::string& message, HTTP::Status respondWithStatus) : Error(message), respondStatus(respondWithStatus) {}
};

class V1TransportContext {
struct TransportFlags {
bool forceContentLength = true;
bool autocompress = true;
};

class TransportContextV1 {
private:
Network::TCP::Connection& m_conn;
const TransportOptions& m_topts;
Expand All @@ -52,15 +57,21 @@ namespace Lambda::HTTP::Transport {
ContentEncodings m_compress = ContentEncodings::None;

public:
V1TransportContext(Network::TCP::Connection& connInit, const TransportOptions& optsInit);
TransportContextV1(Network::TCP::Connection& connInit, const TransportOptions& optsInit);

V1TransportContext(const V1TransportContext& other) = delete;
V1TransportContext& operator=(const V1TransportContext& other) = delete;
TransportContextV1(const TransportContextV1& other) = delete;
TransportContextV1& operator=(const TransportContextV1& other) = delete;

const Network::ConnectionInfo& conninfo() const noexcept;
Network::TCP::Connection& getconn() noexcept;
const ContentEncodings& getEnconding() const noexcept;

std::optional<HTTP::Request> nextRequest();
void respond(const HTTP::Response& response);
void reset() noexcept;
bool hasPartialData() const noexcept;

TransportFlags flags;
};
};

Expand Down
63 changes: 41 additions & 22 deletions core/http/transport_v1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,24 @@ static const std::initializer_list<std::string> compressibleTypes = {
"text", "html", "json", "xml"
};

V1TransportContext::V1TransportContext(
const Network::ConnectionInfo& TransportContextV1::conninfo() const noexcept {
return this->m_conn.info();
}

Network::TCP::Connection& TransportContextV1::getconn() noexcept {
return this->m_conn;
}

const ContentEncodings& TransportContextV1::getEnconding() const noexcept {
return this->m_compress;
}

TransportContextV1::TransportContextV1(
Network::TCP::Connection& connInit,
const TransportOptions& optsInit
) : m_conn(connInit), m_topts(optsInit) {}

std::optional<HTTP::Request> V1TransportContext::nextRequest() {
std::optional<HTTP::Request> TransportContextV1::nextRequest() {

auto headerEnded = this->m_readbuff.end();
while (this->m_conn.active() && headerEnded == this->m_readbuff.end()) {
Expand Down Expand Up @@ -175,31 +187,34 @@ std::optional<HTTP::Request> V1TransportContext::nextRequest() {
return next;
}

void V1TransportContext::respond(const Response& response) {
void TransportContextV1::respond(const Response& response) {

auto applyEncoding = ContentEncodings::None;

auto responseHeaders = response.headers;
const auto& contentTypeHeader = responseHeaders.get("content-type");

if (contentTypeHeader.size()) {
if (this->flags.autocompress) {

auto contentTypeNormalized = Strings::toLowerCase(contentTypeHeader);
if (contentTypeHeader.size()) {

// when content type is provided, check if it's a text format,
// so that we won't be trying to compress jpegs and stuff
for (const auto& item : compressibleTypes) {
if (Strings::includes(contentTypeNormalized, item)) {
applyEncoding = this->m_compress;
break;
auto contentTypeNormalized = Strings::toLowerCase(contentTypeHeader);

// when content type is provided, check if it's a text format,
// so that we won't be trying to compress jpegs and stuff
for (const auto& item : compressibleTypes) {
if (Strings::includes(contentTypeNormalized, item)) {
applyEncoding = this->m_compress;
break;
}
}
}

} else {
// set content type in case it's not provided in response
// by default, it's assumed to be a html page. works fine with just text too
responseHeaders.set("content-type", "text/html; charset=utf-8");
applyEncoding = this->m_compress;
} else {
// set content type in case it's not provided in response
// by default, it's assumed to be a html page. works fine with just text too
responseHeaders.set("content-type", "text/html; charset=utf-8");
applyEncoding = this->m_compress;
}
}

std::vector<uint8_t> responseBody;
Expand All @@ -219,16 +234,20 @@ void V1TransportContext::respond(const Response& response) {
} break;

default: {
responseBody = response.body.buffer();
responseBody = std::move(response.body.buffer());
} break;
}

const auto bodySize = responseBody.size();

if (applyEncoding != ContentEncodings::None) {
responseHeaders.set("content-encoding", contentEncodingMap.at(applyEncoding));
}

auto bodySize = responseBody.size();
responseHeaders.set("content-length", std::to_string(bodySize));
if (this->flags.forceContentLength) {
responseHeaders.set("content-length", std::to_string(bodySize));
}

responseHeaders.set("date", Date().toUTCString());
responseHeaders.set("server", "maddsua/lambda");

Expand All @@ -247,10 +266,10 @@ void V1TransportContext::respond(const Response& response) {
if (bodySize) this->m_conn.write(responseBody);
}

void V1TransportContext::reset() noexcept {
void TransportContextV1::reset() noexcept {
this->m_readbuff.clear();
}

bool V1TransportContext::hasPartialData() const noexcept {
bool TransportContextV1::hasPartialData() const noexcept {
return this->m_readbuff.size() > 0;
}
8 changes: 8 additions & 0 deletions core/network/tcp/connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ static const std::initializer_list<int> blockingEndedCodes = {
#endif
};

/*static const std::initializer_list<int> clientDisconnectedCodes = {
#ifdef _WIN32
WSAECONNRESET
#else
ECONNRESET
#endif
};*/

Connection::Connection(
SockHandle handleInit,
const ConnectionInfo& infoInit
Expand Down
Loading

0 comments on commit fe009b4

Please sign in to comment.