initial
This commit is contained in:
commit
8c3661889f
5 changed files with 273 additions and 0 deletions
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "netlib"]
|
||||||
|
path = netlib
|
||||||
|
url = https://github.com/Lluna4/netlib
|
10
CMakeLists.txt
Normal file
10
CMakeLists.txt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
cmake_minimum_required(VERSION 3.10.0)
|
||||||
|
project(web_serv VERSION 0.1.0 LANGUAGES C CXX)
|
||||||
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
|
|
||||||
|
add_subdirectory(netlib)
|
||||||
|
|
||||||
|
add_executable(web_serv main.cpp)
|
||||||
|
|
||||||
|
target_link_libraries(web_serv PRIVATE netlib)
|
||||||
|
|
79
main.cpp
Normal file
79
main.cpp
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
#include "netlib/src/netlib.h"
|
||||||
|
#include <sys/sendfile.h>
|
||||||
|
#include <print>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
int atoi_newline(const char *data)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
ret += *data - '0';
|
||||||
|
data++;
|
||||||
|
if (*data == '\n' || *data == '\0' || *data == '\r')
|
||||||
|
break;
|
||||||
|
ret *= 10;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
netlib::server_raw server;
|
||||||
|
server.open_server("0.0.0.0", 8080);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
std::vector<int> readable = server.get_readable();
|
||||||
|
for (auto user: readable)
|
||||||
|
{
|
||||||
|
char *data = server.receive_everything(user);
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
std::string_view dat(data);
|
||||||
|
if (dat.starts_with("GET") && dat.size() > 4)
|
||||||
|
{
|
||||||
|
dat.remove_prefix(4);
|
||||||
|
int ins_size = 0;
|
||||||
|
for (auto c: dat)
|
||||||
|
{
|
||||||
|
if (c == ' ')
|
||||||
|
break;
|
||||||
|
ins_size++;
|
||||||
|
}
|
||||||
|
dat.remove_suffix(dat.size() - ins_size);
|
||||||
|
std::println("{}", dat);
|
||||||
|
if (dat.compare("/") == 0)
|
||||||
|
{
|
||||||
|
netlib::send_packet(std::make_tuple(std::string("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n")), user);
|
||||||
|
std::ifstream file("../test.html",std::ios::binary);
|
||||||
|
std::streampos size = file.tellg();
|
||||||
|
file.seekg(0, std::ios::end);
|
||||||
|
size = file.tellg() - size;
|
||||||
|
file.close();
|
||||||
|
int filefd = open("../test.html", O_RDONLY);
|
||||||
|
sendfile(user, filefd, 0, size);
|
||||||
|
}
|
||||||
|
server.disconnect_user(user);
|
||||||
|
}
|
||||||
|
if (dat.starts_with("POST"))
|
||||||
|
{
|
||||||
|
size_t pos = dat.find("Content-Length");
|
||||||
|
dat.remove_prefix(pos);
|
||||||
|
dat.remove_prefix(strlen("Content-Length: "));
|
||||||
|
int lenght = atoi_newline(dat.data());
|
||||||
|
std::println("{} {}", dat, lenght);
|
||||||
|
pos = dat.find("image/png");
|
||||||
|
dat.remove_prefix(pos);
|
||||||
|
dat.remove_prefix(strlen("image/png\r\n") + 2);
|
||||||
|
std::ofstream a("Test.png", std::ios::binary);
|
||||||
|
a.write(dat.data(), lenght);
|
||||||
|
netlib::send_packet(std::make_tuple(std::string("HTTP/1.1 201 CREATED")), user);
|
||||||
|
server.disconnect_user(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||||
|
}
|
||||||
|
}
|
1
netlib
Submodule
1
netlib
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 1dc4578cf1c732065894d961b4ffcb81e12c090d
|
180
test.html
Normal file
180
test.html
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
//THIS IS NOT MY CODE, THIS IS AN AI GENERATED CODE TO TEST MY SERVER AND SEE HOW EVERYTHING WORKS
|
||||||
|
//I WILL CHANGE IT TO MY OWN WHEN MY SERVER WORKS PROPERLY
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Drag and Drop File Upload</title>
|
||||||
|
<style>
|
||||||
|
#drop_zone {
|
||||||
|
border: 5px dashed blue; /* Dashed looks more like a typical drop zone */
|
||||||
|
width: 300px;
|
||||||
|
height: 150px;
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
font-family: sans-serif;
|
||||||
|
line-height: 1.5;
|
||||||
|
transition: border-color 0.3s, background-color 0.3s; /* Add smooth transition */
|
||||||
|
}
|
||||||
|
#drop_zone.dragover { /* Style when dragging over */
|
||||||
|
border-color: green;
|
||||||
|
background-color: #e0ffe0;
|
||||||
|
}
|
||||||
|
#status {
|
||||||
|
margin-top: 15px;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h1>Simple File Upload via Drag & Drop</h1>
|
||||||
|
|
||||||
|
<div
|
||||||
|
id="drop_zone"
|
||||||
|
ondrop="dropHandler(event);"
|
||||||
|
ondragover="dragOverHandler(event);"
|
||||||
|
ondragenter="dragEnterHandler(event);" /* Optional: visual feedback on enter */
|
||||||
|
ondragleave="dragLeaveHandler(event);" /* Optional: visual feedback on leave */
|
||||||
|
>
|
||||||
|
<p>Drag one or more files to this <i>drop zone</i>.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="status"></div> <!-- To display upload status -->
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const dropZone = document.getElementById('drop_zone');
|
||||||
|
const statusDiv = document.getElementById('status');
|
||||||
|
|
||||||
|
function dropHandler(ev) {
|
||||||
|
console.log("File(s) dropped");
|
||||||
|
statusDiv.textContent = 'Processing dropped file(s)...';
|
||||||
|
dropZone.classList.remove('dragover'); // Remove highlight style
|
||||||
|
|
||||||
|
// Prevent default behavior (Prevent file from being opened)
|
||||||
|
ev.preventDefault();
|
||||||
|
|
||||||
|
let filesToUpload = []; // Store files to potentially upload
|
||||||
|
|
||||||
|
if (ev.dataTransfer.items) {
|
||||||
|
// Use DataTransferItemList interface to access the file(s)
|
||||||
|
[...ev.dataTransfer.items].forEach((item, i) => {
|
||||||
|
// If dropped items aren't files, reject them
|
||||||
|
if (item.kind === "file") {
|
||||||
|
const file = item.getAsFile();
|
||||||
|
if (file) { // Check if getAsFile() returned a file
|
||||||
|
console.log(`… file[${i}].name = ${file.name}`);
|
||||||
|
filesToUpload.push(file); // Add file to our list
|
||||||
|
} else {
|
||||||
|
console.log(`… item[${i}] is a file but couldn't be accessed (perhaps a directory?).`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log(`… item[${i}].kind = ${item.kind} (not a file)`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Use DataTransfer interface to access the file(s)
|
||||||
|
[...ev.dataTransfer.files].forEach((file, i) => {
|
||||||
|
console.log(`… file[${i}].name = ${file.name}`);
|
||||||
|
filesToUpload.push(file); // Add file to our list
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- UPLOAD THE FILE(S) ---
|
||||||
|
if (filesToUpload.length > 0) {
|
||||||
|
statusDiv.textContent = `Found ${filesToUpload.length} file(s). Uploading...`;
|
||||||
|
// Example: Uploading the first file found
|
||||||
|
// uploadFile(filesToUpload[0]);
|
||||||
|
|
||||||
|
// OR: Upload ALL dropped files sequentially
|
||||||
|
// (You might want more advanced logic for parallel uploads or progress bars)
|
||||||
|
filesToUpload.forEach(uploadFile);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
console.log("No valid files found to upload.");
|
||||||
|
statusDiv.textContent = 'No valid files detected in drop.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function dragOverHandler(ev) {
|
||||||
|
// Prevent default behavior (Prevent file from being opened)
|
||||||
|
ev.preventDefault();
|
||||||
|
// Optional: Visual feedback
|
||||||
|
// dropZone.classList.add('dragover'); // Handled by dragenter now
|
||||||
|
}
|
||||||
|
|
||||||
|
function dragEnterHandler(ev) {
|
||||||
|
// Optional visual feedback
|
||||||
|
console.log("File entered drop zone");
|
||||||
|
dropZone.classList.add('dragover');
|
||||||
|
ev.preventDefault(); // Necessary for drop event to fire correctly in some browsers
|
||||||
|
}
|
||||||
|
|
||||||
|
function dragLeaveHandler(ev) {
|
||||||
|
// Optional visual feedback
|
||||||
|
console.log("File left drop zone");
|
||||||
|
// Ensure it only removes class if leaving the drop_zone itself, not child elements
|
||||||
|
if (ev.target === dropZone) {
|
||||||
|
dropZone.classList.remove('dragover');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// --- Handles the actual upload ---
|
||||||
|
function uploadFile(file) {
|
||||||
|
// V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V
|
||||||
|
// IMPORTANT: Replace this URL with your actual server endpoint!
|
||||||
|
const url = '/your-server-upload-endpoint';
|
||||||
|
// ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
|
||||||
|
|
||||||
|
const formData = new FormData();
|
||||||
|
|
||||||
|
// 'uploadedFile' is the name the server will look for.
|
||||||
|
// You might need to change this depending on your server-side code.
|
||||||
|
formData.append('uploadedFile', file, file.name);
|
||||||
|
|
||||||
|
console.log(`Uploading ${file.name} to ${url}`);
|
||||||
|
statusDiv.textContent = `Uploading ${file.name}...`; // Update status
|
||||||
|
|
||||||
|
fetch(url, {
|
||||||
|
method: 'POST', // Or 'PUT' depending on your server API
|
||||||
|
body: formData,
|
||||||
|
// Headers are often not needed for FormData uploads,
|
||||||
|
// the browser sets the 'Content-Type' to 'multipart/form-data' automatically.
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
// Throw an error if the server response is not 2xx
|
||||||
|
// Try to get error message from body if possible
|
||||||
|
return response.text().then(text => {
|
||||||
|
throw new Error(`Server responded with ${response.status}: ${response.statusText}. Body: ${text}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Check if the response body is likely JSON or text
|
||||||
|
const contentType = response.headers.get("content-type");
|
||||||
|
if (contentType && contentType.includes("application/json")) {
|
||||||
|
return response.json(); // Parse JSON response
|
||||||
|
} else {
|
||||||
|
return response.text(); // Get response as text
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
console.log(`Upload successful for ${file.name}:`, data);
|
||||||
|
// Add user feedback here
|
||||||
|
statusDiv.textContent = `Successfully uploaded ${file.name}! Server response: ${typeof data === 'object' ? JSON.stringify(data) : data}`;
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error(`Error during upload for ${file.name}:`, error);
|
||||||
|
// Add user feedback here
|
||||||
|
statusDiv.textContent = `Error uploading ${file.name}: ${error.message}`;
|
||||||
|
dropZone.classList.remove('dragover'); // Ensure highlight is removed on error
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Add table
Add a link
Reference in a new issue