commit eff065466a332d7dd6698761ab612c2d9a567174 Author: Snorre Date: Wed Feb 5 01:15:33 2025 +0100 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..48aa698 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "webbisitey" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..57dda76 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "webbisitey" +version = "0.1.0" +edition = "2024" diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..00a1d18 --- /dev/null +++ b/flake.lock @@ -0,0 +1,48 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1738546358, + "narHash": "sha256-nLivjIygCiqLp5QcL7l56Tca/elVqM9FG1hGd9ZSsrg=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "c6e957d81b96751a3d5967a0fd73694f303cc914", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs", + "rust-overlay": "rust-overlay" + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1738635966, + "narHash": "sha256-5MbJhh6nz7tx8FYVOJ0+ixMaEn0ibGzV/hScPMmqVTE=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "1ff8663cd75a11e61f8046c62f4dbb05d1907b44", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..50c4988 --- /dev/null +++ b/flake.nix @@ -0,0 +1,37 @@ +{ + description = "Flake for mc rust proxy"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; + rust-overlay = { + url = "github:oxalica/rust-overlay"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = { + self, + nixpkgs, + rust-overlay, + }: let + # rust-overlay = import rust-overlay; + pkgs = + import nixpkgs + { + system = "x86_64-linux"; + overlays = [rust-overlay.overlays.default]; + }; + in { + devShells.x86_64-linux.default = pkgs.mkShell { + buildInputs = with pkgs; [ + rust-bin.nightly.latest.default + rust-analyzer + ]; + + # shellHook = '' + # echo "Hello from nix dev shell" + # ''; + }; + formatter.x86_64-linux = pkgs.alejandra; + }; +} diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..6d85d95 --- /dev/null +++ b/public/index.html @@ -0,0 +1,133 @@ + + + + + + + + +
+
something something snorre.net
+ +
content
+
content
+
content
+ + + + +
+
+ + + + diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..c05caf5 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,95 @@ +use std::{ + env::current_dir, + io::{BufRead, BufReader, Write}, + net::{TcpListener, TcpStream}, + path::PathBuf, +}; + +static CLRF: &str = "\r\n"; + +fn main() { + let listener = + TcpListener::bind("0.0.0.0:8080").expect("Failed to create TcpListener on 0.0.0.0:8080"); + + for stream in listener.incoming() { + let mut stream = stream.unwrap(); // safe because TcpListener::incoming never returns None. + + handle_connection(stream); + } +} + +#[derive(Debug)] +enum RequestMethod { + GET, + POST, +} +#[derive(Debug)] +struct Request { + method: RequestMethod, + path: Option, +} +impl Request { + pub fn from(string: &str) -> Self { + let mut parts = string.split(" "); + + Self { + method: match parts.next().expect("Invalid request") { + "GET" => RequestMethod::GET, + "POST" => RequestMethod::POST, + _ => panic!("Unknown method"), + }, + path: Some(parts.next().expect("Invalid request").to_string()), + } + } + pub fn file(&self) -> Option { + if self.path == None { + return None; + } + + let mut path = PathBuf::new(); + path.push("public"); + + path.push( + PathBuf::from(self.path.as_ref().unwrap()) + .strip_prefix("/") + .expect("Failed to strip prefix"), + ); + + if path.extension() == None { + path.push("index.html"); + } + + let mut cwd = current_dir().expect("Failed to get CWD"); + cwd.push(path); + Some(cwd) + } +} + +fn handle_connection(mut stream: TcpStream) { + let buf_reader = BufReader::new(&stream); + let http_request: Vec<_> = buf_reader + .lines() + .map(|result| result.unwrap()) + .take_while(|line| !line.is_empty()) + .collect(); + + println!("Request: {http_request:#?}"); + + if http_request.len() == 0 { + return; + } + + let req = Request::from(http_request.get(0).expect("Empty request")); + + println!("Requested file: {:#?}", req.file()); + + let response = match req.file() { + Some(path) => match std::fs::read_to_string(path) { + Ok(content) => format!("HTTP/1.1 200 OK{0}Content-Length: {1}{0}{0}{content}", CLRF, content.len()), + Err(e) => format!("HTTP/1.1 500{0}{0}{e}", CLRF), + } + None => format!("HTTP/1.1 500{0}{0}", CLRF), + }; + + stream.write_all(response.as_bytes()).unwrap(); +}