diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..516e5e5 --- /dev/null +++ b/Makefile @@ -0,0 +1,5 @@ +run: build + ./server + +build: + g++ -std=c++20 server.cpp request.cpp response.cpp -g -o server diff --git a/request.cpp b/request.cpp new file mode 100644 index 0000000..5d512b7 --- /dev/null +++ b/request.cpp @@ -0,0 +1,91 @@ +#include "request.hpp" +#include + +bool Request::protocol(std::stringstream *ss, int *procPart, char c) { + if (c == ' ' || c == '\n') { + switch (*procPart) { + case 0: + m_method = ss->str(); + break; + case 1: + m_path = ss->str(); + break; + case 2: + m_protocol = ss->str(); + break; + } + (*procPart)++; + ss->str(""); + if (c == '\n') + return false; + } else { + ss->put(c); + } + return true; +} + +Request::Request(std::vector buf) { + std::string name; + std::stringstream ss; + bool header = true; + int procPart = 0; + bool data = false; + bool skipNext = false; + bool p = true; + for (auto &byte : buf) { + if (data) { + m_payload.push_back(byte); + continue; + } + + char c = static_cast(byte); + if (c == '\r') + continue; + + if (p) { + p = protocol(&ss, &procPart, c); + continue; + } + + if (skipNext && c == ' ') { + skipNext = false; + continue; + } + skipNext = false; + + if (c == ':' && header) { + skipNext = true; + header = false; + name = ss.str(); + ss.str(""); + } else if (c == '\n' && !name.empty()) { + m_headers.insert_or_assign(name, ss.str()); + ss.str(""); + name.clear(); + header = true; + } else if (c == '\n' && name.empty()) { + data = true; + } else { + ss << c; + } + } +} + +void Request::Print() { + std::cout << "Protocol: " << m_protocol << "\n" + << "Req: " << m_method << " " << m_path << std::endl; + for (const auto &[key, value] : m_headers) { + std::cout << "[" << key << "]: [" << value << "]\n"; + } + + if (HasData()) { + std::cout << "Payload: " << std::endl; + for (auto &byte : m_payload) { + std::cout << static_cast(byte); + } + std::cout << std::endl; + } +} + +bool Request::HasData() { return m_payload.size() != 0; } +std::vector Request::Data() { return m_payload; } diff --git a/request.hpp b/request.hpp new file mode 100644 index 0000000..64d8df1 --- /dev/null +++ b/request.hpp @@ -0,0 +1,25 @@ +#ifndef REQUEST_HEADER_H +#define REQUEST_HEADER_H +#include +#include +#include +#include + +class Request { +private: + std::map m_headers; + std::string m_method; + std::string m_path; + std::vector m_payload; + std::string m_protocol; + +private: + bool protocol(std::stringstream *ss, int *procPart, char c); + +public: + Request(std::vector buf); + void Print(); + bool HasData(); + std::vector Data(); +}; +#endif // !REQUEST_HEADER_H diff --git a/response.cpp b/response.cpp new file mode 100644 index 0000000..dd2f8da --- /dev/null +++ b/response.cpp @@ -0,0 +1,58 @@ +#include "response.hpp" +#include +#include +#include +#include +#include +#include +#include + +Response::Response(std::vector data) { + m_headers.insert(std::pair( + "content-length", std::to_string(data.size()))); + m_payload = data; +} + +Response::Response(std::string data) { + m_headers.insert(std::pair( + "content-length", std::to_string(std::strlen(data.data())))); + + m_payload = std::vector(data.size() + 1); + std::transform(data.begin(), data.end(), m_payload.begin(), + [](char c) { return std::byte(c); }); +} + +void Response::SetContentType(const std::string type) { + m_headers.insert_or_assign("content-type", type); +} + +void Response::Send(int clientSocket) { + std::stringstream ss; + ss << "HTTP/1.1 200 OK\n"; + for (const auto &[key, value] : m_headers) { + ss << key << ": " << value << "\n"; + } + if (m_payload.size() >= 0) { + ss << "\n"; + for (auto &byte : m_payload) { + char c = static_cast(byte); + ss << c; + } + } + std::string p = ss.str(); + send(clientSocket, p.data(), p.size(), 0); +} + +void Response::Print() { + for (const auto &[key, value] : m_headers) { + std::cout << "[" << key << "]: [" << value << "]\n"; + } + + if (m_payload.size() != 0) { + std::cout << "Payload: " << std::endl; + for (auto &byte : m_payload) { + std::cout << static_cast(byte); + } + std::cout << std::endl; + } +} diff --git a/response.hpp b/response.hpp new file mode 100644 index 0000000..59ce516 --- /dev/null +++ b/response.hpp @@ -0,0 +1,19 @@ +#ifndef RESPONSE_H + +#include +#include +#include +class Response { +private: + std::map m_headers; + std::vector m_payload; + +public: + Response(std::vector data); + Response(std::string data); + void SetContentType(const std::string type); + void Send(int clientSocket); + void Print(); +}; + +#endif // !RESPONSE_H diff --git a/server.cpp b/server.cpp index 6b0eaed..29311ca 100644 --- a/server.cpp +++ b/server.cpp @@ -1,176 +1,16 @@ -#include +#include "request.hpp" +#include "response.hpp" #include #include #include #include #include -#include #include #include -#include -#include #include #include #include -class Request { -private: - std::map m_headers; - std::string m_method; - std::string m_path; - std::vector m_payload; - std::string m_protocol; - -private: - bool protocol(std::stringstream *ss, int *procPart, char c) { - if (c == ' ' || c == '\n') { - switch (*procPart) { - case 0: - m_method = ss->str(); - break; - case 1: - m_path = ss->str(); - break; - case 2: - m_protocol = ss->str(); - break; - } - (*procPart)++; - ss->str(""); - if (c == '\n') - return false; - } else { - ss->put(c); - } - return true; - } - -public: - Request(std::vector buf) { - std::string name; - std::stringstream ss; - bool header = true; - int procPart = 0; - bool data = false; - bool skipNext = false; - bool p = true; - for (auto &byte : buf) { - if (data) { - m_payload.push_back(byte); - continue; - } - - char c = static_cast(byte); - if (c == '\r') - continue; - - if (p) { - p = protocol(&ss, &procPart, c); - continue; - } - - if (skipNext && c == ' ') { - skipNext = false; - continue; - } - skipNext = false; - - if (c == ':' && header) { - skipNext = true; - header = false; - name = ss.str(); - ss.str(""); - } else if (c == '\n' && !name.empty()) { - m_headers.insert_or_assign(name, ss.str()); - ss.str(""); - name.clear(); - header = true; - } else if (c == '\n' && name.empty()) { - data = true; - } else { - ss << c; - } - } - } - - void Print() { - std::cout << "Protocol: " << m_protocol << "\n" - << "Req: " << m_method << " " << m_path << std::endl; - for (const auto &[key, value] : m_headers) { - std::cout << "[" << key << "]: [" << value << "]\n"; - } - - if (HasData()) { - std::cout << "Payload: " << std::endl; - for (auto &byte : m_payload) { - std::cout << static_cast(byte); - } - std::cout << std::endl; - } - } - bool HasData() { return m_payload.size() != 0; } - std::vector Data() { return m_payload; } -}; - -class Response { -private: - std::map m_headers; - std::vector m_payload; - -public: - Response(std::vector data) { - m_headers.insert(std::pair( - "content-length", std::to_string(data.size()))); - m_payload = data; - } - - Response(std::string data) { - m_headers.insert(std::pair( - "content-length", std::to_string(std::strlen(data.data())))); - - m_payload = std::vector(data.size() + 1); - std::transform(data.begin(), data.end(), m_payload.begin(), - [](char c) { return std::byte(c); }); - } - - void SetContentType(const std::string type) { - m_headers.insert_or_assign("content-type", type); - } - - void Send(int clientSocket) { - std::stringstream ss; - ss << "HTTP/1.1 200 OK\n"; - for (const auto &[key, value] : m_headers) { - ss << key << ": " << value << "\n"; - } - if (m_payload.size() >= 0) { - ss << "\n"; - for (auto &byte : m_payload) { - std::cout << int(byte) << ' '; - char c = static_cast(byte); - ss << c; - } - std::cout << std::endl; - } - std::string p = ss.str(); - send(clientSocket, p.data(), p.size(), 0); - } - - void Print() { - for (const auto &[key, value] : m_headers) { - std::cout << "[" << key << "]: [" << value << "]\n"; - } - - if (m_payload.size() != 0) { - std::cout << "Payload: " << std::endl; - for (auto &byte : m_payload) { - std::cout << static_cast(byte); - } - std::cout << std::endl; - } - } -}; - int main() { int serverSocket = socket(AF_INET, SOCK_STREAM, 0); sockaddr_in serverAddress; @@ -197,7 +37,6 @@ int main() { int read = recv(clientSocket, buffer.data(), buffer.size(), 0); buffer.resize(read); Request req(buffer); - // req.Print(); Response res = Response("Hello world!"); if (req.HasData()) { auto data = req.Data(); @@ -205,8 +44,6 @@ int main() { } res.SetContentType("text/plain"); - // std::cout << "RESPONSE: " << std::endl; - // res.Print(); res.Send(clientSocket); close(clientSocket); }