Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions src/HttpContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
#include "HttpResponseData.h"
#include "AsyncSocket.h"
#include "WebSocketData.h"
#include "Log.h"

#include <string_view>
#include <iostream>
#include "f2/function2.hpp"

namespace uWS {
Expand Down Expand Up @@ -155,9 +155,13 @@ struct HttpContext {
httpContextData->router.getUserData() = {(HttpResponse<SSL> *) s, httpRequest};
if (!httpContextData->router.route(httpRequest->getMethod(), httpRequest->getUrl())) {
/* We have to force close this socket as we have no handler for it */
UWS_LOG_REQUEST(1, "No handler for route ", httpRequest->getMethod(), " ", httpRequest->getUrl());
us_socket_close(SSL, (us_socket_t *) s, 0, nullptr);
return nullptr;
}
else {
UWS_LOG_REQUEST(3, "Successfully handled route ", httpRequest->getMethod(), " ", httpRequest->getUrl());
}

/* First of all we need to check if this socket was deleted due to upgrade */
if (httpContextData->upgradedWebSocket) {
Expand All @@ -177,8 +181,7 @@ struct HttpContext {

/* Returning from a request handler without responding or attaching an onAborted handler is ill-use */
if (!((HttpResponse<SSL> *) s)->hasResponded() && !httpResponseData->onAborted) {
/* Throw exception here? */
std::cerr << "Error: Returning from a request handler without responding or attaching an abort handler is forbidden!" << std::endl;
UWS_LOG_REQUEST(0, "Error: Returning from a request handler without responding or attaching an abort handler is forbidden!");
std::terminate();
}

Expand Down
72 changes: 72 additions & 0 deletions src/Log.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#ifndef UWS_LOG_H
#define UWS_LOG_H
#include <array>
#include <functional>
#include <iostream>
#include <string_view>

#define UWS_LOG_LEVEL 0 // override this to get more verbose logging

namespace uWS {

/*!
* \brief Log a message. The user of this lib is free to override this function object with a custom logger.
* \param [in] message The message to be logged.
* \param [in] logLevel The severity of the message. 0 is error, 1 is warning, 2 is info. With each increment the severity decrements.
*/
typedef std::function<void(std::string_view message, int logLevel)> LogFunction;

inline LogFunction log = [](std::string_view message, int logLevel) -> void {
if(logLevel <= 1) {
std::cerr << message << std::endl;
}
else {
std::cout << message << std::endl;
}
};

class LogBuffer
{
private:
std::array<char,1024> buf{0};
size_t cursor = 0;

LogBuffer& operator<< (std::string_view sv) {
const size_t bytesFree = buf.size() - cursor;
if(sv.size() > bytesFree)
throw std::length_error("log message too long");
memcpy(&buf[cursor], sv.data(), sv.size());
cursor += sv.size();
return *this;
}

public:
template <typename T>
void put(T msg) {
*this << msg;
}
template <typename T, typename... Ts>
void put(T t, Ts... ts) {
put(t);
put(ts...);
}
std::string_view get() {
std::string_view ret(buf.data(), cursor);
cursor = 0;
return ret;
}
};

thread_local LogBuffer logBuffer;

#define UWS_LOG_REQUEST(loglevel, ...) { \
if constexpr(loglevel <= UWS_LOG_LEVEL) { \
::uWS::logBuffer.put(__VA_ARGS__); \
::uWS::log(::uWS::logBuffer.get(), loglevel); \
} \
}

} // namespace uWS

#endif // UWS_LOG_H