forked from cat/WebBase
Resolving conflict
This commit is contained in:
@@ -7,8 +7,11 @@ set(CMAKE_CXX_STANDARD 17)
|
|||||||
set(CMAKE_BUILD_TYPE Debug)
|
set(CMAKE_BUILD_TYPE Debug)
|
||||||
set(CMAKE_CXX_FLAGS "-Wall -g -fsanitize=address")
|
set(CMAKE_CXX_FLAGS "-Wall -g -fsanitize=address")
|
||||||
|
|
||||||
add_executable(Webserver "src/Entry.cpp" "src/Webserver.cpp" "src/HTTP.cpp"
|
add_executable(
|
||||||
"libs/QuickDigest5/quickdigest5.cpp" "src/Helpers.cpp")
|
Webserver
|
||||||
|
"src/Entry.cpp" "src/Webserver.cpp" "src/HTTP.cpp"
|
||||||
|
"libs/QuickDigest5/quickdigest5.cpp" "src/Helpers.cpp"
|
||||||
|
"src/HTTPRequestProcess.cpp")
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
TARGET Webserver
|
TARGET Webserver
|
||||||
|
@@ -1,6 +1,11 @@
|
|||||||
# TNC File Hoster
|
# TNC File Hoster
|
||||||
|
|
||||||
The Night Club's very own basic image hosting web frontend.
|
The Night Club's very own basic image hosting web frontend.
|
||||||
|
=======
|
||||||
|
# Web Base for C++
|
||||||
|
|
||||||
|
A good starting point for web development on C++. Do implement security stuff.
|
||||||
|
>>>>>>> upstream/main
|
||||||
|
|
||||||
# Building
|
# Building
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
#include "main.hpp"
|
#include "Main.hpp"
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
89
src/HTTP.cpp
89
src/HTTP.cpp
@@ -1,94 +1,9 @@
|
|||||||
#include "Helpers.hpp"
|
#include "Helpers.hpp"
|
||||||
#include "main.hpp"
|
#include "Main.hpp"
|
||||||
#include <asio/completion_condition.hpp>
|
|
||||||
#include <asio/impl/read_until.hpp>
|
|
||||||
#include <iostream>
|
|
||||||
#include <istream>
|
|
||||||
#include <ostream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <string>
|
|
||||||
#include <system_error>
|
|
||||||
|
|
||||||
void HTTPrequest::start() {
|
void HTTPrequest::start() {
|
||||||
// Possible Logging here
|
// Possible Logging here
|
||||||
readData();
|
processHTTPHeader();
|
||||||
}
|
|
||||||
|
|
||||||
void HTTPrequest::readData() {
|
|
||||||
//
|
|
||||||
// Reading happens here
|
|
||||||
//
|
|
||||||
std::shared_ptr<HTTPrequest> self(shared_from_this());
|
|
||||||
|
|
||||||
// TODO: Read until headers, headers contains the file size then allocate that
|
|
||||||
// much memory on buffer, and THEN start reading the file
|
|
||||||
|
|
||||||
// HEADER read
|
|
||||||
asio::async_read_until(
|
|
||||||
sock, buffer, "\r\n\r\n", // its not the other way bud
|
|
||||||
[this, self](std::error_code error, std::size_t packageSize) {
|
|
||||||
if (!error) {
|
|
||||||
buffer.commit(packageSize);
|
|
||||||
std::unordered_map<std::string, std::string> request;
|
|
||||||
std::unordered_map<std::string, std::string> args;
|
|
||||||
std::istream stream(&buffer);
|
|
||||||
uint64_t bitCount = 0;
|
|
||||||
|
|
||||||
// This is HTTP main request
|
|
||||||
std::string rq, key, value, type, path;
|
|
||||||
|
|
||||||
Helpers::getlineAndCount(stream, bitCount, type,
|
|
||||||
' '); // HTTP request type
|
|
||||||
Helpers::getlineAndCount(stream, bitCount, path, ' '); // HTTP path
|
|
||||||
Helpers::getlineAndCount(stream, bitCount,
|
|
||||||
rq); // Version, omitting for now
|
|
||||||
|
|
||||||
// Quick stop to process arguments
|
|
||||||
std::stringstream pathStream(path);
|
|
||||||
std::getline(pathStream, path, '?'); // Keeping the path pure
|
|
||||||
|
|
||||||
while (!pathStream.eof()) {
|
|
||||||
std::getline(pathStream, key, '=');
|
|
||||||
std::getline(pathStream, value, '&');
|
|
||||||
args.insert({key, value});
|
|
||||||
std::cout << key << " " << value << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rest of the request vals
|
|
||||||
while (bitCount <
|
|
||||||
packageSize - 2) { // -2 is due to last two \r\n\r\n combo
|
|
||||||
Helpers::getlineAndCount(stream, bitCount, key, ':');
|
|
||||||
Helpers::getlineAndCount(
|
|
||||||
stream, bitCount, rq,
|
|
||||||
' '); // trim start some gangster shit right here
|
|
||||||
Helpers::getlineAndCount(stream, bitCount, value);
|
|
||||||
request.insert({key, value});
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===================
|
|
||||||
// BODY OF THE REQUEST
|
|
||||||
// ===================
|
|
||||||
std::size_t uploadSize =
|
|
||||||
std::stoull(request.at("Content-Length")) - buffer.size();
|
|
||||||
asio::async_read(
|
|
||||||
sock, buffer.prepare(uploadSize),
|
|
||||||
asio::transfer_exactly(uploadSize),
|
|
||||||
[self, this](std::error_code error, std::size_t packageSize) {
|
|
||||||
buffer.commit(packageSize);
|
|
||||||
std::istream bodyStream(&buffer);
|
|
||||||
std::string body;
|
|
||||||
body.resize(buffer.size());
|
|
||||||
bodyStream.read(body.data(), buffer.size());
|
|
||||||
|
|
||||||
std::cout << body << "\ntest" << std::endl;
|
|
||||||
buffer.consume(buffer.size());
|
|
||||||
sock.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
processRequest(type, path, request, args); // This writes data too
|
|
||||||
sock.close();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTTPrequest::processRequest(
|
void HTTPrequest::processRequest(
|
||||||
|
89
src/HTTPRequestProcess.cpp
Normal file
89
src/HTTPRequestProcess.cpp
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
#include "Helpers.hpp"
|
||||||
|
#include "Main.hpp"
|
||||||
|
|
||||||
|
void HTTPrequest::processHTTPHeader() {
|
||||||
|
//
|
||||||
|
// Reading happens here
|
||||||
|
//
|
||||||
|
std::shared_ptr<HTTPrequest> self(shared_from_this());
|
||||||
|
|
||||||
|
// Sadly due to the nature of how asio works this entire logic needs to be
|
||||||
|
// mostly in 1 method I do wager that I could break off the whole body
|
||||||
|
// processing into its own thing as well as a lot of inline methods
|
||||||
|
// specifically for argument and header processing
|
||||||
|
|
||||||
|
// TODO: Remove boundary from the body. Do keep other stuff like
|
||||||
|
// file type and name
|
||||||
|
|
||||||
|
// HEADER read
|
||||||
|
asio::async_read_until(
|
||||||
|
sock, buffer, "\r\n\r\n", // its not the other way bud
|
||||||
|
[this, self](std::error_code error, std::size_t packageSize) {
|
||||||
|
if (!error) {
|
||||||
|
buffer.commit(packageSize);
|
||||||
|
std::unordered_map<std::string, std::string> request;
|
||||||
|
std::unordered_map<std::string, std::string> args;
|
||||||
|
std::istream stream(&buffer);
|
||||||
|
uint64_t octetCount = 0;
|
||||||
|
|
||||||
|
// This is HTTP main request
|
||||||
|
std::string rq, key, value, type, path;
|
||||||
|
|
||||||
|
Helpers::getlineAndCount(stream, octetCount, type,
|
||||||
|
' '); // HTTP request type
|
||||||
|
Helpers::getlineAndCount(stream, octetCount, path, ' '); // HTTP path
|
||||||
|
Helpers::getlineAndCount(stream, octetCount,
|
||||||
|
rq); // Version, omitting for now
|
||||||
|
|
||||||
|
// Quick stop to process arguments
|
||||||
|
if (path.find('?') != std::string::npos) {
|
||||||
|
std::stringstream pathStream(path);
|
||||||
|
std::getline(pathStream, path, '?'); // Keeping the path pure
|
||||||
|
|
||||||
|
while (!pathStream.eof()) {
|
||||||
|
std::getline(pathStream, key, '=');
|
||||||
|
std::getline(pathStream, value, '&');
|
||||||
|
args.insert({key, value});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rest of the request vals
|
||||||
|
while (octetCount <
|
||||||
|
packageSize - 2) { // -2 is due to last two \r\n\r\n combo
|
||||||
|
Helpers::getlineAndCount(stream, octetCount, key, ':');
|
||||||
|
Helpers::getlineAndCount(
|
||||||
|
stream, octetCount, rq,
|
||||||
|
' '); // trim start some gangster shit right here
|
||||||
|
Helpers::getlineAndCount(stream, octetCount, value);
|
||||||
|
request.insert({key, value});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================
|
||||||
|
// BODY OF THE REQUEST
|
||||||
|
// ===================
|
||||||
|
if (request.find("Content-Length") != request.end()) {
|
||||||
|
std::size_t uploadSize = std::stoull(request.at("Content-Length")) -
|
||||||
|
buffer.size(),
|
||||||
|
octetCount = 0;
|
||||||
|
|
||||||
|
// This part needs to be sync since we want this specific instance
|
||||||
|
// execution to pause
|
||||||
|
while (octetCount < uploadSize) {
|
||||||
|
octetCount += asio::read(sock, buffer.prepare(uploadSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.commit(octetCount);
|
||||||
|
std::istream bodyStream(&buffer);
|
||||||
|
std::string body;
|
||||||
|
body.resize(buffer.size());
|
||||||
|
bodyStream.read(body.data(), buffer.size());
|
||||||
|
|
||||||
|
buffer.consume(
|
||||||
|
buffer.size()); // Just so the buffer is nice and clean
|
||||||
|
}
|
||||||
|
|
||||||
|
processRequest(type, path, request, args); // This writes data too
|
||||||
|
sock.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
@@ -27,7 +27,8 @@ std::string Helpers::GenerateResponse(std::string statusCode,
|
|||||||
std::string content) {
|
std::string content) {
|
||||||
std::stringstream output;
|
std::stringstream output;
|
||||||
output << "HTTP/1.1 " << statusCode << "\n"
|
output << "HTTP/1.1 " << statusCode << "\n"
|
||||||
<< "Content-Type: " << contentType << "\nConnection: close\n\n"
|
<< "Content-Type: " << contentType
|
||||||
|
<< "\nContent-Length: " << content.size() << "\nConnection: close\n\n"
|
||||||
<< content;
|
<< content;
|
||||||
return output.str();
|
return output.str();
|
||||||
}
|
}
|
||||||
|
@@ -30,7 +30,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
HTTPrequest(asio::io_context &context);
|
HTTPrequest(asio::io_context &context);
|
||||||
void readData();
|
void processHTTPHeader();
|
||||||
void processRequest(std::string requestType, std::string requestPath,
|
void processRequest(std::string requestType, std::string requestPath,
|
||||||
std::unordered_map<std::string, std::string> request,
|
std::unordered_map<std::string, std::string> request,
|
||||||
std::unordered_map<std::string, std::string> args);
|
std::unordered_map<std::string, std::string> args);
|
@@ -1,4 +1,4 @@
|
|||||||
#include "main.hpp"
|
#include "Main.hpp"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
// Webserver is defined at main.hpp, you probably do not want to code here
|
// Webserver is defined at main.hpp, you probably do not want to code here
|
||||||
|
@@ -8,7 +8,8 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<h1>Test</h1>
|
<h1>Welcome</h1>
|
||||||
|
<h1>POST test</h1>
|
||||||
<form action="/upload" method="POST" enctype="multipart/form-data">
|
<form action="/upload" method="POST" enctype="multipart/form-data">
|
||||||
<input type="file" name="uploaded_file">
|
<input type="file" name="uploaded_file">
|
||||||
<input type="submit" value="Upload">
|
<input type="submit" value="Upload">
|
||||||
|
Reference in New Issue
Block a user