Use tracing; use cow for hop redirects
This commit is contained in:
parent
72e672bc73
commit
0144cf5f50
1 changed files with 19 additions and 21 deletions
|
@ -1,7 +1,7 @@
|
||||||
use crate::config::{Route as ConfigRoute, RouteType};
|
use crate::config::{Route as ConfigRoute, RouteType};
|
||||||
use crate::{template_args, BunBunError, Route, State};
|
use crate::{template_args, BunBunError, Route, State};
|
||||||
use arc_swap::ArcSwap;
|
use arc_swap::ArcSwap;
|
||||||
use axum::body::{boxed, Bytes, Full};
|
use axum::body::{boxed, Bytes, Empty, Full};
|
||||||
use axum::extract::Query;
|
use axum::extract::Query;
|
||||||
use axum::http::{header, StatusCode};
|
use axum::http::{header, StatusCode};
|
||||||
use axum::response::{Html, IntoResponse, Response};
|
use axum::response::{Html, IntoResponse, Response};
|
||||||
|
@ -9,6 +9,7 @@ use axum::Extension;
|
||||||
use handlebars::Handlebars;
|
use handlebars::Handlebars;
|
||||||
use percent_encoding::{utf8_percent_encode, AsciiSet, CONTROLS};
|
use percent_encoding::{utf8_percent_encode, AsciiSet, CONTROLS};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
@ -88,7 +89,7 @@ pub async fn hop(
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
let data = data.load();
|
let data = data.load();
|
||||||
|
|
||||||
match resolve_hop(&query.to, &data.routes, &data.default_route) {
|
match resolve_hop(&query.to, &data.routes, data.default_route.as_deref()) {
|
||||||
RouteResolution::Resolved { route: path, args } => {
|
RouteResolution::Resolved { route: path, args } => {
|
||||||
let resolved_template = match path {
|
let resolved_template = match path {
|
||||||
ConfigRoute {
|
ConfigRoute {
|
||||||
|
@ -100,7 +101,7 @@ pub async fn hop(
|
||||||
route_type: RouteType::External,
|
route_type: RouteType::External,
|
||||||
path,
|
path,
|
||||||
..
|
..
|
||||||
} => Ok(HopAction::Redirect(path.clone())),
|
} => Ok(HopAction::Redirect(Cow::Borrowed(path))),
|
||||||
};
|
};
|
||||||
|
|
||||||
match resolved_template {
|
match resolved_template {
|
||||||
|
@ -113,8 +114,8 @@ pub async fn hop(
|
||||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||||
Response::builder()
|
Response::builder()
|
||||||
.status(StatusCode::FOUND)
|
.status(StatusCode::FOUND)
|
||||||
.header(header::LOCATION, &path)
|
.header(header::LOCATION, rendered)
|
||||||
.body(boxed(Full::from(rendered)))
|
.body(boxed(Empty::new()))
|
||||||
}
|
}
|
||||||
Ok(HopAction::Body(body)) => Response::builder()
|
Ok(HopAction::Body(body)) => Response::builder()
|
||||||
.status(StatusCode::OK)
|
.status(StatusCode::OK)
|
||||||
|
@ -149,7 +150,7 @@ enum RouteResolution<'a> {
|
||||||
fn resolve_hop<'a>(
|
fn resolve_hop<'a>(
|
||||||
query: &str,
|
query: &str,
|
||||||
routes: &'a HashMap<String, Route>,
|
routes: &'a HashMap<String, Route>,
|
||||||
default_route: &Option<String>,
|
default_route: Option<&str>,
|
||||||
) -> RouteResolution<'a> {
|
) -> RouteResolution<'a> {
|
||||||
let mut split_args = query.split_ascii_whitespace().peekable();
|
let mut split_args = query.split_ascii_whitespace().peekable();
|
||||||
let maybe_route = {
|
let maybe_route = {
|
||||||
|
@ -209,8 +210,8 @@ const fn check_route(route: &Route, arg_count: usize) -> bool {
|
||||||
|
|
||||||
#[derive(Deserialize, Debug, PartialEq, Eq)]
|
#[derive(Deserialize, Debug, PartialEq, Eq)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
enum HopAction {
|
enum HopAction<'a> {
|
||||||
Redirect(String),
|
Redirect(Cow<'a, str>),
|
||||||
Body(String),
|
Body(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,13 +219,13 @@ enum HopAction {
|
||||||
/// so long as the executable was successfully executed. Returns an Error if the
|
/// so long as the executable was successfully executed. Returns an Error if the
|
||||||
/// file doesn't exist or bunbun did not have permission to read and execute the
|
/// file doesn't exist or bunbun did not have permission to read and execute the
|
||||||
/// file.
|
/// file.
|
||||||
fn resolve_path(path: &Path, args: &str) -> Result<HopAction, BunBunError> {
|
fn resolve_path(path: &Path, args: &str) -> Result<HopAction<'static>, BunBunError> {
|
||||||
let output = Command::new(path.canonicalize()?)
|
let output = Command::new(path.canonicalize()?)
|
||||||
.args(args.split(' '))
|
.args(args.split(' '))
|
||||||
.output()?;
|
.output()?;
|
||||||
|
|
||||||
if output.status.success() {
|
if output.status.success() {
|
||||||
Ok(serde_json::from_slice(&output.stdout[..])?)
|
Ok(serde_json::from_slice(&output.stdout)?)
|
||||||
} else {
|
} else {
|
||||||
error!(
|
error!(
|
||||||
"Program exit code for {} was not 0! Dumping standard error!",
|
"Program exit code for {} was not 0! Dumping standard error!",
|
||||||
|
@ -250,7 +251,7 @@ mod resolve_hop {
|
||||||
#[test]
|
#[test]
|
||||||
fn empty_routes_no_default_yields_failed_hop() {
|
fn empty_routes_no_default_yields_failed_hop() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_hop("hello world", &HashMap::new(), &None),
|
resolve_hop("hello world", &HashMap::new(), None),
|
||||||
RouteResolution::Unresolved
|
RouteResolution::Unresolved
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -258,11 +259,7 @@ mod resolve_hop {
|
||||||
#[test]
|
#[test]
|
||||||
fn empty_routes_some_default_yields_failed_hop() {
|
fn empty_routes_some_default_yields_failed_hop() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_hop(
|
resolve_hop("hello world", &HashMap::new(), Some(&"google")),
|
||||||
"hello world",
|
|
||||||
&HashMap::new(),
|
|
||||||
&Some(String::from("google"))
|
|
||||||
),
|
|
||||||
RouteResolution::Unresolved
|
RouteResolution::Unresolved
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -272,7 +269,7 @@ mod resolve_hop {
|
||||||
let mut map: HashMap<String, Route> = HashMap::new();
|
let mut map: HashMap<String, Route> = HashMap::new();
|
||||||
map.insert("google".into(), Route::from("https://example.com"));
|
map.insert("google".into(), Route::from("https://example.com"));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_hop("hello world", &map, &Some(String::from("google"))),
|
resolve_hop("hello world", &map, Some("google")),
|
||||||
generate_route_result(&Route::from("https://example.com"), "hello world"),
|
generate_route_result(&Route::from("https://example.com"), "hello world"),
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -283,7 +280,7 @@ mod resolve_hop {
|
||||||
let mut map: HashMap<String, Route> = HashMap::new();
|
let mut map: HashMap<String, Route> = HashMap::new();
|
||||||
map.insert("google".into(), Route::from("https://example.com"));
|
map.insert("google".into(), Route::from("https://example.com"));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_hop("google hello world", &map, &Some(String::from("a"))),
|
resolve_hop("google hello world", &map, Some("a")),
|
||||||
generate_route_result(&Route::from("https://example.com"), "hello world"),
|
generate_route_result(&Route::from("https://example.com"), "hello world"),
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -294,7 +291,7 @@ mod resolve_hop {
|
||||||
let mut map: HashMap<String, Route> = HashMap::new();
|
let mut map: HashMap<String, Route> = HashMap::new();
|
||||||
map.insert("google".into(), Route::from("https://example.com"));
|
map.insert("google".into(), Route::from("https://example.com"));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_hop("google hello world", &map, &None),
|
resolve_hop("google hello world", &map, None),
|
||||||
generate_route_result(&Route::from("https://example.com"), "hello world"),
|
generate_route_result(&Route::from("https://example.com"), "hello world"),
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -358,6 +355,7 @@ mod resolve_path {
|
||||||
|
|
||||||
use super::{resolve_path, HopAction};
|
use super::{resolve_path, HopAction};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::env::current_dir;
|
use std::env::current_dir;
|
||||||
use std::io::ErrorKind;
|
use std::io::ErrorKind;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
@ -401,7 +399,7 @@ mod resolve_path {
|
||||||
fn return_body() -> Result<()> {
|
fn return_body() -> Result<()> {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_path(&Path::new("/bin/echo"), r#"{"body": "a"}"#)?,
|
resolve_path(&Path::new("/bin/echo"), r#"{"body": "a"}"#)?,
|
||||||
HopAction::Body("a".to_string())
|
HopAction::Body("a".to_owned())
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -411,7 +409,7 @@ mod resolve_path {
|
||||||
fn return_redirect() -> Result<()> {
|
fn return_redirect() -> Result<()> {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_path(&Path::new("/bin/echo"), r#"{"redirect": "a"}"#)?,
|
resolve_path(&Path::new("/bin/echo"), r#"{"redirect": "a"}"#)?,
|
||||||
HopAction::Redirect("a".to_string())
|
HopAction::Redirect(Cow::Borrowed("a"))
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue