mirror of
https://github.com/KeyZox71/webserv.git
synced 2025-05-10 21:38:46 +02:00
4
Makefile
4
Makefile
@ -6,6 +6,7 @@
|
||||
# By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ #
|
||||
# +#+#+#+#+#+ +#+ #
|
||||
# Created: 2024/10/25 16:09:27 by adjoly #+# #+# #
|
||||
# Updated: 2025/04/10 11:52:13 by mmoussou ### ########.fr #
|
||||
# Updated: 2025/03/25 18:13:53 by adjoly ### ########.fr #
|
||||
# #
|
||||
# **************************************************************************** #
|
||||
@ -57,6 +58,7 @@ fclean: clean
|
||||
@rm -Rf $(OBJSDIR)
|
||||
@printf "$(RED)「🗑️」 fclean($(NAME)): program deleted\n"
|
||||
|
||||
re: fclean all
|
||||
re: fclean
|
||||
@$(MAKE) -s all
|
||||
|
||||
.PHONY: clean fclean all re
|
||||
|
47
includes/requests/Errors.hpp
Normal file
47
includes/requests/Errors.hpp
Normal file
@ -0,0 +1,47 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* Errors.hpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/03/16 17:51:46 by mmoussou #+# #+# */
|
||||
/* Updated: 2025/03/24 15:05:53 by mmoussou ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#pragma once
|
||||
#ifndef __WEBSERV_REQUESTS_ERRORS_HPP__
|
||||
# define __WEBSERV_REQUESTS_ERRORS_HPP__
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <requests/HttpResponse.hpp>
|
||||
|
||||
namespace webserv {
|
||||
namespace http {
|
||||
|
||||
/*
|
||||
* DOES NOT WORK
|
||||
* still need to do uh things but base is done at least :D
|
||||
*/
|
||||
|
||||
class Errors {
|
||||
public:
|
||||
//static http::Response &getRequest(int error_code);
|
||||
static std::string getResponseBody(int error_code);
|
||||
static void setEntry(const std::string &key, int value);
|
||||
|
||||
static std::map<int, std::string> message;
|
||||
private:
|
||||
static std::map<int, std::string> populateMessages();
|
||||
|
||||
static std::map<int, std::string> set_error_pages;
|
||||
|
||||
};
|
||||
|
||||
} // -namespace http
|
||||
} // -namespace webserv
|
||||
|
||||
#endif // __WEBSERV_REQUESTS_ERRORS_HPP__
|
@ -6,7 +6,7 @@
|
||||
/* 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 */
|
||||
/* Updated: 2025/04/02 01:47:24 by mmoussou ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
@ -22,10 +22,10 @@ namespace http {
|
||||
|
||||
class IMessage {
|
||||
public:
|
||||
virtual std::multimap<std::string, std::string> getHeaders(void) const;
|
||||
virtual std::map<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 setHeaders(std::map<std::string, std::string> const headers);
|
||||
virtual void setBody(std::string const body);
|
||||
|
||||
virtual void addHeader(std::string const key, std::string const value);
|
||||
@ -34,9 +34,11 @@ public:
|
||||
virtual std::string str(void) const = 0;
|
||||
|
||||
protected:
|
||||
std::multimap<std::string, std::string> _headers;
|
||||
std::map<std::string, std::string> _headers;
|
||||
std::string _body;
|
||||
|
||||
static const std::map<int, std::string> _response_status_codes;
|
||||
|
||||
};
|
||||
|
||||
} // -namespace http
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* 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 */
|
||||
/* Updated: 2025/02/14 15:43:32 by mmoussou ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#ifndef __WEBSERV_REQUESTS_HTTP_REQUEST_HPP__
|
||||
# define __WEBSERV_REQUESTS_HTTP_REQUEST_HPP__
|
||||
|
||||
#include <ctime>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* 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 */
|
||||
/* Updated: 2025/03/24 15:16:39 by mmoussou ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
@ -18,6 +18,8 @@
|
||||
|
||||
#include <requests/HttpIMessage.hpp>
|
||||
|
||||
typedef unsigned int uint;
|
||||
|
||||
namespace webserv {
|
||||
namespace http {
|
||||
|
||||
@ -26,18 +28,17 @@ public:
|
||||
Response(void);
|
||||
|
||||
std::string getProtocol(void) const;
|
||||
size_t getStatusCode(void) const;
|
||||
uint 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);
|
||||
void setStatusCode(uint const status_code);
|
||||
|
||||
std::string str(void) const;
|
||||
|
||||
private:
|
||||
std::string _protocol;
|
||||
size_t _status_code;
|
||||
uint _status_code;
|
||||
std::string _status_text;
|
||||
|
||||
};
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/03 15:48:22 by mmoussou #+# #+# */
|
||||
/* Updated: 2025/02/12 00:11:33 by mmoussou ### ########.fr */
|
||||
/* Updated: 2025/03/17 14:08:50 by mmoussou ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#ifndef __WEBSERV_REQUESTS_DEFAULT_HPP__
|
||||
# define __WEBSERV_REQUESTS_DEFAULT_HPP__
|
||||
|
||||
#include <requests/Errors.hpp>
|
||||
#include <requests/HttpRequest.hpp>
|
||||
#include <requests/HttpResponse.hpp>
|
||||
|
||||
|
124
src/main.cpp
124
src/main.cpp
@ -6,6 +6,7 @@
|
||||
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/03 15:45:07 by mmoussou #+# #+# */
|
||||
/* Updated: 2025/04/10 12:18:39 by mmoussou ### ########.fr */
|
||||
/* Updated: 2025/03/25 17:10:29 by adjoly ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
@ -13,7 +14,124 @@
|
||||
#include "config/Server.hpp"
|
||||
#include <tomlpp.hpp>
|
||||
|
||||
int main(int, char **) {
|
||||
webserv::config::Server serverConf("exemples/test.toml");
|
||||
return 0;
|
||||
#define PORT 8080
|
||||
#define BUFFER_SIZE 4096
|
||||
|
||||
int server_socket;
|
||||
int client_socket;
|
||||
|
||||
void close_socket(int signal)
|
||||
{
|
||||
std::cerr << std::endl << "closing..." << std::endl;
|
||||
close(client_socket);
|
||||
close(server_socket);
|
||||
exit(signal);
|
||||
}
|
||||
|
||||
std::string getMethod(std::string &data)
|
||||
{
|
||||
return (data.substr(0, data.substr(0, 4).find_last_not_of(" ") + 1));
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// handle ctrl-C to close server socket
|
||||
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR || signal(SIGINT, close_socket) == SIG_ERR || signal(SIGQUIT, close_socket) == SIG_ERR)
|
||||
{
|
||||
std::cerr << "Error registering signal handlers!" << 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);
|
||||
|
||||
if (bind(server_socket, (sockaddr*)&server_address, sizeof(server_address)) == -1)
|
||||
{
|
||||
std::cerr << "Failed to bind socket" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
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);
|
||||
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
|
||||
std::string received_data;
|
||||
char buffer[BUFFER_SIZE];
|
||||
ssize_t bytes_received;
|
||||
do
|
||||
{
|
||||
std::memset(buffer, 0, BUFFER_SIZE);
|
||||
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;
|
||||
}
|
||||
received_data += std::string(buffer, bytes_received);
|
||||
}
|
||||
while (buffer[bytes_received]);
|
||||
|
||||
// parse the request
|
||||
|
||||
// handle the request
|
||||
std::string response;
|
||||
|
||||
//std::cout << received_data << std::endl;
|
||||
std::cout << getMethod(received_data) << std::endl;
|
||||
|
||||
if (getMethod(received_data) == "GET")
|
||||
{
|
||||
std::cout << "------------ GET REQUEST ------------" << std::endl;
|
||||
http::Get request(received_data);
|
||||
|
||||
response = request.execute().str();
|
||||
}
|
||||
else if (getMethod(received_data) == "POST")
|
||||
{
|
||||
std::cout << "------------ POST REQUEST ------------" << std::endl;
|
||||
http::Post request(received_data);
|
||||
|
||||
response = request.execute().str();
|
||||
//std::cout << "worked" << std::endl;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
99
src/requests_handling/Errors.cpp
Normal file
99
src/requests_handling/Errors.cpp
Normal file
@ -0,0 +1,99 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* Errors.cpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/03/17 14:08:12 by mmoussou #+# #+# */
|
||||
/* Updated: 2025/04/02 01:48:20 by mmoussou ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include <requests/Errors.hpp>
|
||||
|
||||
using namespace webserv;
|
||||
|
||||
std::string http::Errors::getResponseBody(int error_code)
|
||||
{
|
||||
std::string body;
|
||||
|
||||
if (http::Errors::set_error_pages.find(error_code) != http::Errors::set_error_pages.end())
|
||||
return(Errors::set_error_pages[error_code]);
|
||||
else
|
||||
return("<html><body><h1>" + http::Errors::message[error_code] + "</h1></body></html>");
|
||||
}
|
||||
|
||||
std::map<int, std::string> http::Errors::message = Errors::populateMessages();
|
||||
std::map<int, std::string> http::Errors::set_error_pages;
|
||||
|
||||
std::map<int, std::string> http::Errors::populateMessages()
|
||||
{
|
||||
std::map<int, std::string> m;
|
||||
|
||||
m[100] = "Continue";
|
||||
m[101] = "Switching Protocols";
|
||||
m[102] = "Processing";
|
||||
m[103] = "Early Hints";
|
||||
m[200] = "OK";
|
||||
m[201] = "Created";
|
||||
m[202] = "Accepted";
|
||||
m[203] = "Non-Authoritative Information";
|
||||
m[204] = "No Content";
|
||||
m[205] = "Reset Content";
|
||||
m[206] = "Partial Content";
|
||||
m[207] = "Multi-Status";
|
||||
m[208] = "Already Reported";
|
||||
m[226] = "IM Used";
|
||||
m[300] = "Multiple Choices";
|
||||
m[301] = "Moved Permanently";
|
||||
m[302] = "Found";
|
||||
m[303] = "See Other";
|
||||
m[304] = "Not Modified";
|
||||
m[305] = "Use Proxy";
|
||||
m[306] = "Switch Proxy";
|
||||
m[307] = "Temporary Redirect";
|
||||
m[308] = "Permanent Redirect";
|
||||
m[400] = "Bad Request";
|
||||
m[401] = "Unauthorized";
|
||||
m[402] = "Payment Required";
|
||||
m[403] = "Forbidden";
|
||||
m[404] = "Not Found";
|
||||
m[405] = "Method Not Allowed";
|
||||
m[406] = "Not Acceptable";
|
||||
m[407] = "Proxy Authentication Required";
|
||||
m[408] = "Request Timeout";
|
||||
m[409] = "Conflict";
|
||||
m[410] = "Gone";
|
||||
m[411] = "Length Required";
|
||||
m[412] = "Precondition Failed";
|
||||
m[413] = "Payload Too Large";
|
||||
m[414] = "URI Too Long";
|
||||
m[415] = "Unsupported Media Type";
|
||||
m[416] = "Range Not Satisfiable";
|
||||
m[417] = "Expectation Failed";
|
||||
m[418] = "I'm a teapot";
|
||||
m[420] = "Method Failure";
|
||||
m[421] = "Misdirected Request";
|
||||
m[422] = "Unprocessable Entity";
|
||||
m[423] = "Locked";
|
||||
m[424] = "Failed Dependency";
|
||||
m[426] = "Upgrade Required";
|
||||
m[428] = "Precondition Required";
|
||||
m[429] = "Too Many Requests";
|
||||
m[431] = "Request Header Fields Too Large";
|
||||
m[451] = "Unavailable For Legal Reasons";
|
||||
m[500] = "Internal Server error";
|
||||
m[501] = "Not Implemented";
|
||||
m[502] = "Bad Gateway";
|
||||
m[503] = "Service Unavailable";
|
||||
m[504] = "gateway Timeout";
|
||||
m[505] = "Http version not supported";
|
||||
m[506] = "Varient Also negotiate";
|
||||
m[507] = "Insufficient Storage";
|
||||
m[508] = "Loop Detected";
|
||||
m[510] = "Not Extended";
|
||||
m[511] = "Network Authentication Required";
|
||||
|
||||
return m;
|
||||
}
|
@ -6,7 +6,7 @@
|
||||
/* 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 */
|
||||
/* Updated: 2025/04/02 01:46:52 by mmoussou ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
|
||||
using namespace webserv;
|
||||
|
||||
std::multimap<std::string, std::string> http::IMessage::getHeaders(void) const
|
||||
std::map<std::string, std::string> http::IMessage::getHeaders(void) const
|
||||
{
|
||||
return (this->_headers);
|
||||
}
|
||||
@ -24,7 +24,7 @@ std::string http::IMessage::getBody(void) const
|
||||
return (this->_body);
|
||||
}
|
||||
|
||||
void http::IMessage::setHeaders(std::multimap<std::string, std::string> const headers)
|
||||
void http::IMessage::setHeaders(std::map<std::string, std::string> const headers)
|
||||
{
|
||||
this->_headers = headers;
|
||||
}
|
||||
|
@ -6,11 +6,17 @@
|
||||
/* 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 */
|
||||
/* Updated: 2025/04/10 11:50:48 by mmoussou ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include <requests/HttpRequest.hpp>
|
||||
#include <requests/Errors.hpp>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
|
||||
using namespace webserv;
|
||||
|
||||
@ -21,7 +27,7 @@ std::string http::IRequest::str(void) const
|
||||
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)
|
||||
for (std::map<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";
|
||||
@ -103,6 +109,7 @@ void http::Get::parse(std::string const &data)
|
||||
this->_body = body_stream.str();
|
||||
|
||||
/*
|
||||
std::cout << "-- start-line --" << std::endl;
|
||||
std::cout << "method: " << this->_method << std::endl;
|
||||
std::cout << "target: " << this->_target << std::endl;
|
||||
std::cout << "protocol: " << this->_protocol << std::endl;
|
||||
@ -115,30 +122,289 @@ void http::Get::parse(std::string const &data)
|
||||
*/
|
||||
}
|
||||
|
||||
char isDirectory(const std::string& path)
|
||||
{
|
||||
struct stat file_stat;
|
||||
|
||||
if (stat(path.c_str(), &file_stat) != 0)
|
||||
{
|
||||
throw std::runtime_error("can't open file (non-existant ?)");
|
||||
}
|
||||
return S_ISDIR(file_stat.st_mode);
|
||||
}
|
||||
|
||||
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>()));
|
||||
if (isDirectory(this->_target))
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *entry;
|
||||
struct stat file_stat;
|
||||
std::vector<std::string> files;
|
||||
|
||||
if ((dir = opendir(this->_target.c_str())) == NULL)
|
||||
throw;
|
||||
while ((entry = readdir(dir)) != NULL)
|
||||
{
|
||||
std::string file_name = entry->d_name;
|
||||
if (file_name == ".")
|
||||
continue;
|
||||
std::string file_path = this->_target + "/" + file_name;
|
||||
if (stat(file_path.c_str(), &file_stat) == 0)
|
||||
{
|
||||
if (S_ISDIR(file_stat.st_mode))
|
||||
files.push_back(file_name + "/");
|
||||
else
|
||||
files.push_back(file_name);
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
std::sort(files.begin(), files.end());
|
||||
|
||||
std::string body = "<html><body><ul>\n";
|
||||
for (size_t i = 0; i < files.size(); i++)
|
||||
body += "<li><a href=\"" + files[i] + "\">" + files[i] + "</a></li>\n";
|
||||
body += "</ul></body></html>";
|
||||
|
||||
response.setProtocol(this->_protocol);
|
||||
response.setStatusCode(200);
|
||||
std::stringstream length;
|
||||
length << body.length();
|
||||
response.addHeader("Content-Length", length.str());
|
||||
response.addHeader("Content-Type", "text/html");
|
||||
response.setBody(body);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ifstream file(this->_target.c_str(), std::ios::binary);
|
||||
std::streampos file_start = file.tellg();
|
||||
response.setBody(std::string((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>()));
|
||||
std::stringstream length;
|
||||
length << (file.tellg() - file_start);
|
||||
response.addHeader("Content-Length", length.str());
|
||||
|
||||
response.setProtocol(this->_protocol);
|
||||
response.setStatusCode(200);
|
||||
response.addHeader("Content-Type", "text/html"); // TODO: change it to check the file extension and set it to the corresponding MIME or text/plain if unkown. we will only implement the important MIME types in the Mozilla documentation because https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/MIME_types/Common_types
|
||||
|
||||
//std::ifstream file_end(this->_target.c_str(), std::ios::binary | std::ios::ate);
|
||||
//std::stringstream length;
|
||||
//length << (file_end.tellg() - file.tellg());
|
||||
//std::cout << length.str() << std::endl;
|
||||
//response.addHeader("Content-Length", length.str());
|
||||
}
|
||||
}
|
||||
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>");
|
||||
response.setBody(http::Errors::getResponseBody(response.getStatusCode()));
|
||||
}
|
||||
|
||||
return (response);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
http::Delete::Delete(void)
|
||||
{
|
||||
}
|
||||
|
||||
http::Delete::Delete(std::string &data)
|
||||
{
|
||||
this->parse(data);
|
||||
}
|
||||
|
||||
void http::Delete::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 << "-- start-line --" << std::endl;
|
||||
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::Delete::execute(void)
|
||||
{
|
||||
http::Response response;
|
||||
|
||||
try
|
||||
{
|
||||
if (std::remove(this->_target.c_str()))
|
||||
throw std::runtime_error("can't remove file, FF");
|
||||
response.setProtocol(this->_protocol);
|
||||
response.setStatusCode(204);
|
||||
time_t now = std::time(NULL);
|
||||
response.addHeader("Date", std::string(std::ctime(&now)));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// TODO: check errno value and get corresponding error page, check for corresponding error code : https://cdn.discordapp.com/attachments/784779058407014403/1350841524778307586/image.png?ex=67d8dd74&is=67d78bf4&hm=c030468d3862627d6402bf200960d1a15249ba2f8dac772af3283b368a77f2f5&
|
||||
|
||||
response.setProtocol(this->_protocol);
|
||||
response.setStatusCode(404);
|
||||
response.addHeader("Content-Type", "text/html");
|
||||
response.setBody(http::Errors::getResponseBody(response.getStatusCode()));
|
||||
}
|
||||
|
||||
return (response);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
http::Post::Post(void)
|
||||
{
|
||||
}
|
||||
|
||||
http::Post::Post(std::string &data)
|
||||
{
|
||||
this->parse(data);
|
||||
}
|
||||
|
||||
void http::Post::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 << "-- start-line --" << std::endl;
|
||||
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;
|
||||
*/
|
||||
}
|
||||
|
||||
std::string extractFilename(const std::string &header)
|
||||
{
|
||||
size_t start = header.find("filename=\"") + 10;
|
||||
size_t end = header.find("\"", start);
|
||||
return header.substr(start, end - start);
|
||||
}
|
||||
|
||||
void handleMultipartData(const std::string &body, const std::string &boundary)
|
||||
{
|
||||
size_t i = 0;
|
||||
std::string delim = "--" + boundary;
|
||||
delim.erase(delim.size() - 1);
|
||||
|
||||
while ((i = body.find(delim, i)) != std::string::npos)
|
||||
{
|
||||
size_t start = i + delim.length();
|
||||
size_t end = body.find("\r\n\r\n", start);
|
||||
|
||||
if (end != std::string::npos)
|
||||
{
|
||||
std::string part_header = body.substr(start, end - start);
|
||||
//std::cout << std::endl << std::endl << std::endl << std::endl;
|
||||
std::string part_content = body.substr(end + 4, body.find(delim, end) - end - 4);
|
||||
|
||||
std::ofstream outfile(extractFilename(part_header).c_str(), std::ios::binary);
|
||||
if (outfile.is_open())
|
||||
{
|
||||
outfile.write(part_content.c_str(), part_content.length());
|
||||
outfile.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "open failed" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
i += delim.length();
|
||||
}
|
||||
}
|
||||
|
||||
http::Response http::Post::execute(void)
|
||||
{
|
||||
http::Response response;
|
||||
|
||||
try
|
||||
{
|
||||
handleMultipartData(this->_body, this->getHeaders()["Content-Type"].substr(this->getHeaders()["Content-Type"].find("=", this->getHeaders()["Content-Type"].find(";")) + 1));
|
||||
|
||||
response.setProtocol(this->_protocol);
|
||||
response.setStatusCode(200);
|
||||
response.addHeader("Content-Type", "text/html");
|
||||
response.setBody(http::Errors::getResponseBody(response.getStatusCode()));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
response.setProtocol(this->_protocol);
|
||||
response.setStatusCode(500);
|
||||
response.addHeader("Content-Type", "text/html");
|
||||
response.setBody(http::Errors::getResponseBody(response.getStatusCode()));
|
||||
}
|
||||
return (response);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
@ -6,17 +6,21 @@
|
||||
/* 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 */
|
||||
/* Updated: 2025/04/08 01:11:40 by mmoussou ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "requests/HttpResponse.hpp"
|
||||
#include <requests/HttpResponse.hpp>
|
||||
#include <requests/Errors.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
|
||||
*/
|
||||
|
||||
// tmp, need to be cleaned
|
||||
#include <iostream>
|
||||
|
||||
using namespace webserv;
|
||||
|
||||
http::Response::Response(void)
|
||||
@ -30,12 +34,13 @@ std::string http::Response::str(void) const
|
||||
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)
|
||||
for (std::map<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;
|
||||
|
||||
//std::cout << "------------ RESPONSE -------------" << std::endl << response.str();
|
||||
return (response.str());
|
||||
}
|
||||
|
||||
@ -44,7 +49,7 @@ std::string http::Response::getProtocol(void) const
|
||||
return (this->_protocol);
|
||||
}
|
||||
|
||||
size_t http::Response::getStatusCode(void) const
|
||||
uint http::Response::getStatusCode(void) const
|
||||
{
|
||||
return (this->_status_code);
|
||||
}
|
||||
@ -59,12 +64,8 @@ void http::Response::setProtocol(std::string const protocol)
|
||||
this->_protocol = protocol;
|
||||
}
|
||||
|
||||
void http::Response::setStatusCode(size_t const status_code)
|
||||
void http::Response::setStatusCode(uint const status_code)
|
||||
{
|
||||
this->_status_code = status_code;
|
||||
}
|
||||
|
||||
void http::Response::setStatusText(std::string const status_text)
|
||||
{
|
||||
this->_status_text = status_text;
|
||||
this->_status_text = Errors::message[status_code];
|
||||
}
|
||||
|
90
upload.html
Normal file
90
upload.html
Normal file
@ -0,0 +1,90 @@
|
||||
<meta charset="utf-8">
|
||||
<html>
|
||||
<head>
|
||||
<title>upload</title>
|
||||
</head>
|
||||
<body>
|
||||
<!-- j'ai pas volé le code (c'est faux) -->
|
||||
<!-- putain les pubs spotify c'est chiant -->
|
||||
<!-- je m'en fous de leur bière -->
|
||||
<form id="upload_form" enctype="multipart/form-data" method="post">
|
||||
<input type="file" name="file1" id="file1" onchange="uploadFile()"><br>
|
||||
<progress id="progressBar" value="0" max="100" style="width:300px;"></progress>
|
||||
<h3 id="status"></h3>
|
||||
<p id="loaded_n_total"></p>
|
||||
</form>
|
||||
<button id="abort" hidden>annuler le tranfert</button>
|
||||
<script>
|
||||
function _(el) {
|
||||
return document.getElementById(el);
|
||||
}
|
||||
|
||||
function uploadFile() {
|
||||
bouton = document.getElementById("abort")
|
||||
var file = _("file1").files[0];
|
||||
|
||||
// alert(file.name+" | "+file.size+" | "+file.type);
|
||||
var formdata = new FormData();
|
||||
formdata.append("file1", file);
|
||||
var ajax = new XMLHttpRequest();
|
||||
bouton.onclick = function(){
|
||||
ajax.abort()
|
||||
}
|
||||
bouton.removeAttribute("hidden")
|
||||
ajax.upload.addEventListener("progress", progressHandler, false);
|
||||
ajax.addEventListener("load", completeHandler, false);
|
||||
ajax.addEventListener("error", errorHandler, false);
|
||||
ajax.addEventListener("abort", abortHandler, false);
|
||||
ajax.open("POST", "/upload.html");
|
||||
ajax.send(formdata);
|
||||
startmillis = Date.now()
|
||||
}
|
||||
|
||||
function copy(){
|
||||
window.getSelection().removeAllRanges()
|
||||
range = document.createRange()
|
||||
range.selectNodeContents(_("addr"))
|
||||
window.getSelection().addRange(range)
|
||||
document.execCommand('copy')
|
||||
window.getSelection().removeAllRanges()
|
||||
temp = _("addr").innerHTML
|
||||
_("addr").innerHTML = "copié !"
|
||||
setTimeout(()=>{_("addr").innerHTML = temp},500)
|
||||
}
|
||||
|
||||
function progressHandler(event) {
|
||||
// console.log(Math.round((event.loaded/1024/1024)*100)/100)
|
||||
// console.log((Date.now()-startmillis)/1000+'s')
|
||||
//console.log((event.loaded/1024/1024) /((Date.now()-startmillis)*1000)+"Mo/s")
|
||||
// console.log((event.loaded/1024/1024))
|
||||
|
||||
console.log(`${(event.loaded/1024/1024)} / ${(Date.now()-startmillis)} / 1000`)
|
||||
console.log((event.loaded/1024/1024)/((Date.now()-startmillis)/1000))
|
||||
|
||||
|
||||
|
||||
|
||||
_("loaded_n_total").innerHTML = Math.round((event.loaded/1024/1024)*100)/100 + "Mo / " + Math.round((event.total/1024/1024)*100)/100+"Mo envoyé<br/>"+Math.round((event.loaded/1024/1024)/((Date.now()-startmillis)/1000)*100)/100+"Mo/s en moyenne";
|
||||
var percent = (event.loaded / event.total) * 100;
|
||||
_("progressBar").value = Math.round(percent);
|
||||
_("status").innerHTML = Math.round(percent * 100) / 100 + "% envoyé... veuillez patienter";
|
||||
}
|
||||
|
||||
function completeHandler(event) {
|
||||
_("status").innerHTML = event.target.responseText;
|
||||
_("progressBar").value = 0; //wil clear progress bar after successful upload
|
||||
console.log("fin de l'envoi")
|
||||
_("abort").setAttribute("hidden",true)
|
||||
}
|
||||
|
||||
function errorHandler(event) {
|
||||
_("status").innerHTML = "Upload Failed";
|
||||
}
|
||||
|
||||
function abortHandler(event) {
|
||||
_("status").innerHTML = "envoi annulé";
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
Reference in New Issue
Block a user