parent
9a7eece05e
commit
a697e0db12
4 changed files with 217 additions and 0 deletions
@ -0,0 +1,80 @@ |
|||||||
|
#include "http_packet.h" |
||||||
|
namespace Bk::Net { |
||||||
|
HttpRequest::HttpRequest(std::string method, |
||||||
|
std::string url, |
||||||
|
std::string version, |
||||||
|
HttpParams params, |
||||||
|
std::string body)
|
||||||
|
: method(method), url(url), version(version), params(params), body(body) {} |
||||||
|
|
||||||
|
HttpRequest::HttpRequest(std::string data) |
||||||
|
{ |
||||||
|
auto lines = Tools::string_split(data, "\n"); |
||||||
|
auto first_line = std::string(lines->at(0)); |
||||||
|
auto req_data = Tools::string_split(first_line, " "); |
||||||
|
method = req_data->at(0); |
||||||
|
url = req_data->at(1); |
||||||
|
version = req_data->at(2); |
||||||
|
body = std::string(lines->at(lines->size() - 1)); |
||||||
|
|
||||||
|
lines->erase(lines->begin()); |
||||||
|
lines->erase(lines->end()); |
||||||
|
|
||||||
|
for (auto line : *lines) |
||||||
|
{ |
||||||
|
auto param = Tools::string_split(line, ":", 1); |
||||||
|
if (param->size() >= 2)
|
||||||
|
{ |
||||||
|
Tools::string_trim(param->at(1)); |
||||||
|
params.insert({param->at(0), param->at(1)}); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
std::string HttpRequest::to_string() |
||||||
|
{ |
||||||
|
std::string request = ""; |
||||||
|
request += method + " " + url + " " + version + "\r\n"; |
||||||
|
std::string param_order[] =
|
||||||
|
{ |
||||||
|
"Host", |
||||||
|
"User-Agent", |
||||||
|
"Accept", |
||||||
|
"Accept-Language", |
||||||
|
"Accept-Encoding", |
||||||
|
"Connection", |
||||||
|
"Upgrade-Insecure-Requests", |
||||||
|
"Sec-Fetch-Dest", |
||||||
|
"Sec-Fetch-Mode", |
||||||
|
"Sec-Fetch-Site" |
||||||
|
}; |
||||||
|
if (params.size()) for ( const auto& param : param_order) if (params[param].length()) request += param + ": " + params[param] + "\r\n"; |
||||||
|
request += "\r\n"; |
||||||
|
if (body.length()) request += body; |
||||||
|
return request; |
||||||
|
} |
||||||
|
|
||||||
|
HttpReponse::HttpReponse(std::string status, |
||||||
|
std::string version, |
||||||
|
HttpParams params, |
||||||
|
std::string body) |
||||||
|
: status(status), version(version), params(params), body(body) {} |
||||||
|
|
||||||
|
HttpReponse::HttpReponse(std::string data) |
||||||
|
{ |
||||||
|
status = ""; |
||||||
|
version = ""; |
||||||
|
params = HttpParams(0); |
||||||
|
body = ""; |
||||||
|
} |
||||||
|
|
||||||
|
std::string HttpReponse::to_string() |
||||||
|
{ |
||||||
|
std::string reponse = ""; |
||||||
|
reponse = version + " " + status + " \r\n"; |
||||||
|
if (params.size()) for ( const auto& pair : params) reponse += pair.first + ": " + pair.second + " \r\n"; |
||||||
|
reponse += "\r\n"; |
||||||
|
if (body.length()) reponse += body; |
||||||
|
return reponse; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,59 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include <bakanetpch.h> |
||||||
|
#include <bakanet/tools/string_tools.h> |
||||||
|
|
||||||
|
#define HTTP_RES_200 "200 OK" |
||||||
|
|
||||||
|
#define HTTP_RES_303 "303 See Other" |
||||||
|
|
||||||
|
#define HTTP_RES_400 "400 Bad Request" |
||||||
|
#define HTTP_RES_401 "401 Unauthorized" |
||||||
|
#define HTTP_RES_402 "402 Payment Required" |
||||||
|
#define HTTP_RES_403 "403 Forbidden" |
||||||
|
#define HTTP_RES_404 "404 Not Found" |
||||||
|
#define HTTP_RES_405 "405 Method Not Allowed" |
||||||
|
#define HTTP_RES_406 "406 Not Acceptable" |
||||||
|
#define HTTP_RES_408 "408 Request Timeout" |
||||||
|
|
||||||
|
namespace Bk::Net { |
||||||
|
using HttpParams = std::unordered_map<std::string, std::string>; |
||||||
|
|
||||||
|
class HttpRequest
|
||||||
|
{ |
||||||
|
public: |
||||||
|
HttpRequest(std::string method,
|
||||||
|
std::string url, |
||||||
|
std::string version, |
||||||
|
HttpParams params = HttpParams(0), |
||||||
|
std::string body = ""); |
||||||
|
|
||||||
|
HttpRequest(std::string data); |
||||||
|
|
||||||
|
std::string to_string(); |
||||||
|
|
||||||
|
std::string method; |
||||||
|
std::string url; |
||||||
|
std::string version; |
||||||
|
HttpParams params; |
||||||
|
std::string body; |
||||||
|
}; |
||||||
|
|
||||||
|
class HttpReponse |
||||||
|
{ |
||||||
|
public: |
||||||
|
HttpReponse(std::string status, |
||||||
|
std::string version, |
||||||
|
HttpParams params = HttpParams(0), |
||||||
|
std::string body = ""); |
||||||
|
|
||||||
|
HttpReponse(std::string data); |
||||||
|
|
||||||
|
std::string to_string(); |
||||||
|
|
||||||
|
std::string status; |
||||||
|
std::string version; |
||||||
|
HttpParams params; |
||||||
|
std::string body; |
||||||
|
}; |
||||||
|
} |
@ -0,0 +1,52 @@ |
|||||||
|
#include "http_server.h" |
||||||
|
namespace Bk::Net { |
||||||
|
HttpServer::HttpServer(IpAddress ip, int port)
|
||||||
|
{ |
||||||
|
socket = Socket::create(ip, port, IpProtocol::TCP); |
||||||
|
} |
||||||
|
|
||||||
|
void HttpServer::start() |
||||||
|
{ |
||||||
|
bool running = socket->init() && socket->start(5); |
||||||
|
while (running) |
||||||
|
{ |
||||||
|
log("BEFORE") |
||||||
|
Connection conn = socket->ack(); |
||||||
|
if(conn >= 0) |
||||||
|
{ |
||||||
|
log("AFTER") |
||||||
|
route_request(conn, recv_request(conn)); |
||||||
|
close(conn); |
||||||
|
} |
||||||
|
|
||||||
|
}
|
||||||
|
} |
||||||
|
|
||||||
|
HttpRequest HttpServer::recv_request(Connection conn) |
||||||
|
{ |
||||||
|
Packet req; |
||||||
|
bool reading = true; |
||||||
|
while(reading) |
||||||
|
{ |
||||||
|
auto data = socket->obtain(conn, 4); |
||||||
|
log("SIZE " << data.size()) |
||||||
|
reading = req.append_data(data); |
||||||
|
} |
||||||
|
int req_size = req.size(); |
||||||
|
if (req_size) return HttpRequest(std::string(req.pull<char>(req_size).release(), req_size)); |
||||||
|
return HttpRequest("", "", ""); |
||||||
|
} |
||||||
|
|
||||||
|
void HttpServer::send_reponse(Connection conn, HttpReponse res) |
||||||
|
{ |
||||||
|
Packet res_packet; |
||||||
|
std::string str_res = res.to_string(); |
||||||
|
res_packet.push<char>(str_res.c_str(), str_res.length()); |
||||||
|
socket->emit(conn, res_packet.payload); |
||||||
|
} |
||||||
|
|
||||||
|
void HttpServer::route_request(Connection conn, HttpRequest req) |
||||||
|
{ |
||||||
|
if(req_mapper[req.url]) send_reponse(conn, req_mapper[req.url](req)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include <bakanetpch.h> |
||||||
|
#include <bakanet/sock_layer/ip_address.h> |
||||||
|
#include <bakanet/sock_layer/packet.h> |
||||||
|
#include <bakanet/sock_layer/socket.h> |
||||||
|
#include "http_packet.h" |
||||||
|
|
||||||
|
namespace Bk::Net { |
||||||
|
class HttpServer
|
||||||
|
{ |
||||||
|
using RequestHandler = std::function<HttpReponse(HttpRequest& req)>; |
||||||
|
public: |
||||||
|
HttpServer(IpAddress ip, int port); |
||||||
|
~HttpServer() = default; |
||||||
|
void start(); |
||||||
|
void get(std::string url, RequestHandler req_handler) { req_mapper.insert({ url, req_handler }); } |
||||||
|
private: |
||||||
|
std::unique_ptr<Socket> socket; |
||||||
|
std::unordered_map<std::string, RequestHandler> req_mapper; |
||||||
|
|
||||||
|
HttpRequest recv_request(Connection conn); |
||||||
|
void send_reponse(Connection conn, HttpReponse res); |
||||||
|
void route_request(Connection conn, HttpRequest req); |
||||||
|
}; |
||||||
|
} |
Loading…
Reference in New Issue