First working proxy!

proxy
Jef Roosens 2021-11-26 20:49:45 +01:00
parent 1ed62dc18c
commit 84b9afbd1b
Signed by: Jef Roosens
GPG Key ID: B580B976584B5F30
3 changed files with 49 additions and 21 deletions

10
Cargo.lock generated
View File

@ -1167,6 +1167,7 @@ dependencies = [
"diesel", "diesel",
"diesel_migrations", "diesel_migrations",
"figment", "figment",
"futures",
"hmac", "hmac",
"jwt", "jwt",
"mimalloc", "mimalloc",
@ -1512,9 +1513,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.71" version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "063bf466a64011ac24040a49009724ee60a57da1b437617ceb32e53ad61bfb19" checksum = "d0ffa0837f2dfa6fb90868c2b5468cad482e175f7dad97e7421951e663f2b527"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
@ -1694,9 +1695,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.81" version = "1.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2afee18b8beb5a596ecb4a2dce128c719b4ba399d34126b9e4396e3f9860966" checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1848,6 +1849,7 @@ checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-core", "futures-core",
"futures-io",
"futures-sink", "futures-sink",
"log", "log",
"pin-project-lite", "pin-project-lite",

View File

@ -40,8 +40,9 @@ base64 = "0.13.0"
figment = { version = "*", features = [ "yaml" ] } figment = { version = "*", features = [ "yaml" ] }
mimalloc = { version = "0.1.26", default_features = false } mimalloc = { version = "0.1.26", default_features = false }
reqwest = { version = "0.11.6", features = [ "stream" ] } reqwest = { version = "0.11.6", features = [ "stream" ] }
tokio-util = {version="*", features=["io"]} tokio-util = {version="*", features=["compat"]}
bytes = "*" bytes = "*"
futures = "0.3.18"
[profile.dev] [profile.dev]
lto = "off" lto = "off"

View File

@ -1,16 +1,21 @@
use std::path::{Path, PathBuf}; use std::{
io::Cursor,
path::{Path, PathBuf},
};
use futures::stream::TryStreamExt;
use reqwest::{ use reqwest::{
header::{HeaderMap, HeaderName, HeaderValue}, header::{HeaderMap, HeaderName, HeaderValue},
Method as ReqMethod, Method as ReqMethod,
}; };
use rocket::{ use rocket::{
response::stream::ByteStream,
data::ToByteUnit, data::ToByteUnit,
http::{Header, Method}, http::{Header, Method},
response::{Redirect}, response::{stream::ByteStream, Redirect},
route::{Handler, Outcome}, route::{Handler, Outcome},
Data, Request, Route, Data, Request, Route,
}; };
use tokio_util::compat::FuturesAsyncReadCompatExt;
#[derive(Clone)] #[derive(Clone)]
pub struct ProxyServer pub struct ProxyServer
@ -26,7 +31,11 @@ impl ProxyServer
pub fn new<P: AsRef<Path>>(root: &str, prefix: P, rank: isize) -> Self pub fn new<P: AsRef<Path>>(root: &str, prefix: P, rank: isize) -> Self
{ {
ProxyServer { root: String::from(root), prefix: prefix.as_ref().into(), rank } ProxyServer {
root: String::from(root),
prefix: prefix.as_ref().into(),
rank,
}
} }
pub fn from<P: AsRef<Path>>(root: &str, prefix: P) -> Self pub fn from<P: AsRef<Path>>(root: &str, prefix: P) -> Self
@ -51,8 +60,15 @@ impl Into<Vec<Route>> for ProxyServer
for method in METHODS { for method in METHODS {
let mut route = Route::ranked(self.rank, method, "/<path..>", self.clone()); let mut route = Route::ranked(self.rank, method, "/<path..>", self.clone());
route.name = route.name = Some(
Some(format!("ProxyServer: {} {}{}", method.as_str(), self.root.clone(), self.prefix.to_str().unwrap()).into()); format!(
"ProxyServer: {} {}{}",
method.as_str(),
self.root.clone(),
self.prefix.to_str().unwrap()
)
.into(),
);
routes.push(route); routes.push(route);
} }
@ -94,7 +110,10 @@ impl Handler for ProxyServer
// We first extract all URL segments starting from the mountpoint // We first extract all URL segments starting from the mountpoint
let segments: PathBuf = req.segments(0..).unwrap(); let segments: PathBuf = req.segments(0..).unwrap();
let query_part = req.uri().query().map_or(String::from(""), |s| format!("?{}", s)); let query_part = req
.uri()
.query()
.map_or(String::from(""), |s| format!("?{}", s));
let url = format!( let url = format!(
"{}{}/{}{}", "{}{}/{}{}",
@ -123,19 +142,25 @@ impl Handler for ProxyServer
.send() .send()
.await .await
.unwrap(); .unwrap();
println!("{:?}", new_res); let mut res_headers = new_res.headers().clone();
let mut res_builder = rocket::Response::build(); let mut res_builder = rocket::Response::build();
let mut res_builder = res_builder.status(rocket::http::Status::new(new_res.status().as_u16())); let mut res_builder = res_builder
// .streamed_body(ByteStream::from(new_res.bytes_stream())); .status(rocket::http::Status::new(new_res.status().as_u16()))
.streamed_body(
// reqwest headers -> rocket headers new_res
for (key, value) in new_res.headers().clone().iter_mut() { .bytes_stream()
res_builder = res_builder.raw_header( .map_err(|e| futures::io::Error::new(futures::io::ErrorKind::Other, e))
String::from(key.clone().as_str()), .into_async_read()
String::from(value.clone().to_str().unwrap()) .compat(),
); );
// reqwest headers -> rocket headers
for (key, value) in res_headers.iter_mut() {
res_builder = res_builder.raw_header(
String::from(key.clone().as_str()),
String::from(value.clone().to_str().unwrap()),
);
} }
Outcome::Success(res_builder.finalize()) Outcome::Success(res_builder.finalize())