rust implementation
This commit is contained in:
81
src/main.rs
Normal file
81
src/main.rs
Normal file
@@ -0,0 +1,81 @@
|
||||
use std::{net::SocketAddr, sync::Arc};
|
||||
|
||||
use anyhow::Context;
|
||||
use axum::{routing::any, Router};
|
||||
use dotenvy::dotenv;
|
||||
use tracing::{error, info, level_filters::LevelFilter};
|
||||
use tracing_subscriber::{fmt, prelude::*, EnvFilter};
|
||||
|
||||
mod crypto;
|
||||
mod proxy;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AppState {
|
||||
pub client: reqwest::Client,
|
||||
pub target_url: reqwest::Url,
|
||||
pub key: String,
|
||||
pub iv: String,
|
||||
}
|
||||
|
||||
const DEFAULT_TARGET_URL: &str = "https://cloud.linspirer.com:883";
|
||||
const DEFAULT_HOST: &str = "0.0.0.0";
|
||||
const DEFAULT_PORT: &str = "8080";
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
// Load environment variables from .env file
|
||||
dotenv().ok();
|
||||
|
||||
// Set up logging
|
||||
tracing_subscriber::registry()
|
||||
.with(fmt::layer())
|
||||
.with(
|
||||
EnvFilter::builder()
|
||||
.with_default_directive(LevelFilter::INFO.into())
|
||||
.from_env_lossy(),
|
||||
)
|
||||
.init();
|
||||
|
||||
// Load configuration from environment
|
||||
let key = std::env::var("LINSPIRER_KEY").context("LINSPIRER_KEY must be set")?;
|
||||
let iv = std::env::var("LINSPIRER_IV").context("LINSPIRER_IV must be set")?;
|
||||
let target_url_str = std::env::var("LINSPIRER_TARGET_URL");
|
||||
let target_url_str = target_url_str.as_deref().unwrap_or(DEFAULT_TARGET_URL);
|
||||
let target_url = reqwest::Url::parse(target_url_str)?;
|
||||
|
||||
let host_str = std::env::var("LINSPIRER_HOST");
|
||||
let host = host_str.as_deref().unwrap_or(DEFAULT_HOST);
|
||||
let port_str = std::env::var("LINSPIRER_PORT");
|
||||
let port = port_str.as_deref().unwrap_or(DEFAULT_PORT);
|
||||
let addr_str = format!("{}:{}", host, port);
|
||||
let addr: SocketAddr = addr_str
|
||||
.parse()
|
||||
.context(format!("Invalid address format: {}", addr_str))?;
|
||||
|
||||
// Create a reqwest client that ignores SSL certificate verification
|
||||
let client = reqwest::Client::builder()
|
||||
.danger_accept_invalid_certs(true)
|
||||
.build()?;
|
||||
|
||||
// Create shared state
|
||||
let state = Arc::new(AppState {
|
||||
client,
|
||||
target_url,
|
||||
key,
|
||||
iv,
|
||||
});
|
||||
|
||||
// Build our application with a single route
|
||||
let app = Router::new()
|
||||
.route("/{*path}", any(proxy::proxy_handler))
|
||||
.with_state(state);
|
||||
|
||||
// Run the server
|
||||
info!("Proxy started on {} => {}", addr_str, target_url_str);
|
||||
let listener = tokio::net::TcpListener::bind(&addr).await?;
|
||||
if let Err(e) = axum::serve(listener, app.into_make_service()).await {
|
||||
error!("Server error: {}", e);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user