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
|
||||
|
||||
[dependencies]
|
||||
actix-web = "4.4.0"
|
||||
arti-client = "0.11.0"
|
||||
eyre = "0.6.8"
|
||||
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 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
1
src/types.rs
Normal file
|
@ -0,0 +1 @@
|
|||
|
Loading…
Reference in a new issue