Added web server

This commit is contained in:
vanten-s 2023-11-22 10:13:00 +01:00
parent fe514a3066
commit 5dd892f15c
Signed by: vanten-s
GPG key ID: DE3060396884D3F2
4 changed files with 111 additions and 129 deletions

View file

@ -6,6 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
actix-web = "4.4.0"
arti-client = "0.11.0"
eyre = "0.6.8"
tokio = { version = "1.34.0", features = ["full"] }

View file

@ -1,113 +0,0 @@
use arti_client::TorClient;
use eyre::Result;
use tokio::io::{AsyncWriteExt, AsyncReadExt};
trait Serialize {
fn serialize(&self) -> Vec<u8>;
}
#[derive(Clone, Debug)]
pub struct HTTPRequest {
pub method: HTTPMethod,
pub location: String,
pub version: String,
pub headers: Vec<HTTPHeader>,
pub body: Option<Vec<u8>>,
}
#[derive(Clone, Debug)]
pub struct HTTPResponse {
pub version: String,
pub status_code: u16,
pub status: String,
pub headers: Vec<HTTPHeader>,
pub body: Option<Vec<u8>>,
}
#[derive(Clone, Copy, Debug)]
pub enum HTTPMethod {
Get,
}
#[derive(Clone, Debug)]
pub struct HTTPHeader {
pub key: String,
pub value: String,
}
impl Serialize for HTTPRequest {
fn serialize(&self) -> Vec<u8> {
let mut result = vec![];
let mut method_vec_u8 = self.method.serialize();
let mut location_vec_u8 = self.location.as_bytes().to_vec();
let mut version_vec_u8 = self.version.as_bytes().to_vec();
let mut headers = self
.headers
.iter()
.map(|x| x.serialize())
.collect::<Vec<_>>()
.concat();
result.append(&mut method_vec_u8);
result.push(b' ');
result.append(&mut location_vec_u8);
result.push(b' ');
result.append(&mut version_vec_u8);
result.append(&mut headers);
result.push(b'\n');
result.push(b'\n');
if let Some(body) = &self.body {
let mut body = body.clone();
result.append(&mut body)
}
println!("{}", match String::from_utf8(result.clone()) {
Ok(v) => v,
Err(v) => format!("{}", v),
});
result
}
}
impl Serialize for HTTPMethod {
fn serialize(&self) -> Vec<u8> {
use HTTPMethod as M;
match self {
M::Get => b"GET"
}.to_vec()
}
}
impl Serialize for HTTPHeader {
fn serialize(&self) -> Vec<u8> {
format!("\n{}: {}", self.key, self.value).into_bytes()
}
}
pub async fn get_website(
address: &str,
port: u16,
request: HTTPRequest,
tor_client: TorClient<tor_rtcompat::PreferredRuntime>,
) -> Result<Vec<u8>> {
let mut stream = tor_client.connect((address, port)).await?;
stream.write_all(&request.serialize()).await?;
stream.flush().await?;
println!("Sent request for {} to {address}", request.location);
let mut response_status: Vec<u8> = Vec::new();
loop {
let response = stream.read_u8().await?;
response_status.push(dbg!(response));
if response == b'\n' {
break;
}
}
let _ = dbg!(String::from_utf8(response_status));
todo!();
}

View file

@ -1,26 +1,119 @@
use actix_web::{
get, post,
web::{self, BufMut},
App, HttpRequest, HttpResponse, HttpServer, Responder, HttpResponseBuilder, http::StatusCode,
};
use arti_client::{TorClient, TorClientConfig};
use eyre::Result;
use eyre::{ErrReport, Result};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
mod http_lib;
use http_lib::*;
mod types;
struct State {
tor_client: TorClient<tor_rtcompat::PreferredRuntime>,
}
#[get("/{tail:.*}")]
async fn get(req: HttpRequest, data: web::Data<State>, path: web::Path<String>) -> impl Responder {
let tail = "/".to_string() + &path.into_inner();
let host = match req.uri().host() {
Some(v) => v.replace(".vanten-s.com", ""),
None => return HttpResponse::InternalServerError().body("How did you manage to get an invalid URI??")
};
let raw_website_response = match get_website(&host, 80, &req, None, &data.tor_client).await {
Ok(v) => v,
Err(e) => return HttpResponse::InternalServerError().body(format!("hihi, {e}")),
};
HttpResponse::Ok().body("Hi!")
}
#[tokio::main]
async fn main() -> Result<()> {
let config = TorClientConfig::default();
let tor_client = TorClient::create_bootstrapped(config).await?;
println!("Tor Client Created!");
let test_request = HTTPRequest {
method: HTTPMethod::Get,
location: "/".to_string(),
version: "HTTP/1.1".to_string(),
headers: vec![HTTPHeader {
key: "Host".to_string(),
value: "vanten-s.com".to_string(),
}],
body: None,
};
dbg!(get_website("94.255.138.67", 80, test_request, tor_client).await?);
let tor_client = TorClient::create_bootstrapped(config).await?;
let server = HttpServer::new(move || App::new().app_data(State { tor_client: tor_client.clone() }).service(get))
.bind(("127.0.0.1", 8080))?
.run();
let server = server.await;
println!("Everything Started!");
Ok(())
}
async fn get_website(
address: &str,
port: u16,
request: &HttpRequest,
body: Option<String>,
tor_client: &TorClient<tor_rtcompat::PreferredRuntime>,
) -> Result<Vec<u8>> {
let mut stream = tor_client.connect((address, port)).await?;
stream.write_all(&request_to_bytes(request, body)?).await?;
stream.flush().await?;
println!("Sent request to {address}");
let mut response_status: Vec<u8> = Vec::new();
loop {
let response = stream.read_u8().await?;
response_status.push(dbg!(response));
if response == b'\n' {
break;
}
}
let _ = dbg!(String::from_utf8(response_status));
todo!();
}
fn request_to_bytes(request: &HttpRequest, body: Option<String>) -> Result<Vec<u8>> {
let mut finished = vec![];
// First Line
{
use actix_web::http::Version as V;
let method = request.method().to_string().as_bytes();
let path = request.path().as_bytes();
let version = match request.version() {
V::HTTP_09 => "HTTP/0.9",
V::HTTP_10 => "HTTP/1",
V::HTTP_11 => "HTTP/1.1",
V::HTTP_2 => "HTTP/2",
V::HTTP_3 => "HTTP/3",
}
.as_bytes();
finished.put_slice(method);
finished.push(b' ');
finished.put_slice(path);
finished.push(b' ');
finished.put_slice(version);
finished.push(b'\n');
}
// Headers
{
for header in request.headers() {
let name = header.0.to_string().as_bytes();
let value = header.1.as_bytes();
finished.put_slice(name);
finished.put_slice(b": ");
finished.put_slice(value);
finished.push(b'\n');
}
finished.push(b'\n');
}
match body {
Some(v) => finished.put_slice(v.as_bytes()),
None => {},
}
Ok(finished)
}

1
src/types.rs Normal file
View file

@ -0,0 +1 @@