Merge pull request #1 from KeyZox71/yosyo-indev

🔀」 merge(yosyo-indev): starting base of the responses classes and parsing + little norm fix
This commit is contained in:
Adam
2025-02-14 11:30:09 +01:00
committed by GitHub
14 changed files with 632 additions and 18 deletions

View File

@ -6,7 +6,7 @@
# By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ # # By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ # # +#+#+#+#+#+ +#+ #
# Created: 2024/10/25 16:09:27 by adjoly #+# #+# # # Created: 2024/10/25 16:09:27 by adjoly #+# #+# #
# Updated: 2025/01/21 13:13:53 by mmoussou ### ########.fr # # Updated: 2025/02/03 16:43:32 by mmoussou ### ########.fr #
# # # #
# **************************************************************************** # # **************************************************************************** #
@ -18,6 +18,8 @@ CC = c++
OBJSDIR = obj/ OBJSDIR = obj/
INCLUDES = ./includes
SRCS = $(shell find . -name '*.cpp') SRCS = $(shell find . -name '*.cpp')
OBJS = $(addprefix $(OBJSDIR), $(SRCS:.cpp=.o)) OBJS = $(addprefix $(OBJSDIR), $(SRCS:.cpp=.o))
@ -38,12 +40,12 @@ endif
all: $(NAME) all: $(NAME)
$(NAME): $(OBJS) $(NAME): $(OBJS)
@$(CC) $(FLAGS) -I . $(OBJS) -o $(NAME) @$(CC) $(FLAGS) -I$(INCLUDES) $(OBJS) -o $(NAME)
@printf "$(YELLOW)「✨」 feat($(NAME)): program compiled\n" @printf "$(YELLOW)「✨」 feat($(NAME)): program compiled\n"
$(OBJSDIR)%.o: %.cpp $(OBJSDIR)%.o: %.cpp
@mkdir -p $(@D) @mkdir -p $(@D)
@$(CC) $(FLAGS) -I . -c $< -o $@ @$(CC) $(FLAGS) -I$(INCLUDES) -c $< -o $@
@printf "$(DELETE)$(GREEN)「🔨」 build($<): object compiled\n" @printf "$(DELETE)$(GREEN)「🔨」 build($<): object compiled\n"
clean: clean:

View File

@ -2,14 +2,14 @@
## File Structure ## File Structure
- Header Files (.h): - Header Files (.hpp/.h):
- Include declarations of classes, functions, constants, and macros. - Include declarations of classes, functions, constants, and macros.
- Use include guards or #pragma once to prevent multiple inclusions. - Use include guards or #pragma once to prevent multiple inclusions.
- Source Files (.cpp): - Source Files (.cpp):
- Contain the implementation of functions and classes. - Contain the implementation of functions and classes.
## Naming Conventions ## Naming Conventions
- Variables: camelCase (e.g., int studentAge;) - Variables: snake_case (e.g., int student_age;)
- Functions: camelCase (e.g., void calculateSum();) - Functions: camelCase (e.g., void calculateSum();)
- Classes: PascalCase (e.g., class UserAccount {};) - Classes: PascalCase (e.g., class UserAccount {};)
- Constants: ALL_CAPS_SNAKE_CASE (e.g., const int MAX_SIZE = 100;) - Constants: ALL_CAPS_SNAKE_CASE (e.g., const int MAX_SIZE = 100;)

View File

@ -1,7 +1,7 @@
# webserv # webserv
Webserv go brrrrr \ webserv go brrrrr \
This is the webserver you will see in all your life star this IMMIDIATELY otherwise we will come to your house this is the webserver you will see in all your life, star this IMMEDIATELY otherwise we will come to your house
## license ## license

View File

@ -0,0 +1,45 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* HttpIMessage.hpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/11 22:13:38 by mmoussou #+# #+# */
/* Updated: 2025/02/12 00:55:12 by mmoussou ### ########.fr */
/* */
/* ************************************************************************** */
#pragma once
#ifndef __WEBSERV_REQUESTS_HTTP_IMESSAGE_HPP__
# define __WEBSERV_REQUESTS_HTTP_IMESSAGE_HPP__
#include <map>
#include <string>
namespace webserv {
namespace http {
class IMessage {
public:
virtual std::multimap<std::string, std::string> getHeaders(void) const;
virtual std::string getBody(void) const;
virtual void setHeaders(std::multimap<std::string, std::string> const headers);
virtual void setBody(std::string const body);
virtual void addHeader(std::string const key, std::string const value);
virtual void rmHeader(std::string const key);
virtual std::string str(void) const = 0;
protected:
std::multimap<std::string, std::string> _headers;
std::string _body;
};
} // -namespace http
} // -namespace webserv
#endif // __WEBSERV_REQUESTS_HTTP_IMESSAGE_HPP__

View File

@ -0,0 +1,85 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* HttpRequest.hpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/03 17:23:00 by mmoussou #+# #+# */
/* Updated: 2025/02/12 08:56:21 by mmoussou ### ########.fr */
/* */
/* ************************************************************************** */
#pragma once
#ifndef __WEBSERV_REQUESTS_HTTP_REQUEST_HPP__
# define __WEBSERV_REQUESTS_HTTP_REQUEST_HPP__
#include <fstream>
#include <sstream>
#include <iostream>
#include <requests/HttpIMessage.hpp>
#include <requests/HttpResponse.hpp>
namespace webserv {
namespace http {
class IRequest: public http::IMessage {
public:
virtual void parse(std::string const &data) = 0;
virtual http::Response execute(void) = 0;
std::string str(void) const;
std::string getMethod(void) const;
std::string getTarget(void) const;
std::string getProtocol(void) const;
void setMethod(std::string const method);
void setTarget(std::string const target);
void setProtocol(std::string const protocol);
protected:
std::string _method;
std::string _target;
std::string _protocol;
};
class Get: public http::IRequest {
public:
Get(void);
Get(std::string &data);
void parse(std::string const &data);
http::Response execute(void);
};
class Post: public http::IRequest {
public:
Post(void);
Post(std::string &data);
void parse(std::string const &data);
http::Response execute(void);
};
class Delete: public http::IRequest {
public:
Delete(void);
Delete(std::string &data);
void parse(std::string const &data);
http::Response execute(void);
};
} // -namespace http
} // -namespace webserv
#endif // __WEBSERV_REQUESTS_HTTP_REQUEST_HPP__

View File

@ -0,0 +1,48 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* HttpResponse.hpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/03 17:21:20 by mmoussou #+# #+# */
/* Updated: 2025/02/12 00:50:47 by mmoussou ### ########.fr */
/* */
/* ************************************************************************** */
#pragma once
#ifndef __WEBSERV_REQUESTS_HTTP_RESPONSE_HPP__
# define __WEBSERV_REQUESTS_HTTP_RESPONSE_HPP__
#include <sstream>
#include <requests/HttpIMessage.hpp>
namespace webserv {
namespace http {
class Response: public http::IMessage {
public:
Response(void);
std::string getProtocol(void) const;
size_t getStatusCode(void) const;
std::string getStatusText(void) const;
void setProtocol(std::string const protocol);
void setStatusCode(size_t const status_code);
void setStatusText(std::string const status_text);
std::string str(void) const;
private:
std::string _protocol;
size_t _status_code;
std::string _status_text;
};
} // -namespace http
} // -namespace webserv
#endif // __WEBSERV_REQUESTS_HTTP_RESPONSE_HPP__

View File

@ -1,20 +1,22 @@
/* ************************************************************************** */ /* ************************************************************************** */
/* */ /* */
/* ::: :::::::: */ /* ::: :::::::: */
/* webserv.cpp :+: :+: :+: */ /* default.hpp :+: :+: :+: */
/* +:+ +:+ +:+ */ /* +:+ +:+ +:+ */
/* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */ /* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/01/20 16:33:31 by adjoly #+# #+# */ /* Created: 2025/02/03 15:48:22 by mmoussou #+# #+# */
/* Updated: 2025/01/20 16:35:02 by adjoly ### ########.fr */ /* Updated: 2025/02/12 00:11:33 by mmoussou ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include <iostream> #pragma once
#ifndef __WEBSERV_REQUESTS_DEFAULT_HPP__
# define __WEBSERV_REQUESTS_DEFAULT_HPP__
int main(int ac, char **av, char **env) { #include <requests/HttpRequest.hpp>
(void)ac; #include <requests/HttpResponse.hpp>
(void)av;
(void)env; using namespace webserv;
std::cout << "test" << std::endl;
} #endif // __WEBSERV_REQUESTS_DEFAULT_HPP__

View File

@ -0,0 +1,25 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* default.hpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/11 13:29:05 by mmoussou #+# #+# */
/* Updated: 2025/02/12 00:14:11 by mmoussou ### ########.fr */
/* */
/* ************************************************************************** */
#pragma once
#ifndef __WEBSERV_SERVER_DEFAULT_HPP__
# define __WEBSERV_SERVER_DEFAULT_HPP__
namespace webserv {
namespace server {
} // -namespace server
} // -namespace webserv
using namespace webserv;
#endif // __WEBSERV_SERVER_DEFAULT_HPP__

View File

@ -0,0 +1,31 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* webserv.hpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/11 13:29:21 by mmoussou #+# #+# */
/* Updated: 2025/02/12 00:11:41 by mmoussou ### ########.fr */
/* */
/* ************************************************************************** */
#pragma once
#ifndef __WEBSERV_WEBSERV_HPP__
# define __WEBSERV_WEBSERV_HPP__
#include <string>
#include <cstring>
#include <fstream>
#include <csignal>
#include <cstdlib>
#include <iostream>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
namespace webserv {
} //-namespace webserv
#endif // __WEBSERV_WEBSERV_HPP__

11
index.html Normal file
View File

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<style>
body {
background-color: #1e2024;
}
</style>
<body>
<h1 style="font-size: 3rem; font-weight: bold; color: #fff; text-align: center; letter-spacing: 2px; background: linear-gradient(90deg, #ff00ff, #00ffff); -webkit-background-clip: text; display: inline-block; border-bottom: 2px solid #fff;">evilge</h1>
</body>
</html>

106
src/main.cpp Normal file
View File

@ -0,0 +1,106 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* main.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/03 15:45:07 by mmoussou #+# #+# */
/* Updated: 2025/02/12 10:02:11 by mmoussou ### ########.fr */
/* */
/* ************************************************************************** */
#include <webserv.hpp>
#include <requests/default.hpp>
#define PORT 8080
#define BUFFER_SIZE 4096
int server_socket;
void close_socket(int signal)
{
close(server_socket);
exit(signal);
}
int main() {
// handle ctrl-C to close server socket
if (signal(SIGINT, close_socket) == SIG_ERR) {
std::cerr << "Error registering signal handler!" << std::endl;
return 1;
}
// create a socket
server_socket = socket(AF_INET, SOCK_STREAM, 0);
if (server_socket == -1) {
std::cerr << "Failed to create socket" << std::endl;
return 1;
}
// prepare the server address
sockaddr_in server_address;
std::memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = INADDR_ANY;
server_address.sin_port = htons(PORT);
// bind the socket to the address
if (bind(server_socket, (sockaddr*)&server_address, sizeof(server_address)) == -1) {
std::cerr << "Failed to bind socket" << std::endl;
return 1;
}
// listen for incoming connections
if (listen(server_socket, 5) == -1) {
std::cerr << "Failed to listen on socket" << std::endl;
return 1;
}
std::cout << "Server is listening on port " << PORT << std::endl;
while (true) {
// accept an incoming connection
sockaddr_in client_address;
socklen_t client_address_len = sizeof(client_address);
int client_socket = accept(server_socket, (sockaddr*)&client_address, &client_address_len);
if (client_socket == -1) {
std::cerr << "Failed to accept connection" << std::endl;
continue;
}
// receive the HTTP request
char buffer[BUFFER_SIZE];
std::memset(buffer, 0, BUFFER_SIZE);
ssize_t bytes_received = recv(client_socket, buffer, BUFFER_SIZE - 1, 0);
if (bytes_received == -1) {
std::cerr << "Failed to receive request" << std::endl;
close(client_socket);
continue;
}
// parse the request
std::string received_data(buffer, bytes_received);
//HttpRequest request = parseRequest(received_data);
http::Get request(received_data);
std::cout << "Received " << request.getMethod() << " request for " << request.getTarget() << std::endl;
// handle the request
std::string response;
if (request.getMethod() == "GET")
{
response = request.execute().str();
}
else
{
response = "HTTP/1.1 501 Not Implemented\r\nContent-Type: text/html\r\n\r\n<html><body><h1>501 Not Implemented</h1></body></html>";
}
send(client_socket, response.c_str(), response.length(), 0);
close(client_socket);
}
close(server_socket);
return 0;
}

View File

@ -0,0 +1,45 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* HttpIMessage.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/11 23:34:45 by mmoussou #+# #+# */
/* Updated: 2025/02/12 00:59:22 by mmoussou ### ########.fr */
/* */
/* ************************************************************************** */
#include <requests/HttpIMessage.hpp>
using namespace webserv;
std::multimap<std::string, std::string> http::IMessage::getHeaders(void) const
{
return (this->_headers);
}
std::string http::IMessage::getBody(void) const
{
return (this->_body);
}
void http::IMessage::setHeaders(std::multimap<std::string, std::string> const headers)
{
this->_headers = headers;
}
void http::IMessage::setBody(std::string const body)
{
this->_body = body;
}
void http::IMessage::addHeader(std::string const key, std::string const value)
{
this->_headers.insert(std::make_pair(key, value));
}
void http::IMessage::rmHeader(std::string const key)
{
this->_headers.erase(key);
}

View File

@ -0,0 +1,144 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* HttpRequests.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/03 16:07:01 by mmoussou #+# #+# */
/* Updated: 2025/02/12 10:04:33 by mmoussou ### ########.fr */
/* */
/* ************************************************************************** */
#include <requests/HttpRequest.hpp>
using namespace webserv;
std::string http::IRequest::str(void) const
{
std::ostringstream response;
response << this->_method << " " << this->_target << " " << this->_protocol;
response << "\r\n";
for (std::multimap<std::string, std::string>::const_iterator it = this->_headers.begin(); it != this->_headers.end(); ++it)
response << it->first << ": " << it->second << "\r\n";
response << "\r\n";
response << this->_body;
return (response.str());
}
void parse(std::string const &data) { (void) data; }
http::Response execute(void) { return (http::Response()); }
std::string http::IRequest::getMethod(void) const
{
return (this->_method);
}
std::string http::IRequest::getTarget(void) const
{
return (this->_target);
}
std::string http::IRequest::getProtocol(void) const
{
return (this->_protocol);
}
void http::IRequest::setMethod(std::string const method)
{
this->_method = method;
}
void http::IRequest::setTarget(std::string const target)
{
this->_target = target;
}
void http::IRequest::setProtocol(std::string const protocol)
{
this->_protocol = protocol;
}
// ------------------------------------------------------------------
http::Get::Get(void)
{
}
http::Get::Get(std::string &data)
{
this->parse(data);
}
void http::Get::parse(std::string const &data)
{
std::istringstream stream(data);
std::string line;
if (std::getline(stream, line))
{
std::istringstream line_stream(line);
line_stream >> this->_method >> this->_target >> this->_protocol;
this->_target.insert(this->_target.begin(), '.');
}
while (std::getline(stream, line) && line != "\r")
{
size_t delimiter_index = line.find(':');
if (delimiter_index != std::string::npos)
{
std::string key = line.substr(0, delimiter_index);
std::string value = line.substr(delimiter_index + 2);
this->_headers.insert(std::make_pair(key, value));
}
}
std::ostringstream body_stream;
while (std::getline(stream, line))
body_stream << line << "\n";
this->_body = body_stream.str();
/*
std::cout << "method: " << this->_method << std::endl;
std::cout << "target: " << this->_target << std::endl;
std::cout << "protocol: " << this->_protocol << std::endl;
std::cout << std::endl;
std::cout << "-- headers --" << std::endl;
for (std::map<std::string, std::string>::const_iterator it = this->_headers.begin(); it != this->_headers.end(); ++it)
std::cout << it->first << ": " << it->second << std::endl;
std::cout << std::endl;
std::cout << "-- body --" << std::endl << this->_body << std::endl;
*/
}
http::Response http::Get::execute(void)
{
http::Response response;
try
{
std::ifstream file(this->_target.c_str(), std::ios::binary);
response.setProtocol(this->_protocol);
response.setStatusCode(200);
response.setStatusText("OK");
response.addHeader("Content-Type", "text/html");
response.setBody(std::string((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>()));
}
catch (...)
{
// TODO: replace with a predefined array of error pages
response.setProtocol(this->_protocol);
response.setStatusCode(404);
response.setStatusText("Not Found");
response.addHeader("Content-Type", "text/html");
response.setBody("<html><body>nuh uh, get 404'd >:D</body></html>");
}
return (response);
}
// ------------------------------------------------------------------

View File

@ -0,0 +1,70 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* HttpResponse.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/03 17:28:31 by mmoussou #+# #+# */
/* Updated: 2025/02/12 01:00:54 by mmoussou ### ########.fr */
/* */
/* ************************************************************************** */
#include "requests/HttpResponse.hpp"
/*
- do a map of all the status_text and get it from here, not storing them
- get error pages from an array of predefined response, that would be modified by the config
*/
using namespace webserv;
http::Response::Response(void)
{
}
std::string http::Response::str(void) const
{
std::ostringstream response;
response << this->_protocol << " " << this->_status_code << " " << this->_status_text;
response << "\r\n";
for (std::multimap<std::string, std::string>::const_iterator it = this->_headers.begin(); it != this->_headers.end(); ++it)
response << it->first << ": " << it->second << "\r\n";
response << "\r\n";
response << this->_body;
return (response.str());
}
std::string http::Response::getProtocol(void) const
{
return (this->_protocol);
}
size_t http::Response::getStatusCode(void) const
{
return (this->_status_code);
}
std::string http::Response::getStatusText(void) const
{
return (this->_status_text);
}
void http::Response::setProtocol(std::string const protocol)
{
this->_protocol = protocol;
}
void http::Response::setStatusCode(size_t const status_code)
{
this->_status_code = status_code;
}
void http::Response::setStatusText(std::string const status_text)
{
this->_status_text = status_text;
}