restructure + parser + readme updates

This commit is contained in:
Nicholas Orlowsky 2023-09-07 19:33:22 -04:00
parent c726e6cf28
commit b4265fe9c3
No known key found for this signature in database
GPG key ID: 24C84C4DDAD95065
10 changed files with 778 additions and 149 deletions

172
main.cpp
View file

@ -1,4 +1,6 @@
#include "backends/file_backend.cpp"
#include <exception>
#include <fmt/core.h>
#include <fstream>
#include <iostream>
#include <netinet/in.h>
@ -9,157 +11,37 @@
using namespace std;
class Socket {
private:
int server_socket;
int client_socket;
void log_request_an_response(http_request req, http_response resp);
public:
Socket(int port, int max_queue = 10) {
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_port = htons(port);
address.sin_addr.s_addr = INADDR_ANY;
constexpr int default_port = 80;
server_socket = socket(AF_INET, SOCK_STREAM, 0);
int x = 1;
setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
bind(server_socket, (struct sockaddr *)&address, sizeof(address));
int main(int argc, char** argv)
{
int port_number = default_port;
::listen(server_socket, max_queue);
}
void wait_for_conn() { client_socket = accept(server_socket, NULL, NULL); }
void close_conn() {
close(client_socket);
client_socket = -1;
}
void send_message(string msg) {
if (client_socket == -1) {
return;
}
send(client_socket, &msg[0], msg.length(), 0);
}
string recv_message(int buffer_size = 1024) {
if (client_socket == -1) {
return "";
if (argc > 1) {
port_number = atoi(argv[1]);
}
char response[buffer_size + 1];
recv(client_socket, response, sizeof(response), 0);
response[buffer_size] = '\0';
return string(response);
}
};
cout << "Initializing Anthracite\n";
anthracite_socket s(port_number);
cout << "Initialization Complete\n";
cout << "Listening for HTTP connections on port " << port_number << "\n";
file_backend fb;
enum http_method { GET, POST, PUT, PATCH, UNKNOWN };
static unordered_map<string, http_method> const http_method_map = {
{"GET", http_method::GET}};
static unordered_map<int, string> const http_status_map = {
{200, "OK"},
{404, "NOT FOUND"},
};
class http_request {
private:
http_method _method;
string _path;
public:
http_request(string raw_data) {
int state = 0;
string method = "";
for (int i = 0; i < raw_data.length() && state != 2; i++) {
if (raw_data[i] == ' ') {
state++;
continue;
}
if (state == 0) {
method += raw_data[i];
} else if (state == 1) {
_path += raw_data[i];
}
while (true) {
s.wait_for_conn();
http_request req(s);
http_response resp = fb.handle_request(req);
log_request_an_response(req, resp);
s.send_message(resp.to_string());
s.close_conn();
}
if (http_method_map.find(method) == http_method_map.end()) {
_method = http_method::UNKNOWN;
} else {
_method = http_method_map.find(method)->second;
}
}
string path() { return _path; }
http_method method() { return _method; }
};
class http_response {
private:
int _status_code;
string _content;
public:
http_response(string content, int status_code = 200) {
_content = content;
_status_code = status_code;
}
string to_string() {
string response = "";
response += "HTTP/1.1 " + ::to_string(_status_code) + " " +
http_status_map.find(_status_code)->second + " \n";
response += "Content-Type: text/html\n";
response += "Content-Length: " + ::to_string(_content.length()) + "\n";
response += "Server: Anthracite/0.0.1\n\n";
response += _content;
return response;
}
};
int main() {
cout << "Initializing Server...\n";
Socket s(8099);
cout << "Initialized, Awaiting Connections...\n";
while (true) {
s.wait_for_conn();
cout << "Received Request...\n";
http_request req(s.recv_message(8190));
string response = "";
switch (req.method()) {
case http_method::GET: {
string filename = req.path() == "/" ? "index.html" : req.path();
filename = "./www/" + filename;
ifstream stream(filename);
int status = 200;
if (!stream.is_open()) {
status = 404;
filename = "./error_pages/404.html";
stream = ifstream(filename);
}
stringstream buffer;
buffer << stream.rdbuf();
http_response res(buffer.str(), status);
response = res.to_string();
} break;
default:
break;
}
cout << "Responding with: \n" << response << "\n";
s.send_message(response);
s.close_conn();
}
return 0;
return 0;
}
void log_request_an_response(http_request req, http_response resp)
{
cout << "[" << resp.status_code() << " " + http_status_map.find(resp.status_code())->second + "] " + req.client_ip() + " " + http_reverse_method_map.find(req.method())->second + " " + req.path() + "\n";
}