Clippy
This commit is contained in:
parent
ce68f4dd42
commit
531a7da636
5 changed files with 57 additions and 53 deletions
|
@ -92,7 +92,7 @@ impl From<&'static str> for Route {
|
||||||
/// web path. This incurs a disk check operation, but since users shouldn't be
|
/// web path. This incurs a disk check operation, but since users shouldn't be
|
||||||
/// updating the config that frequently, it should be fine.
|
/// updating the config that frequently, it should be fine.
|
||||||
impl<'de> Deserialize<'de> for Route {
|
impl<'de> Deserialize<'de> for Route {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Route, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
{
|
{
|
||||||
|
@ -233,7 +233,7 @@ pub enum RouteType {
|
||||||
Internal,
|
Internal,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ConfigData {
|
pub struct FileData {
|
||||||
pub path: PathBuf,
|
pub path: PathBuf,
|
||||||
pub file: File,
|
pub file: File,
|
||||||
}
|
}
|
||||||
|
@ -242,19 +242,19 @@ pub struct ConfigData {
|
||||||
/// locations for a place to write a config file to. In order, it checks the
|
/// locations for a place to write a config file to. In order, it checks the
|
||||||
/// system-wide config location (`/etc/`, in Linux), followed by the config
|
/// system-wide config location (`/etc/`, in Linux), followed by the config
|
||||||
/// folder, followed by the user's home folder.
|
/// folder, followed by the user's home folder.
|
||||||
pub fn get_config_data() -> Result<ConfigData, BunBunError> {
|
pub fn get_config_data() -> Result<FileData, BunBunError> {
|
||||||
// Locations to check, with highest priority first
|
// Locations to check, with highest priority first
|
||||||
let locations: Vec<_> = {
|
let locations: Vec<_> = {
|
||||||
let mut folders = vec![PathBuf::from("/etc/")];
|
let mut folders = vec![PathBuf::from("/etc/")];
|
||||||
|
|
||||||
// Config folder
|
// Config folder
|
||||||
if let Some(folder) = config_dir() {
|
if let Some(folder) = config_dir() {
|
||||||
folders.push(folder)
|
folders.push(folder);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Home folder
|
// Home folder
|
||||||
if let Some(folder) = home_dir() {
|
if let Some(folder) = home_dir() {
|
||||||
folders.push(folder)
|
folders.push(folder);
|
||||||
}
|
}
|
||||||
|
|
||||||
folders
|
folders
|
||||||
|
@ -271,13 +271,13 @@ pub fn get_config_data() -> Result<ConfigData, BunBunError> {
|
||||||
match file {
|
match file {
|
||||||
Ok(file) => {
|
Ok(file) => {
|
||||||
debug!("Found file at {location:?}.");
|
debug!("Found file at {location:?}.");
|
||||||
return Ok(ConfigData {
|
return Ok(FileData {
|
||||||
path: location.clone(),
|
path: location.clone(),
|
||||||
file,
|
file,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
debug!("Tried to read '{location:?}' but failed due to error: {e}",)
|
debug!("Tried to read '{location:?}' but failed due to error: {e}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -298,7 +298,7 @@ pub fn get_config_data() -> Result<ConfigData, BunBunError> {
|
||||||
file.write_all(DEFAULT_CONFIG)?;
|
file.write_all(DEFAULT_CONFIG)?;
|
||||||
|
|
||||||
let file = OpenOptions::new().read(true).open(location.clone())?;
|
let file = OpenOptions::new().read(true).open(location.clone())?;
|
||||||
return Ok(ConfigData {
|
return Ok(FileData {
|
||||||
path: location,
|
path: location,
|
||||||
file,
|
file,
|
||||||
});
|
});
|
||||||
|
@ -314,19 +314,19 @@ pub fn get_config_data() -> Result<ConfigData, BunBunError> {
|
||||||
|
|
||||||
/// Assumes that the user knows what they're talking about and will only try
|
/// Assumes that the user knows what they're talking about and will only try
|
||||||
/// to load the config at the given path.
|
/// to load the config at the given path.
|
||||||
pub fn load_custom_path_config(
|
pub fn load_custom_file(
|
||||||
path: impl Into<PathBuf>,
|
path: impl Into<PathBuf>,
|
||||||
) -> Result<ConfigData, BunBunError> {
|
) -> Result<FileData, BunBunError> {
|
||||||
let path = path.into();
|
let path = path.into();
|
||||||
let file = OpenOptions::new()
|
let file = OpenOptions::new()
|
||||||
.read(true)
|
.read(true)
|
||||||
.open(&path)
|
.open(&path)
|
||||||
.map_err(|e| BunBunError::InvalidConfigPath(path.clone(), e))?;
|
.map_err(|e| BunBunError::InvalidConfigPath(path.clone(), e))?;
|
||||||
|
|
||||||
Ok(ConfigData { file, path })
|
Ok(FileData { path, file })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_config(
|
pub fn load_file(
|
||||||
mut config_file: File,
|
mut config_file: File,
|
||||||
large_config: bool,
|
large_config: bool,
|
||||||
) -> Result<Config, BunBunError> {
|
) -> Result<Config, BunBunError> {
|
||||||
|
@ -417,7 +417,7 @@ mod read_config {
|
||||||
fn empty_file() -> Result<()> {
|
fn empty_file() -> Result<()> {
|
||||||
let config_file = tempfile::tempfile()?;
|
let config_file = tempfile::tempfile()?;
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
read_config(config_file, false),
|
load_file(config_file, false),
|
||||||
Err(BunBunError::ZeroByteConfig)
|
Err(BunBunError::ZeroByteConfig)
|
||||||
));
|
));
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -428,7 +428,7 @@ mod read_config {
|
||||||
let mut config_file = tempfile::tempfile()?;
|
let mut config_file = tempfile::tempfile()?;
|
||||||
let size_to_write = (LARGE_FILE_SIZE_THRESHOLD + 1) as usize;
|
let size_to_write = (LARGE_FILE_SIZE_THRESHOLD + 1) as usize;
|
||||||
config_file.write(&[0].repeat(size_to_write))?;
|
config_file.write(&[0].repeat(size_to_write))?;
|
||||||
match read_config(config_file, false) {
|
match load_file(config_file, false) {
|
||||||
Err(BunBunError::ConfigTooLarge(size))
|
Err(BunBunError::ConfigTooLarge(size))
|
||||||
if size as usize == size_to_write => {}
|
if size as usize == size_to_write => {}
|
||||||
Err(BunBunError::ConfigTooLarge(size)) => {
|
Err(BunBunError::ConfigTooLarge(size)) => {
|
||||||
|
@ -441,7 +441,7 @@ mod read_config {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn valid_config() -> Result<()> {
|
fn valid_config() -> Result<()> {
|
||||||
assert!(read_config(File::open("bunbun.default.yaml")?, false).is_ok());
|
assert!(load_file(File::open("bunbun.default.yaml")?, false).is_ok());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ use std::error::Error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
#[allow(clippy::module_name_repetitions)]
|
||||||
pub enum BunBunError {
|
pub enum BunBunError {
|
||||||
Io(std::io::Error),
|
Io(std::io::Error),
|
||||||
Parse(serde_yaml::Error),
|
Parse(serde_yaml::Error),
|
||||||
|
|
43
src/main.rs
43
src/main.rs
|
@ -1,13 +1,13 @@
|
||||||
#![forbid(unsafe_code)]
|
#![forbid(unsafe_code)]
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
#![warn(clippy::nursery, clippy::pedantic)]
|
||||||
|
|
||||||
//! Bunbun is a pure-Rust implementation of bunny1 that provides a customizable
|
//! Bunbun is a pure-Rust implementation of bunny1 that provides a customizable
|
||||||
//! search engine and quick-jump tool in one small binary. For information on
|
//! search engine and quick-jump tool in one small binary. For information on
|
||||||
//! usage, please take a look at the readme.
|
//! usage, please take a look at the readme.
|
||||||
|
|
||||||
use crate::config::{
|
use crate::config::{
|
||||||
get_config_data, load_custom_path_config, read_config, ConfigData, Route,
|
get_config_data, load_custom_file, load_file, FileData, Route, RouteGroup,
|
||||||
RouteGroup,
|
|
||||||
};
|
};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use arc_swap::ArcSwap;
|
use arc_swap::ArcSwap;
|
||||||
|
@ -50,15 +50,15 @@ async fn main() -> Result<()> {
|
||||||
init_logger(opts.verbose, opts.quiet)?;
|
init_logger(opts.verbose, opts.quiet)?;
|
||||||
|
|
||||||
let conf_data = match opts.config {
|
let conf_data = match opts.config {
|
||||||
Some(file_name) => load_custom_path_config(file_name),
|
Some(file_name) => load_custom_file(file_name),
|
||||||
None => get_config_data(),
|
None => get_config_data(),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
let conf = read_config(conf_data.file.try_clone()?, opts.large_config)?;
|
let conf = load_file(conf_data.file.try_clone()?, opts.large_config)?;
|
||||||
let state = Arc::from(ArcSwap::from_pointee(State {
|
let state = Arc::from(ArcSwap::from_pointee(State {
|
||||||
public_address: conf.public_address,
|
public_address: conf.public_address,
|
||||||
default_route: conf.default_route,
|
default_route: conf.default_route,
|
||||||
routes: cache_routes(&conf.groups),
|
routes: cache_routes(conf.groups.clone()),
|
||||||
groups: conf.groups,
|
groups: conf.groups,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -106,14 +106,15 @@ fn init_logger(num_verbose_flags: u8, num_quiet_flags: u8) -> Result<()> {
|
||||||
/// Generates a hashmap of routes from the data structure created by the config
|
/// Generates a hashmap of routes from the data structure created by the config
|
||||||
/// file. This should improve runtime performance and is a better solution than
|
/// file. This should improve runtime performance and is a better solution than
|
||||||
/// just iterating over the config object for every hop resolution.
|
/// just iterating over the config object for every hop resolution.
|
||||||
fn cache_routes(groups: &[RouteGroup]) -> HashMap<String, Route> {
|
fn cache_routes(groups: Vec<RouteGroup>) -> HashMap<String, Route> {
|
||||||
let mut mapping = HashMap::new();
|
let mut mapping = HashMap::new();
|
||||||
for group in groups {
|
for group in groups {
|
||||||
for (kw, dest) in &group.routes {
|
for (kw, dest) in group.routes {
|
||||||
|
// This function isn't called often enough to not be a performance issue.
|
||||||
match mapping.insert(kw.clone(), dest.clone()) {
|
match mapping.insert(kw.clone(), dest.clone()) {
|
||||||
None => trace!("Inserting {} into mapping.", kw),
|
None => trace!("Inserting {kw} into mapping."),
|
||||||
Some(old_value) => {
|
Some(old_value) => {
|
||||||
trace!("Overriding {} route from {} to {}.", kw, old_value, dest)
|
trace!("Overriding {kw} route from {old_value} to {dest}.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -158,16 +159,14 @@ fn compile_templates() -> Result<Handlebars<'static>> {
|
||||||
#[cfg(not(tarpaulin_include))]
|
#[cfg(not(tarpaulin_include))]
|
||||||
fn start_watch(
|
fn start_watch(
|
||||||
state: Arc<ArcSwap<State>>,
|
state: Arc<ArcSwap<State>>,
|
||||||
config_data: ConfigData,
|
config_data: FileData,
|
||||||
large_config: bool,
|
large_config: bool,
|
||||||
) -> Result<Hotwatch> {
|
) -> Result<Hotwatch> {
|
||||||
let mut watch = Hotwatch::new_with_custom_delay(Duration::from_millis(500))?;
|
let mut watch = Hotwatch::new_with_custom_delay(Duration::from_millis(500))?;
|
||||||
let ConfigData { path, mut file } = config_data;
|
let FileData { path, mut file } = config_data;
|
||||||
let watch_result = watch.watch(&path, move |e: Event| {
|
let watch_result = watch.watch(&path, move |e: Event| {
|
||||||
if let Event::Create(ref path) = e {
|
if let Event::Create(ref path) = e {
|
||||||
file = load_custom_path_config(path)
|
file = load_custom_file(path).expect("file to exist at path").file;
|
||||||
.expect("file to exist at path")
|
|
||||||
.file;
|
|
||||||
trace!("Getting new file handler as file was recreated.");
|
trace!("Getting new file handler as file was recreated.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,7 +174,7 @@ fn start_watch(
|
||||||
Event::Write(_) | Event::Create(_) => {
|
Event::Write(_) | Event::Create(_) => {
|
||||||
trace!("Grabbing writer lock on state...");
|
trace!("Grabbing writer lock on state...");
|
||||||
trace!("Obtained writer lock on state!");
|
trace!("Obtained writer lock on state!");
|
||||||
match read_config(
|
match load_file(
|
||||||
file.try_clone().expect("Failed to clone file handle"),
|
file.try_clone().expect("Failed to clone file handle"),
|
||||||
large_config,
|
large_config,
|
||||||
) {
|
) {
|
||||||
|
@ -183,7 +182,7 @@ fn start_watch(
|
||||||
state.store(Arc::new(State {
|
state.store(Arc::new(State {
|
||||||
public_address: conf.public_address,
|
public_address: conf.public_address,
|
||||||
default_route: conf.default_route,
|
default_route: conf.default_route,
|
||||||
routes: cache_routes(&conf.groups),
|
routes: cache_routes(conf.groups.clone()),
|
||||||
groups: conf.groups,
|
groups: conf.groups,
|
||||||
}));
|
}));
|
||||||
info!("Successfully updated active state");
|
info!("Successfully updated active state");
|
||||||
|
@ -198,7 +197,9 @@ fn start_watch(
|
||||||
match watch_result {
|
match watch_result {
|
||||||
Ok(_) => info!("Watcher is now watching {path:?}"),
|
Ok(_) => info!("Watcher is now watching {path:?}"),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!("Couldn't watch {path:?}: {e}. Changes to this file won't be seen!",)
|
warn!(
|
||||||
|
"Couldn't watch {path:?}: {e}. Changes to this file won't be seen!"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,7 +256,7 @@ mod cache_routes {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn empty_groups_yield_empty_routes() {
|
fn empty_groups_yield_empty_routes() {
|
||||||
assert_eq!(cache_routes(&[]), HashMap::new());
|
assert_eq!(cache_routes(Vec::new()), HashMap::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -275,7 +276,7 @@ mod cache_routes {
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache_routes(&[group1, group2]),
|
cache_routes(vec![group1, group2]),
|
||||||
generate_external_routes(&[
|
generate_external_routes(&[
|
||||||
("a", "b"),
|
("a", "b"),
|
||||||
("c", "d"),
|
("c", "d"),
|
||||||
|
@ -302,7 +303,7 @@ mod cache_routes {
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache_routes(&[group1.clone(), group2]),
|
cache_routes(vec![group1.clone(), group2]),
|
||||||
generate_external_routes(&[("a", "1"), ("c", "2")])
|
generate_external_routes(&[("a", "1"), ("c", "2")])
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -314,7 +315,7 @@ mod cache_routes {
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache_routes(&[group1, group3]),
|
cache_routes(vec![group1, group3]),
|
||||||
generate_external_routes(&[("a", "1"), ("b", "2"), ("c", "d")])
|
generate_external_routes(&[("a", "1"), ("b", "2"), ("c", "d")])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,11 +11,11 @@ use log::{debug, error};
|
||||||
use percent_encoding::{utf8_percent_encode, AsciiSet, CONTROLS};
|
use percent_encoding::{utf8_percent_encode, AsciiSet, CONTROLS};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::path::PathBuf;
|
use std::path::Path;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// https://url.spec.whatwg.org/#fragment-percent-encode-set
|
// https://url.spec.whatwg.org/#fragment-percent-encode-set
|
||||||
const FRAGMENT_ENCODE_SET: &AsciiSet = &CONTROLS
|
const FRAGMENT_ENCODE_SET: &AsciiSet = &CONTROLS
|
||||||
.add(b' ')
|
.add(b' ')
|
||||||
.add(b'"')
|
.add(b'"')
|
||||||
|
@ -27,6 +27,7 @@ const FRAGMENT_ENCODE_SET: &AsciiSet = &CONTROLS
|
||||||
.add(b'#') // Interpreted as a hyperlink section target
|
.add(b'#') // Interpreted as a hyperlink section target
|
||||||
.add(b'\'');
|
.add(b'\'');
|
||||||
|
|
||||||
|
#[allow(clippy::unused_async)]
|
||||||
pub async fn index(
|
pub async fn index(
|
||||||
Extension(data): Extension<Arc<ArcSwap<State>>>,
|
Extension(data): Extension<Arc<ArcSwap<State>>>,
|
||||||
Extension(handlebars): Extension<Handlebars<'static>>,
|
Extension(handlebars): Extension<Handlebars<'static>>,
|
||||||
|
@ -40,6 +41,7 @@ pub async fn index(
|
||||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
|
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::unused_async)]
|
||||||
pub async fn opensearch(
|
pub async fn opensearch(
|
||||||
Extension(data): Extension<Arc<ArcSwap<State>>>,
|
Extension(data): Extension<Arc<ArcSwap<State>>>,
|
||||||
Extension(handlebars): Extension<Handlebars<'static>>,
|
Extension(handlebars): Extension<Handlebars<'static>>,
|
||||||
|
@ -62,6 +64,7 @@ pub async fn opensearch(
|
||||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
|
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::unused_async)]
|
||||||
pub async fn list(
|
pub async fn list(
|
||||||
Extension(data): Extension<Arc<ArcSwap<State>>>,
|
Extension(data): Extension<Arc<ArcSwap<State>>>,
|
||||||
Extension(handlebars): Extension<Handlebars<'static>>,
|
Extension(handlebars): Extension<Handlebars<'static>>,
|
||||||
|
@ -77,6 +80,7 @@ pub struct SearchQuery {
|
||||||
to: String,
|
to: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::unused_async)]
|
||||||
pub async fn hop(
|
pub async fn hop(
|
||||||
Extension(data): Extension<Arc<ArcSwap<State>>>,
|
Extension(data): Extension<Arc<ArcSwap<State>>>,
|
||||||
Extension(handlebars): Extension<Handlebars<'static>>,
|
Extension(handlebars): Extension<Handlebars<'static>>,
|
||||||
|
@ -91,7 +95,7 @@ pub async fn hop(
|
||||||
route_type: RouteType::Internal,
|
route_type: RouteType::Internal,
|
||||||
path,
|
path,
|
||||||
..
|
..
|
||||||
} => resolve_path(PathBuf::from(path), &args),
|
} => resolve_path(Path::new(path), &args),
|
||||||
ConfigRoute {
|
ConfigRoute {
|
||||||
route_type: RouteType::External,
|
route_type: RouteType::External,
|
||||||
path,
|
path,
|
||||||
|
@ -190,7 +194,7 @@ fn resolve_hop<'a>(
|
||||||
|
|
||||||
/// Checks if the user provided string has the correct properties required by
|
/// Checks if the user provided string has the correct properties required by
|
||||||
/// the route to be successfully matched.
|
/// the route to be successfully matched.
|
||||||
fn check_route(route: &Route, arg_count: usize) -> bool {
|
const fn check_route(route: &Route, arg_count: usize) -> bool {
|
||||||
if let Some(min_args) = route.min_args {
|
if let Some(min_args) = route.min_args {
|
||||||
if arg_count < min_args {
|
if arg_count < min_args {
|
||||||
return false;
|
return false;
|
||||||
|
@ -217,7 +221,7 @@ 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: PathBuf, args: &str) -> Result<HopAction, BunBunError> {
|
fn resolve_path(path: &Path, args: &str) -> Result<HopAction, BunBunError> {
|
||||||
let output = Command::new(path.canonicalize()?)
|
let output = Command::new(path.canonicalize()?)
|
||||||
.args(args.split(' '))
|
.args(args.split(' '))
|
||||||
.output()?;
|
.output()?;
|
||||||
|
@ -369,18 +373,16 @@ mod resolve_path {
|
||||||
use super::{resolve_path, HopAction};
|
use super::{resolve_path, HopAction};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use std::env::current_dir;
|
use std::env::current_dir;
|
||||||
use std::path::PathBuf;
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn invalid_path_returns_err() {
|
fn invalid_path_returns_err() {
|
||||||
assert!(resolve_path(PathBuf::from("/bin/aaaa"), "aaaa").is_err());
|
assert!(resolve_path(&Path::new("/bin/aaaa"), "aaaa").is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn valid_path_returns_ok() {
|
fn valid_path_returns_ok() {
|
||||||
assert!(
|
assert!(resolve_path(&Path::new("/bin/echo"), r#"{"body": "a"}"#).is_ok());
|
||||||
resolve_path(PathBuf::from("/bin/echo"), r#"{"body": "a"}"#).is_ok()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -389,7 +391,7 @@ mod resolve_path {
|
||||||
let nest_level = current_dir()?.ancestors().count() - 1;
|
let nest_level = current_dir()?.ancestors().count() - 1;
|
||||||
let mut rel_path = PathBuf::from("../".repeat(nest_level));
|
let mut rel_path = PathBuf::from("../".repeat(nest_level));
|
||||||
rel_path.push("./bin/echo");
|
rel_path.push("./bin/echo");
|
||||||
assert!(resolve_path(rel_path, r#"{"body": "a"}"#).is_ok());
|
assert!(resolve_path(&rel_path, r#"{"body": "a"}"#).is_ok());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -399,7 +401,7 @@ mod resolve_path {
|
||||||
// Trying to run a command without permission
|
// Trying to run a command without permission
|
||||||
format!(
|
format!(
|
||||||
"{}",
|
"{}",
|
||||||
resolve_path(PathBuf::from("/root/some_exec"), "").unwrap_err()
|
resolve_path(&Path::new("/root/some_exec"), "").unwrap_err()
|
||||||
)
|
)
|
||||||
.contains("Permission denied")
|
.contains("Permission denied")
|
||||||
);
|
);
|
||||||
|
@ -408,13 +410,13 @@ mod resolve_path {
|
||||||
#[test]
|
#[test]
|
||||||
fn non_success_exit_code_yields_err() {
|
fn non_success_exit_code_yields_err() {
|
||||||
// cat-ing a folder always returns exit code 1
|
// cat-ing a folder always returns exit code 1
|
||||||
assert!(resolve_path(PathBuf::from("/bin/cat"), "/").is_err());
|
assert!(resolve_path(&Path::new("/bin/cat"), "/").is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn return_body() -> Result<()> {
|
fn return_body() -> Result<()> {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_path(PathBuf::from("/bin/echo"), r#"{"body": "a"}"#)?,
|
resolve_path(&Path::new("/bin/echo"), r#"{"body": "a"}"#)?,
|
||||||
HopAction::Body("a".to_string())
|
HopAction::Body("a".to_string())
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -424,7 +426,7 @@ mod resolve_path {
|
||||||
#[test]
|
#[test]
|
||||||
fn return_redirect() -> Result<()> {
|
fn return_redirect() -> Result<()> {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_path(PathBuf::from("/bin/echo"), r#"{"redirect": "a"}"#)?,
|
resolve_path(&Path::new("/bin/echo"), r#"{"redirect": "a"}"#)?,
|
||||||
HopAction::Redirect("a".to_string())
|
HopAction::Redirect("a".to_string())
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::borrow::Cow;
|
||||||
use percent_encoding::PercentEncode;
|
use percent_encoding::PercentEncode;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
pub fn query<'a>(query: PercentEncode<'a>) -> impl Serialize + 'a {
|
pub fn query(query: PercentEncode<'_>) -> impl Serialize + '_ {
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct TemplateArgs<'a> {
|
struct TemplateArgs<'a> {
|
||||||
query: Cow<'a, str>,
|
query: Cow<'a, str>,
|
||||||
|
@ -13,7 +13,7 @@ pub fn query<'a>(query: PercentEncode<'a>) -> impl Serialize + 'a {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hostname<'a>(hostname: &'a str) -> impl Serialize + 'a {
|
pub fn hostname(hostname: &'_ str) -> impl Serialize + '_ {
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct TemplateArgs<'a> {
|
pub struct TemplateArgs<'a> {
|
||||||
pub hostname: &'a str,
|
pub hostname: &'a str,
|
||||||
|
|
Loading…
Reference in a new issue