Split WebApplication into WebServer and WebRoot. WebServer inherits from NodeTree, and WebRoot inherits from WebNode. Also removed some of the brynet classes.

This commit is contained in:
Relintai 2022-01-07 20:11:06 +01:00
parent 3133ecdb08
commit a1afe210d1
13 changed files with 112 additions and 458 deletions

View File

@ -1,157 +0,0 @@
#include "bry_request.h"
#include "web_application.h"
void BryRequest::send() {
//if (connection_closed) {
// RequestPool::return_request(this);
// return;
//}
if (http_parser->isKeepAlive()) {
response->setBody(compiled_body);
response->addHeadValue("Connection", "Keep-Alive");
String result = response->getResult();
session->send(result.c_str(), result.size());
} else {
response->setBody(compiled_body);
response->addHeadValue("Connection", "Close");
String result = response->getResult();
HttpSession::Ptr lsession = session;
session->send(result.c_str(), result.size(), [lsession]() { lsession->postShutdown(); });
}
pool();
}
void BryRequest::send_file(const String &p_file_path) {
//if (connection_closed) {
// RequestPool::return_request(this);
// return;
//}
file_path = p_file_path;
FILE *f = fopen(file_path.c_str(), "rb");
if (!f) {
printf("send_file: Error: Download: file doesn't exists! %s\n", file_path.c_str());
return;
}
fseek(f, 0, SEEK_END);
file_size = ftell(f);
fclose(f);
response->addHeadValue("Connection", "Close");
String result = "HTTP/1.1 200 OK\r\nConnection: Close\r\n\r\n";
application->register_request_update(this);
session->send(result.c_str(), result.size(), [this]() { this->_file_chunk_sent(); });
}
void BryRequest::reset() {
Request::reset();
http_parser = nullptr;
session = nullptr;
if (response)
delete response;
response = new ::HttpResponse();
}
String BryRequest::parser_get_path() {
return http_parser->getPath();
}
void BryRequest::update() {
if (file_next) {
file_next = false;
_progress_send_file();
}
}
BryRequest *BryRequest::get() {
return _request_pool.get_request();
}
void BryRequest::pool(BryRequest *request) {
return _request_pool.return_request(request);
}
void BryRequest::pool() {
BryRequest::pool(this);
}
BryRequest::BryRequest() :
Request() {
response = nullptr;
reset();
}
BryRequest::~BryRequest() {
delete response;
}
void BryRequest::_progress_send_file() {
if (connection_closed) {
pool();
return;
}
if (current_file_progress >= file_size) {
session->postShutdown();
pool();
return;
}
FILE *f = fopen(file_path.c_str(), "rb");
if (!f) {
printf("Error: Download: In progress file doesn't exists anymore! %s\n", file_path.c_str());
application->unregister_request_update(this);
session->postShutdown();
pool();
return;
}
fseek(f, current_file_progress, SEEK_SET);
long nfp = current_file_progress + file_chunk_size;
long csize = file_chunk_size;
if (nfp >= file_size) {
csize = (file_size - current_file_progress);
}
body.resize(csize);
fread(&body[0], 1, csize, f);
fclose(f);
current_file_progress = nfp;
session->send(body.c_str(), body.size(), [this]() { this->_file_chunk_sent(); });
}
void BryRequest::_file_chunk_sent() {
file_next = true;
}
RequestPool<BryRequest> BryRequest::_request_pool;

View File

@ -1,50 +0,0 @@
#ifndef BRY_REQUEST_H
#define BRY_REQUEST_H
#include "core/string.h"
#include "core/http/request.h"
#include <mutex>
#include <vector>
#include <brynet/net/http/HttpFormat.hpp>
#include <brynet/net/http/HttpService.hpp>
#include "core/http/handler_instance.h"
class WebApplication;
class BryRequest : public Request {
public:
HTTPParser::Ptr http_parser;
HttpSession::Ptr session;
HttpResponse *response;
void send();
void send_file(const String &p_file_path);
void reset();
String parser_get_path();
void update();
static BryRequest *get();
static void pool(BryRequest *request);
void pool();
BryRequest();
~BryRequest();
protected:
void _progress_send_file();
void _file_chunk_sent();
std::vector<String> _path_stack;
uint32_t _path_stack_pointer;
private:
static RequestPool<BryRequest> _request_pool;
};
#endif

View File

@ -1,133 +0,0 @@
#include "http_server.h"
#include "core/http/web_application.h"
#include "bry_request.h"
#define LOG_VERBOSE 0
void HTTPServer::http_callback_handler(Request *request) {
application->handle_request(request);
}
void HTTPServer::httpEnterCallbackDefault(const HTTPParser &httpParser, const HttpSession::Ptr &session) {
std::unique_lock<std::mutex> lock(_request_map_mutex, std::defer_lock);
BryRequest *request = BryRequest::get();
HttpSession *s = session.get();
lock.lock();
_request_map[s] = request;
lock.unlock();
request->application = application;
request->http_parser = std::make_shared<HTTPParser>(httpParser);
request->session = session;
request->setup_url_stack();
#if LOG_VERBOSE
std::cout << "method:" << http_method_str(static_cast<http_method>(httpParser.method())) << std::endl;
#endif
http_callback_handler(request);
}
void HTTPServer::wsEnterCallbackDefault(const HttpSession::Ptr &httpSession, WebSocketFormat::WebSocketFrameType opcode, const std::string &payload) {
std::cout << "frame enter of type:" << int(opcode) << std::endl;
std::cout << "payload is:" << payload << std::endl;
// echo frame
//auto frame = std::make_shared<std::string>();
//WebSocketFormat::wsFrameBuild(payload.c_str(), payload.size(), *frame, WebSocketFormat::WebSocketFrameType::TEXT_FRAME, true, false);
//httpSession->send(frame);
}
void HTTPServer::closedCallbackDefault(const HttpSession::Ptr &session) {
HttpSession *s = session.get();
std::unique_lock<std::mutex> lock(_request_map_mutex, std::defer_lock);
lock.lock();
Request *r = _request_map[s];
if (r == nullptr) {
lock.unlock();
//printf("Error HTTPServer::closedCallbackDefault: r == nullptr!\n");
return;
}
_request_map.erase(s);
lock.unlock();
r->connection_closed = true;
}
void HTTPServer::configure() {
}
void HTTPServer::initialize() {
if (service)
return;
configure();
service = TcpService::Create();
service->startWorkerThread(threads);
int p_port = port;
//!
if (listenBuilder)
delete listenBuilder;
listenBuilder = new HttpListenerBuilder();
listenBuilder->WithService(service);
listenBuilder->AddSocketProcess([](TcpSocket &socket) {
socket.setNodelay();
socket.setNonblock();
});
listenBuilder->WithAddr(false, "0.0.0.0", p_port);
listenBuilder->WithEnterCallback([this](const HttpSession::Ptr &httpSession, HttpSessionHandlers &handlers) {
handlers.setHttpCallback([this](const HTTPParser &httpParser, const HttpSession::Ptr &session){ this->httpEnterCallbackDefault(httpParser, session); });
handlers.setWSCallback([this](const HttpSession::Ptr &httpSession, WebSocketFormat::WebSocketFrameType opcode, const std::string &payload){ this->wsEnterCallbackDefault(httpSession, opcode, payload); });
handlers.setClosedCallback([this](const HttpSession::Ptr &session){ this->closedCallbackDefault(session); });
});
listenBuilder->asyncRun();
}
void HTTPServer::loop_once() {
application->update();
}
void HTTPServer::main_loop() {
while (true) {
//std::this_thread::sleep_for(std::chrono::seconds(1));
std::this_thread::sleep_for(std::chrono::milliseconds(10));
if (app_kbhit()) {
break;
}
application->update();
}
}
HTTPServer::HTTPServer() {
port = 80;
threads = 4;
listenBuilder = nullptr;
application = nullptr;
}
HTTPServer::~HTTPServer() {
delete listenBuilder;
}

View File

@ -1,50 +0,0 @@
#ifndef HTTP_SERVER_H
#define HTTP_SERVER_H
#include <condition_variable>
#include <iostream>
#include <map>
#include <mutex>
#include <string>
#include <brynet/base/AppStatus.hpp>
#include <brynet/net/http/HttpFormat.hpp>
#include <brynet/net/http/HttpService.hpp>
#include <brynet/net/http/WebSocketFormat.hpp>
#include <brynet/net/wrapper/HttpServiceBuilder.hpp>
#include <brynet/net/wrapper/ServiceBuilder.hpp>
class Request;
class WebApplication;
class HTTPServer {
public:
int port;
int threads;
std::shared_ptr<TcpService> service;
HttpListenerBuilder *listenBuilder;
void http_callback_handler(Request *response);
void httpEnterCallbackDefault(const HTTPParser &httpParser, const HttpSession::Ptr &session);
void wsEnterCallbackDefault(const HttpSession::Ptr &httpSession, WebSocketFormat::WebSocketFrameType opcode, const std::string &payload);
void closedCallbackDefault(const HttpSession::Ptr &session);
virtual void configure();
virtual void initialize();
void loop_once();
void main_loop();
HTTPServer();
virtual ~HTTPServer();
//move this to a sublcass
WebApplication *application;
protected:
std::map<HttpSession *, Request *> _request_map;
std::mutex _request_map_mutex;
};
#endif

View File

@ -1,11 +1,12 @@
#include "request.h"
#include "core/http/cookie.h"
#include "web_application.h"
#include "web_server.h"
#include "http_session.h"
#include "session_manager.h"
#include "core/http/web_root.h"
HTTPSession *Request::get_or_create_session() {
if (session) {
@ -100,12 +101,12 @@ void Request::send_file(const String &p_file_path) {
}
void Request::send_error(int error_code) {
application->send_error(error_code, this);
server->get_web_root()->send_error(error_code, this);
}
void Request::reset() {
session = nullptr;
application = nullptr;
server = nullptr;
current_middleware_index = 0;
middleware_stack = nullptr;
_path_stack.clear();

View File

@ -4,6 +4,7 @@
#include "core/containers/vector.h"
#include "core/string.h"
#include <vector>
#include <map>
#include <mutex>
@ -14,13 +15,13 @@
#include "http_enums.h"
class WebApplication;
class WebServer;
class Cookie;
class HTTPSession;
class Request {
public:
WebApplication *application;
WebServer *server;
uint32_t current_middleware_index;
HandlerInstance handler_instance;

View File

@ -1,4 +1,4 @@
#include "web_application.h"
#include "web_root.h"
#include <functional>
#include <string>
@ -12,23 +12,25 @@
#include <stdio.h>
#include <stdlib.h>
void WebApplication::load_settings() {
#include "core/http/web_server.h"
void WebRoot::load_settings() {
}
void WebApplication::setup_routes() {
default_error_handler_func = WebApplication::default_fallback_error_handler;
void WebRoot::setup_routes() {
default_error_handler_func = WebRoot::default_fallback_error_handler;
error_handler_map[404] = WebApplication::default_404_error_handler;
error_handler_map[404] = WebRoot::default_404_error_handler;
}
void WebApplication::setup_middleware() {
void WebRoot::setup_middleware() {
//If you want sessions add this to your inherited class. Should probably be the first one.
//middlewares.push_back(HandlerInstance(::SessionManager::session_setup_middleware));
middlewares.push_back(HandlerInstance([this](Object *instance, Request *request){ this->default_routing_middleware(instance, request); }));
}
void WebApplication::default_routing_middleware(Object *instance, Request *request) {
void WebRoot::default_routing_middleware(Object *instance, Request *request) {
std::string path = request->get_path_full();
if (FileCache::get_singleton()->wwwroot_has_file(path)) {
@ -63,25 +65,25 @@ void WebApplication::default_routing_middleware(Object *instance, Request *reque
request->next_stage();
}
void WebApplication::default_fallback_error_handler(int error_code, Request *request) {
void WebRoot::default_fallback_error_handler(int error_code, Request *request) {
request->compiled_body = default_generic_error_body;
request->send();
}
void WebApplication::default_404_error_handler(int error_code, Request *request) {
void WebRoot::default_404_error_handler(int error_code, Request *request) {
request->compiled_body = default_error_404_body;
request->send();
}
void WebApplication::handle_request(Request *request) {
void WebRoot::handle_request_main(Request *request) {
request->middleware_stack = &middlewares;
//note that middlewares handle the routing -> WebApplication::default_routing_middleware by default
//note that middlewares handle the routing -> WebRoot::default_routing_middleware by default
request->next_stage();
}
void WebApplication::send_error(int error_code, Request *request) {
void WebRoot::send_error(int error_code, Request *request) {
std::function<void(int, Request *)> func = error_handler_map[error_code];
if (!func) {
@ -92,21 +94,21 @@ void WebApplication::send_error(int error_code, Request *request) {
func(error_code, request);
}
void WebApplication::send_file(const std::string &path, Request *request) {
void WebRoot::send_file(const std::string &path, Request *request) {
std::string fp = FileCache::get_singleton()->wwwroot + path;
request->send_file(fp);
}
void WebApplication::migrate() {
void WebRoot::migrate() {
}
void WebApplication::register_request_update(Request *request) {
void WebRoot::register_request_update(Request *request) {
std::lock_guard<std::mutex> lock(_update_registered_requests_mutex);
_update_registered_requests.push_back(request);
}
void WebApplication::unregister_request_update(Request *request) {
void WebRoot::unregister_request_update(Request *request) {
std::lock_guard<std::mutex> lock(_update_registered_requests_mutex);
std::size_t s = _update_registered_requests.size();
@ -123,7 +125,7 @@ void WebApplication::unregister_request_update(Request *request) {
}
}
void WebApplication::update() {
void WebRoot::update() {
for (std::size_t i = 0; i < _update_registered_requests.size(); ++i) {
Request *r = _update_registered_requests[i];
@ -131,14 +133,19 @@ void WebApplication::update() {
}
}
WebApplication::WebApplication() {
WebServer *WebRoot::get_server() {
//todo this shoult probably be cached
return Object::cast_to<WebServer>(get_tree());
}
WebApplication::~WebApplication() {
WebRoot::WebRoot() : WebNode() {
}
WebRoot::~WebRoot() {
main_route_map.clear();
error_handler_map.clear();
middlewares.clear();
}
std::string WebApplication::default_error_404_body = "<html><body>404 :(</body></html>";
std::string WebApplication::default_generic_error_body = "<html><body>Internal server error! :(</body></html>";
std::string WebRoot::default_error_404_body = "<html><body>404 :(</body></html>";
std::string WebRoot::default_generic_error_body = "<html><body>Internal server error! :(</body></html>";

View File

@ -1,7 +1,7 @@
#ifndef WEB_APPLICATION_H
#define WEB_APPLICATION_H
#ifndef WEB_ROOT_H
#define WEB_ROOT_H
#include "core/object.h"
#include "core/http/web_node.h"
#include <functional>
#include <map>
#include <string>
@ -12,15 +12,16 @@
#include "handler_instance.h"
class Request;
class WebServer;
class WebApplication : public Object {
RCPP_OBJECT(WebApplication, Object);
class WebRoot : public WebNode {
RCPP_OBJECT(WebRoot, WebNode);
public:
static std::string default_error_404_body;
static std::string default_generic_error_body;
void handle_request(Request *request);
void handle_request_main(Request *request);
void send_error(int error_code, Request *request);
void send_file(const std::string &path, Request *request);
@ -39,8 +40,10 @@ public:
void unregister_request_update(Request *request);
void update();
WebApplication();
virtual ~WebApplication();
WebServer *get_server();
WebRoot();
virtual ~WebRoot();
public:
HandlerInstance index_func;

31
core/http/web_server.cpp Normal file
View File

@ -0,0 +1,31 @@
#include "web_server.h"
#include "request.h"
#include "core/http/web_root.h"
WebRoot *WebServer::get_web_root() {
return _web_root;
}
void WebServer::set_root(Node *root) {
WebRoot *web_root = Object::cast_to<WebRoot>(root);
ERR_FAIL_COND(!web_root);
_web_root = web_root;
NodeTree::set_root(root);
}
void WebServer::handle_request(Request *request) {
ERR_FAIL_COND(!_web_root);
_web_root->handle_request_main(request);
}
WebServer::WebServer() {
}
WebServer::~WebServer() {
}

27
core/http/web_server.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef WEB_SERVER_H
#define WEB_SERVER_H
#include "core/nodes/node_tree.h"
class Request;
class WebRoot;
class WebServer : public NodeTree {
RCPP_OBJECT(WebServer, NodeTree);
public:
WebRoot *get_web_root();
void set_root(Node *root);
void handle_request(Request *request);
WebServer();
virtual ~WebServer();
protected:
WebRoot *_web_root;
};
#endif

View File

@ -27,22 +27,6 @@
#include <io.h>
#endif
void DWebApplication::load_settings() {
}
void DWebApplication::setup_routes() {
default_error_handler_func = WebApplication::default_fallback_error_handler;
error_handler_map[404] = WebApplication::default_404_error_handler;
}
void DWebApplication::setup_middleware() {
middlewares.push_back(HandlerInstance([this](Object *instance, Request *request) { this->default_routing_middleware(instance, request); }));
}
void DWebApplication::migrate() {
}
void DWebApplication::add_listener(const std::string &ip, uint16_t port, bool useSSL, const std::string &certFile, const std::string &keyFile, bool useOldTLS, const std::vector<std::pair<std::string, std::string> > &sslConfCmds) {
assert(!_running);
@ -540,7 +524,7 @@ void DWebApplication::on_async_request(const HttpRequestImplPtr &req, std::funct
//callback(resp);
DRequest *request = DRequest::get();
request->application = this;
request->server = this;
request->request = std::shared_ptr<drogon::HttpRequestImpl>(req);
request->callback = callback; //std::move(callback);
@ -656,8 +640,8 @@ void DWebApplication::find_session_for_request(const HttpRequestImplPtr &req) {
//void forward(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback,const std::string &hostString,double timeout);
//void forward(const HttpRequestImplPtr &req,std::function<void(const HttpResponsePtr &)> &&callback,const std::string &hostString,double timeout = 0);
DWebApplication::DWebApplication() :
_listener_manager(new ListenerManager()) {
DWebApplication::DWebApplication() :
_listener_manager(new ListenerManager()), WebServer() {
//staticFileRouterPtr_(new StaticFileRouter{}),
/*
httpCtrlsRouterPtr_(new HttpControllersRouter(*staticFileRouterPtr_,
@ -687,7 +671,4 @@ DWebApplication::DWebApplication() :
}
DWebApplication::~DWebApplication() {
main_route_map.clear();
error_handler_map.clear();
middlewares.clear();
}

View File

@ -1,7 +1,7 @@
#ifndef DWEB_APPLICATION_H
#define DWEB_APPLICATION_H
#include "core/http/web_application.h"
#include "core/http/web_server.h"
#include "core/object.h"
#include <functional>
@ -9,6 +9,7 @@
#include <string>
#include <vector>
#include <memory>
#include <mutex>
#include "core/http/handler_instance.h"
@ -29,16 +30,10 @@ using namespace drogon;
class Request;
class DWebApplication : public WebApplication {
RCPP_OBJECT(DWebApplication, WebApplication);
class DWebApplication : public WebServer {
RCPP_OBJECT(DWebApplication, WebServer);
public:
void load_settings();
void setup_routes();
void setup_middleware();
void migrate();
void add_listener(const std::string &ip, uint16_t port,
bool useSSL = false, const std::string &certFile = "", const std::string &keyFile = "", bool useOldTLS = false,
const std::vector<std::pair<std::string, std::string> > &sslConfCmds = {});
@ -198,7 +193,7 @@ protected:
std::string _home_page_file{ "index.html" };
const std::unique_ptr<ListenerManager> _listener_manager;
std::unique_ptr<SessionManager> _session_manager;
std::unique_ptr<drogon::SessionManager> _session_manager;
bool _enable_server_header{ true };
bool _enable_date_header{ true };

View File

@ -8,8 +8,6 @@
#include <tinydir/tinydir.h>
#include <iostream>
#include "core/http/web_application.h"
void PagedArticle::index(Request *request) {
const String r = request->get_current_path_segment();