Added web server
This commit is contained in:
parent
fe514a3066
commit
5dd892f15c
|
@ -6,6 +6,7 @@ edition = "2021"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
actix-web = "4.4.0"
|
||||||
arti-client = "0.11.0"
|
arti-client = "0.11.0"
|
||||||
eyre = "0.6.8"
|
eyre = "0.6.8"
|
||||||
tokio = { version = "1.34.0", features = ["full"] }
|
tokio = { version = "1.34.0", features = ["full"] }
|
||||||
|
|
113
src/http_lib.rs
113
src/http_lib.rs
|
@ -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!();
|
|
||||||
}
|
|
125
src/main.rs
125
src/main.rs
|
@ -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 arti_client::{TorClient, TorClientConfig};
|
||||||
use eyre::Result;
|
use eyre::{ErrReport, Result};
|
||||||
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||||
|
|
||||||
mod http_lib;
|
mod types;
|
||||||
use http_lib::*;
|
|
||||||
|
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]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
let config = TorClientConfig::default();
|
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(())
|
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
1
src/types.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
|
Loading…
Reference in a new issue