init
This commit is contained in:
commit
02acb04f65
9 changed files with 582 additions and 0 deletions
10
404.html
Normal file
10
404.html
Normal file
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>404 NOT_FOUND</title>
|
||||
</head>
|
||||
<body>
|
||||
Page not found. Check you typed the address correctly, or contact the site owner.
|
||||
</body>
|
||||
</html>
|
289
Cargo.lock
generated
Normal file
289
Cargo.lock
generated
Normal file
|
@ -0,0 +1,289 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"is_terminal_polyfill",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"once_cell_polyfill",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell_polyfill"
|
||||
version = "1.70.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||
|
||||
[[package]]
|
||||
name = "rust_http_server"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4307e30089d6fd6aff212f2da3a1f9e32f3223b1f010fb09b7c95f90f3ca1e8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.59.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
12
Cargo.toml
Normal file
12
Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "rust_http_server"
|
||||
version = "0.1.0"
|
||||
authors = ["Andromeda"]
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
regex = "1.11.1"
|
||||
clap = { version = "4.5.40", features = ["derive"] }
|
||||
|
||||
[profile.release]
|
||||
opt-level = 3
|
26
flake.lock
generated
Normal file
26
flake.lock
generated
Normal file
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1749794982,
|
||||
"narHash": "sha256-Kh9K4taXbVuaLC0IL+9HcfvxsSUx8dPB5s5weJcc9pc=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "ee930f9755f58096ac6e8ca94a1887e0534e2d81",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"id": "nixpkgs",
|
||||
"ref": "nixos-unstable",
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
12
flake.nix
Normal file
12
flake.nix
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "nixpkgs/nixos-unstable";
|
||||
};
|
||||
outputs = {nixpkgs, ...}: let
|
||||
system = "x86_64-linux";
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
in {
|
||||
packages.${system}.default = pkgs.callPackage ./package.nix {};
|
||||
# nixosModules.${system}.default = ./module.nix;
|
||||
};
|
||||
}
|
11
index.html
Normal file
11
index.html
Normal file
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Test</h1>
|
||||
<p>Does it work?</p>
|
||||
</body>
|
||||
</html>
|
16
package.nix
Normal file
16
package.nix
Normal file
|
@ -0,0 +1,16 @@
|
|||
{rustPlatform, ...}:
|
||||
rustPlatform.buildRustPackage {
|
||||
name = "rust_http_server";
|
||||
src = ./.;
|
||||
cargoLock.lockFile = ./Cargo.lock;
|
||||
nativeBuildInputs = [];
|
||||
buildInputs = [];
|
||||
configurePhase = '''';
|
||||
buildPhase = '''';
|
||||
installPhase = '''';
|
||||
meta = {
|
||||
mainProgram = "rust_http_server";
|
||||
description = "bare minimum, serves the current directory";
|
||||
homepage = "https://mtgmonkey.net";
|
||||
};
|
||||
}
|
116
src/lib.rs
Normal file
116
src/lib.rs
Normal file
|
@ -0,0 +1,116 @@
|
|||
use std::sync::{Arc, Mutex, mpsc};
|
||||
use std::thread;
|
||||
|
||||
pub enum HTTP_RESPONSE_CODE {
|
||||
HTTP_200_OK,
|
||||
HTTP_400_BAD_REQUEST,
|
||||
HTTP_404_NOT_FOUND,
|
||||
HTTP_501_NOT_IMPLEMENTED,
|
||||
HTTP_505_HTTP_VERSION_NOT_SUPPORTED,
|
||||
}
|
||||
impl std::fmt::Debug for HTTP_RESPONSE_CODE {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||
match self {
|
||||
HTTP_RESPONSE_CODE::HTTP_200_OK => write!(f, "HTTP_200_OK"),
|
||||
HTTP_RESPONSE_CODE::HTTP_400_BAD_REQUEST => write!(f, "HTTP_400_BAD_REQUEST"),
|
||||
HTTP_RESPONSE_CODE::HTTP_404_NOT_FOUND => write!(f, "HTTP_404_NOT_FOUND"),
|
||||
HTTP_RESPONSE_CODE::HTTP_501_NOT_IMPLEMENTED => write!(f, "HTTP_501_NOT_IMPLEMENTED"),
|
||||
HTTP_RESPONSE_CODE::HTTP_505_HTTP_VERSION_NOT_SUPPORTED => {
|
||||
write!(f, "HTTP_505_HTTP_VERSION_NOT_SUPPORTED")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
impl std::fmt::Display for HTTP_RESPONSE_CODE {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||
match self {
|
||||
HTTP_RESPONSE_CODE::HTTP_200_OK => write!(f, "200 OK"),
|
||||
HTTP_RESPONSE_CODE::HTTP_400_BAD_REQUEST => write!(f, "400 BAD REQUEST"),
|
||||
HTTP_RESPONSE_CODE::HTTP_404_NOT_FOUND => write!(f, "404 NOT FOUND"),
|
||||
HTTP_RESPONSE_CODE::HTTP_501_NOT_IMPLEMENTED => write!(f, "501 NOT IMPLEMENTED"),
|
||||
HTTP_RESPONSE_CODE::HTTP_505_HTTP_VERSION_NOT_SUPPORTED => {
|
||||
write!(f, "HTTP_505_HTTP_VERSION_NOT_SUPPORTED")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ThreadPool {
|
||||
workers: Vec<Worker>,
|
||||
sender: Option<mpsc::Sender<Job>>,
|
||||
}
|
||||
impl ThreadPool {
|
||||
pub fn new(size: usize) -> ThreadPool {
|
||||
assert!(size > 0);
|
||||
let (sender, receiver) = mpsc::channel();
|
||||
let receiver = Arc::new(Mutex::new(receiver));
|
||||
let mut workers = Vec::with_capacity(size);
|
||||
for id in 0..size {
|
||||
workers.push(Worker::new(id, Arc::clone(&receiver)));
|
||||
}
|
||||
ThreadPool {
|
||||
workers,
|
||||
sender: Some(sender),
|
||||
}
|
||||
}
|
||||
pub fn execute<F>(&self, f: F)
|
||||
where
|
||||
F: FnOnce() + Send + 'static,
|
||||
{
|
||||
let job = Box::new(f);
|
||||
match self.sender.as_ref() {
|
||||
Some(sender) => match sender.send(job) {
|
||||
Ok(_) => {}
|
||||
Err(e) => println!("[ERROR]: {e}"),
|
||||
},
|
||||
None => println!("[ERROR] no sender to execute!"),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Drop for ThreadPool {
|
||||
fn drop(&mut self) {
|
||||
drop(self.sender.take());
|
||||
for worker in self.workers.drain(..) {
|
||||
println!("Shutting down worker {}", worker.id);
|
||||
match worker.thread.join() {
|
||||
Ok(join) => join,
|
||||
Err(_) => println!(
|
||||
"Failed to join thread while shutting down worker {}",
|
||||
worker.id
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type Job = Box<dyn FnOnce() + Send + 'static>;
|
||||
|
||||
struct Worker {
|
||||
id: usize,
|
||||
thread: thread::JoinHandle<()>,
|
||||
}
|
||||
impl Worker {
|
||||
fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker {
|
||||
let thread = thread::spawn(move || {
|
||||
loop {
|
||||
match receiver.lock() {
|
||||
Ok(receiver) => {
|
||||
let message = receiver.recv();
|
||||
match message {
|
||||
Ok(job) => {
|
||||
println!("Worker {id} got a job, executing.");
|
||||
job();
|
||||
}
|
||||
Err(_) => {
|
||||
println!("Worker {id} disconnected, shutting down.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => println!("[ERROR]: {e}"),
|
||||
}
|
||||
}
|
||||
});
|
||||
Worker { id, thread }
|
||||
}
|
||||
}
|
90
src/main.rs
Normal file
90
src/main.rs
Normal file
|
@ -0,0 +1,90 @@
|
|||
use clap::Parser;
|
||||
use regex::Regex;
|
||||
use rust_http_server::HTTP_RESPONSE_CODE::*;
|
||||
use rust_http_server::*;
|
||||
use std::fs;
|
||||
use std::io::{BufReader, prelude::*};
|
||||
use std::net::{SocketAddr, TcpListener, TcpStream};
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(version, about, long_about = None)]
|
||||
struct Args {
|
||||
#[arg(short, long, default_value_t = 8383)]
|
||||
port: u16,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args = Args::parse();
|
||||
let listener = TcpListener::bind(SocketAddr::from(([127, 0, 0, 1], args.port)))
|
||||
.expect(&format!("Failed to bind to port {}", args.port));
|
||||
println!("Successfully started server at port {}", args.port);
|
||||
let pool = ThreadPool::new(8);
|
||||
for stream in listener.incoming() {
|
||||
pool.execute(|| {
|
||||
handle_connection(stream.unwrap());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_connection(stream: TcpStream) {
|
||||
let contents = match parse_connection_to_header(&stream) {
|
||||
Ok(request) => {
|
||||
println!("Request: {request}");
|
||||
match parse_header_to_filepath(request) {
|
||||
Ok(filepath) => read_file(filepath),
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
Err(err) => Err(err),
|
||||
};
|
||||
respond(&stream, contents);
|
||||
}
|
||||
|
||||
fn parse_connection_to_header(stream: &TcpStream) -> Result<String, HTTP_RESPONSE_CODE> {
|
||||
// read first line of buffer
|
||||
let buf_reader = BufReader::new(stream);
|
||||
match buf_reader.lines() {
|
||||
mut lines => match lines.next() {
|
||||
Some(Ok(line)) => Ok(line),
|
||||
_ => Err(HTTP_400_BAD_REQUEST),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_header_to_filepath(request: String) -> Result<String, HTTP_RESPONSE_CODE> {
|
||||
let regex = Regex::new(r"GET /(?<path>[^/].*|) HTTP/1\.1").unwrap();
|
||||
match regex.captures(&request) {
|
||||
Some(captures) => Ok(captures["path"].to_string()),
|
||||
None => Err(HTTP_400_BAD_REQUEST),
|
||||
}
|
||||
}
|
||||
|
||||
fn read_file(filename: String) -> Result<String, HTTP_RESPONSE_CODE> {
|
||||
match fs::read_to_string(if filename == "" {
|
||||
"index.html"
|
||||
} else {
|
||||
&filename
|
||||
}) {
|
||||
Ok(file) => Ok(file),
|
||||
Err(_) => Err(HTTP_404_NOT_FOUND),
|
||||
}
|
||||
}
|
||||
|
||||
fn respond(mut stream: &TcpStream, contents: Result<String, HTTP_RESPONSE_CODE>) {
|
||||
let (status, length, contents) = match contents {
|
||||
Ok(contents) =>
|
||||
( format!("HTTP/1.1 {HTTP_200_OK}")
|
||||
, contents.len()
|
||||
, contents
|
||||
),
|
||||
Err(err) =>
|
||||
( format!("HTTP/1.1 {err}")
|
||||
, "<!DOCTYPE html><html><head><meta charset=\"utf-8\"><title>404 NOT FOUND</title></head><body>Page not found. Check that you typed the address correctly, or contact the site owner.</body></html>".len()
|
||||
, "<!DOCTYPE html><html><head><meta charset=\"utf-8\"><title>404 NOT FOUND</title></head><body>Page not found. Check that you typed the address correctly, or contact the site owner.</body></html>".to_string()
|
||||
),
|
||||
};
|
||||
println!("Response: {status}\r\nContent-Length: {length}\r\n\r\n{contents}");
|
||||
stream
|
||||
.write_all(format!("{status}\r\nContent-Length: {length}\r\n\r\n{contents}").as_bytes())
|
||||
.expect("Error writing to stream");
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue