♻️ refactor: clean up ptth_server
- Found I was passing the file server root twice - Removed handlebars from the public API. The templates are fixed when ptth_server ships, so I don't think users of the lib should care what handlebars is. - Making other stuff private where possiblemain
							parent
							
								
									86af3194e5
								
							
						
					
					
						commit
						ae33337156
					
				| 
						 | 
					@ -51,14 +51,8 @@ async fn handle_all (req: Request <Body>, state: Arc <State>)
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	let ptth_req = RequestParts::from_hyper (parts.method, path_and_query, parts.headers)?;
 | 
						let ptth_req = RequestParts::from_hyper (parts.method, path_and_query, parts.headers)?;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	let default_root = PathBuf::from ("./");
 | 
					 | 
				
			||||||
	let file_server_root: &std::path::Path = state.config.file_server_root
 | 
					 | 
				
			||||||
	.as_ref ()
 | 
					 | 
				
			||||||
	.unwrap_or (&default_root);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	let ptth_resp = file_server::serve_all (
 | 
						let ptth_resp = file_server::serve_all (
 | 
				
			||||||
		&state,
 | 
							&state,
 | 
				
			||||||
		file_server_root,
 | 
					 | 
				
			||||||
		ptth_req.method, 
 | 
							ptth_req.method, 
 | 
				
			||||||
		&ptth_req.uri, 
 | 
							&ptth_req.uri, 
 | 
				
			||||||
		&ptth_req.headers
 | 
							&ptth_req.headers
 | 
				
			||||||
| 
						 | 
					@ -94,12 +88,6 @@ async fn main () -> anyhow::Result <()> {
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	let addr = SocketAddr::from(([0, 0, 0, 0], 4000));
 | 
						let addr = SocketAddr::from(([0, 0, 0, 0], 4000));
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	let handlebars = file_server::load_templates (&PathBuf::new ())?;
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	let metrics_startup = metrics::Startup::new ( 
 | 
					 | 
				
			||||||
		config_file.name.unwrap_or_else (|| "PTTH File Server".to_string ())
 | 
					 | 
				
			||||||
	);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	let metrics_interval = Arc::new (ArcSwap::default ());
 | 
						let metrics_interval = Arc::new (ArcSwap::default ());
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	let interval_writer = Arc::clone (&metrics_interval);
 | 
						let interval_writer = Arc::clone (&metrics_interval);
 | 
				
			||||||
| 
						 | 
					@ -107,15 +95,13 @@ async fn main () -> anyhow::Result <()> {
 | 
				
			||||||
		file_server::metrics::Interval::monitor (interval_writer).await;
 | 
							file_server::metrics::Interval::monitor (interval_writer).await;
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	let state = Arc::new (State {
 | 
						let state = Arc::new (State::new (
 | 
				
			||||||
		config: file_server::Config {
 | 
							config_file.file_server_root,
 | 
				
			||||||
			file_server_root: config_file.file_server_root,
 | 
							&PathBuf::new (),
 | 
				
			||||||
		},
 | 
							config_file.name.unwrap_or_else (|| "PTTH File Server".to_string ()),
 | 
				
			||||||
		handlebars,
 | 
					 | 
				
			||||||
		metrics_startup,
 | 
					 | 
				
			||||||
		metrics_interval,
 | 
							metrics_interval,
 | 
				
			||||||
		hidden_path: Some (path),
 | 
							Some (path),
 | 
				
			||||||
	});
 | 
						)?);
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	let make_svc = make_service_fn (|_conn| {
 | 
						let make_svc = make_service_fn (|_conn| {
 | 
				
			||||||
		let state = state.clone ();
 | 
							let state = state.clone ();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,20 +1,30 @@
 | 
				
			||||||
use thiserror::Error;
 | 
					use thiserror::Error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Errors thrown when the server loads its TOML config file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive (Debug, Error)]
 | 
					#[derive (Debug, Error)]
 | 
				
			||||||
pub enum LoadTomlError {
 | 
					pub enum LoadTomlError {
 | 
				
			||||||
 | 
						/// The server's config file is readable by other users, meaning
 | 
				
			||||||
 | 
						/// that the file server module could accidentally serve it to
 | 
				
			||||||
 | 
						/// clients, and expose the server's API key.
 | 
				
			||||||
	#[error ("Config file has bad permissions mode, it should be octal 0600")]
 | 
						#[error ("Config file has bad permissions mode, it should be octal 0600")]
 | 
				
			||||||
	ConfigBadPermissions,
 | 
						ConfigBadPermissions,
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
 | 
						/// Wraps `std::io::Error`
 | 
				
			||||||
	#[error ("I/O")]
 | 
						#[error ("I/O")]
 | 
				
			||||||
	Io (#[from] std::io::Error),
 | 
						Io (#[from] std::io::Error),
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
 | 
						/// Wraps `std::string::FromUtf8Error`
 | 
				
			||||||
	#[error ("UTF-8")]
 | 
						#[error ("UTF-8")]
 | 
				
			||||||
	Utf8 (#[from] std::string::FromUtf8Error),
 | 
						Utf8 (#[from] std::string::FromUtf8Error),
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
 | 
						/// Wraps `toml::de::Error`
 | 
				
			||||||
	#[error ("TOML")]
 | 
						#[error ("TOML")]
 | 
				
			||||||
	Toml (#[from] toml::de::Error),
 | 
						Toml (#[from] toml::de::Error),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Errors thrown when the server is starting up or serving requests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive (Debug, Error)]
 | 
					#[derive (Debug, Error)]
 | 
				
			||||||
pub enum ServerError {
 | 
					pub enum ServerError {
 | 
				
			||||||
	#[error ("Loading TOML")]
 | 
						#[error ("Loading TOML")]
 | 
				
			||||||
| 
						 | 
					@ -23,9 +33,6 @@ pub enum ServerError {
 | 
				
			||||||
	#[error ("Loading Handlebars template file")]
 | 
						#[error ("Loading Handlebars template file")]
 | 
				
			||||||
	LoadHandlebars (#[from] handlebars::TemplateFileError),
 | 
						LoadHandlebars (#[from] handlebars::TemplateFileError),
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	#[error ("API key is too weak, server can't use it")]
 | 
					 | 
				
			||||||
	WeakApiKey,
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	#[error ("File server error")]
 | 
						#[error ("File server error")]
 | 
				
			||||||
	FileServer (#[from] super::file_server::errors::FileServerError),
 | 
						FileServer (#[from] super::file_server::errors::FileServerError),
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,9 +2,6 @@ use thiserror::Error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive (Debug, Error)]
 | 
					#[derive (Debug, Error)]
 | 
				
			||||||
pub enum FileServerError {
 | 
					pub enum FileServerError {
 | 
				
			||||||
	#[error ("Handlebars render error")]
 | 
					 | 
				
			||||||
	Handlebars (#[from] handlebars::RenderError),
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	#[error ("I/O error")]
 | 
						#[error ("I/O error")]
 | 
				
			||||||
	Io (#[from] std::io::Error),
 | 
						Io (#[from] std::io::Error),
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
| 
						 | 
					@ -28,6 +25,9 @@ pub enum FileServerError {
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	#[error ("Heim process error")]
 | 
						#[error ("Heim process error")]
 | 
				
			||||||
	HeimProcess,
 | 
						HeimProcess,
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						#[error(transparent)]
 | 
				
			||||||
 | 
						Other (#[from] anyhow::Error),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl From <heim::process::ProcessError> for FileServerError {
 | 
					impl From <heim::process::ProcessError> for FileServerError {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -60,7 +60,7 @@ pub async fn serve_root (
 | 
				
			||||||
		metrics_interval: &**state.metrics_interval.load (),
 | 
							metrics_interval: &**state.metrics_interval.load (),
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	let s = state.handlebars.render ("file_server_root", ¶ms)?;
 | 
						let s = state.handlebars.render ("file_server_root", ¶ms).map_err (anyhow::Error::from)?;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	Ok (serve (s))
 | 
						Ok (serve (s))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -85,7 +85,7 @@ pub async fn serve_dir (
 | 
				
			||||||
		path,
 | 
							path,
 | 
				
			||||||
		entries,
 | 
							entries,
 | 
				
			||||||
		instance_metrics,
 | 
							instance_metrics,
 | 
				
			||||||
	})?;
 | 
						}).map_err (anyhow::Error::from)?;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	Ok (serve (s))
 | 
						Ok (serve (s))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -67,6 +67,27 @@ pub struct State {
 | 
				
			||||||
	pub hidden_path: Option <PathBuf>,
 | 
						pub hidden_path: Option <PathBuf>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl State {
 | 
				
			||||||
 | 
						pub fn new (
 | 
				
			||||||
 | 
							file_server_root: Option <PathBuf>,
 | 
				
			||||||
 | 
							asset_root: &Path,
 | 
				
			||||||
 | 
							name: String,
 | 
				
			||||||
 | 
							metrics_interval: Arc <ArcSwap <Option <metrics::Interval>>>,
 | 
				
			||||||
 | 
							hidden_path: Option <PathBuf>,
 | 
				
			||||||
 | 
						) -> Result <Self, FileServerError>
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							Ok (Self {
 | 
				
			||||||
 | 
								config: Config {
 | 
				
			||||||
 | 
									file_server_root,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								handlebars: load_templates (asset_root)?,
 | 
				
			||||||
 | 
								metrics_startup: metrics::Startup::new (name),
 | 
				
			||||||
 | 
								metrics_interval,
 | 
				
			||||||
 | 
								hidden_path,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive (Serialize)]
 | 
					#[derive (Serialize)]
 | 
				
			||||||
struct DirJson {
 | 
					struct DirJson {
 | 
				
			||||||
	entries: Vec <DirEntryJson>,
 | 
						entries: Vec <DirEntryJson>,
 | 
				
			||||||
| 
						 | 
					@ -311,14 +332,14 @@ async fn stream_file (
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Pass a request to the internal decision-making logic.
 | 
					/// Top-level request handler for the file server module.
 | 
				
			||||||
// When it returns, prettify it as HTML or JSON based on what the client
 | 
					/// 
 | 
				
			||||||
// asked for.
 | 
					/// Passes a request to the internal file server logic.
 | 
				
			||||||
 | 
					/// Returns an HTTP response as HTML or JSON, depending on the request.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[instrument (level = "debug", skip (state, headers))]
 | 
					#[instrument (level = "debug", skip (state, headers))]
 | 
				
			||||||
pub async fn serve_all (
 | 
					pub async fn serve_all (
 | 
				
			||||||
	state: &State,
 | 
						state: &State,
 | 
				
			||||||
	root: &Path,
 | 
					 | 
				
			||||||
	method: Method,
 | 
						method: Method,
 | 
				
			||||||
	uri: &str,
 | 
						uri: &str,
 | 
				
			||||||
	headers: &HashMap <String, Vec <u8>>
 | 
						headers: &HashMap <String, Vec <u8>>
 | 
				
			||||||
| 
						 | 
					@ -342,6 +363,11 @@ pub async fn serve_all (
 | 
				
			||||||
		resp
 | 
							resp
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
 | 
						let default_root = PathBuf::from ("./");
 | 
				
			||||||
 | 
						let root: &std::path::Path = state.config.file_server_root
 | 
				
			||||||
 | 
						.as_ref ()
 | 
				
			||||||
 | 
						.unwrap_or (&default_root);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
	Ok (match internal::serve_all (root, method, uri, headers, state.hidden_path.as_deref ()).await? {
 | 
						Ok (match internal::serve_all (root, method, uri, headers, state.hidden_path.as_deref ()).await? {
 | 
				
			||||||
		Favicon => serve_error (StatusCode::NotFound, "Not found\n"),
 | 
							Favicon => serve_error (StatusCode::NotFound, "Not found\n"),
 | 
				
			||||||
		Forbidden => serve_error (StatusCode::Forbidden, "403 Forbidden\n"),
 | 
							Forbidden => serve_error (StatusCode::Forbidden, "403 Forbidden\n"),
 | 
				
			||||||
| 
						 | 
					@ -400,10 +426,10 @@ pub async fn serve_all (
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn load_templates (
 | 
					fn load_templates (
 | 
				
			||||||
	asset_root: &Path
 | 
						asset_root: &Path
 | 
				
			||||||
) 
 | 
					) 
 | 
				
			||||||
-> Result <Handlebars <'static>, handlebars::TemplateFileError>
 | 
					-> Result <Handlebars <'static>, anyhow::Error>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	let mut handlebars = Handlebars::new ();
 | 
						let mut handlebars = Handlebars::new ();
 | 
				
			||||||
	handlebars.set_strict_mode (true);
 | 
						handlebars.set_strict_mode (true);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
//! # PTTH Server
 | 
					//! # PTTH Server
 | 
				
			||||||
//! 
 | 
					//! 
 | 
				
			||||||
//! The PTTH server makes an outgoing HTTP connection to a
 | 
					//! The PTTH server makes outgoing HTTP connections to a
 | 
				
			||||||
//! PTTH relay, and then serves incoming HTTP requests through
 | 
					//! PTTH relay, and then serves incoming HTTP requests through
 | 
				
			||||||
//! the relay.
 | 
					//! the relay.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,7 +35,12 @@ use ptth_core::{
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub mod errors;
 | 
					pub mod errors;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// In-process file server module with byte range and ETag support
 | 
				
			||||||
pub mod file_server;
 | 
					pub mod file_server;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Load and de-serialize structures from TOML, with a size limit
 | 
				
			||||||
 | 
					/// and checking permissions (On Unix)
 | 
				
			||||||
pub mod load_toml;
 | 
					pub mod load_toml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use errors::ServerError;
 | 
					use errors::ServerError;
 | 
				
			||||||
| 
						 | 
					@ -58,14 +63,8 @@ async fn handle_one_req (
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	debug! ("Handling request {}", req_id);
 | 
						debug! ("Handling request {}", req_id);
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	let default_root = PathBuf::from ("./");
 | 
					 | 
				
			||||||
	let file_server_root: &std::path::Path = state.file_server.config.file_server_root
 | 
					 | 
				
			||||||
	.as_ref ()
 | 
					 | 
				
			||||||
	.unwrap_or (&default_root);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	let response = file_server::serve_all (
 | 
						let response = file_server::serve_all (
 | 
				
			||||||
		&state.file_server,
 | 
							&state.file_server,
 | 
				
			||||||
		file_server_root,
 | 
					 | 
				
			||||||
		parts.method, 
 | 
							parts.method, 
 | 
				
			||||||
		&parts.uri, 
 | 
							&parts.uri, 
 | 
				
			||||||
		&parts.headers,
 | 
							&parts.headers,
 | 
				
			||||||
| 
						 | 
					@ -161,16 +160,30 @@ async fn handle_req_resp (
 | 
				
			||||||
	Ok (())
 | 
						Ok (())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// A complete config file. The bin frontend is allowed to use a different
 | 
					/// Config for ptth_server and the file server module
 | 
				
			||||||
// type to load an incomplete file, as long as the command line options
 | 
					/// 
 | 
				
			||||||
// complete it.
 | 
					/// This is a complete config. 
 | 
				
			||||||
 | 
					/// The bin frontend is allowed to load an incomplete config from
 | 
				
			||||||
 | 
					/// the TOML file, fill it out with command-line options, and put
 | 
				
			||||||
 | 
					/// the completed config in this struct.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive (Clone)]
 | 
					#[derive (Clone)]
 | 
				
			||||||
pub struct ConfigFile {
 | 
					pub struct ConfigFile {
 | 
				
			||||||
 | 
						/// A name that uniquely identifies this server on the relay.
 | 
				
			||||||
 | 
						/// May be human-readable.
 | 
				
			||||||
	pub name: String,
 | 
						pub name: String,
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						/// Secret API key used to authenticate the server with the relay
 | 
				
			||||||
	pub api_key: String,
 | 
						pub api_key: String,
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						/// URL of the PTTH relay server that ptth_server should connect to
 | 
				
			||||||
	pub relay_url: String,
 | 
						pub relay_url: String,
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						/// Directory that the file server module will expose to clients
 | 
				
			||||||
 | 
						/// over the relay. If None, the current working dir is used.
 | 
				
			||||||
	pub file_server_root: Option <PathBuf>,
 | 
						pub file_server_root: Option <PathBuf>,
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						/// For debugging.
 | 
				
			||||||
	pub throttle_upload: bool,
 | 
						pub throttle_upload: bool,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -192,12 +205,19 @@ impl ConfigFile {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Config for ptth_server itself
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive (Default)]
 | 
					#[derive (Default)]
 | 
				
			||||||
pub struct Config {
 | 
					pub struct Config {
 | 
				
			||||||
 | 
						/// URL of the PTTH relay server that ptth_server should connect to
 | 
				
			||||||
	pub relay_url: String,
 | 
						pub relay_url: String,
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						/// For debugging.
 | 
				
			||||||
	pub throttle_upload: bool,
 | 
						pub throttle_upload: bool,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Runs a PTTH file server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub async fn run_server (
 | 
					pub async fn run_server (
 | 
				
			||||||
	config_file: ConfigFile,
 | 
						config_file: ConfigFile,
 | 
				
			||||||
	shutdown_oneshot: oneshot::Receiver <()>,
 | 
						shutdown_oneshot: oneshot::Receiver <()>,
 | 
				
			||||||
| 
						 | 
					@ -224,9 +244,7 @@ pub async fn run_server (
 | 
				
			||||||
	.default_headers (headers)
 | 
						.default_headers (headers)
 | 
				
			||||||
	.connect_timeout (Duration::from_secs (30))
 | 
						.connect_timeout (Duration::from_secs (30))
 | 
				
			||||||
	.build ().map_err (ServerError::CantBuildHttpClient)?;
 | 
						.build ().map_err (ServerError::CantBuildHttpClient)?;
 | 
				
			||||||
	let handlebars = file_server::load_templates (&asset_root)?;
 | 
					 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	let metrics_startup = file_server::metrics::Startup::new (config_file.name);
 | 
					 | 
				
			||||||
	let metrics_interval = Arc::new (ArcSwap::default ());
 | 
						let metrics_interval = Arc::new (ArcSwap::default ());
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	let interval_writer = Arc::clone (&metrics_interval);
 | 
						let interval_writer = Arc::clone (&metrics_interval);
 | 
				
			||||||
| 
						 | 
					@ -235,15 +253,13 @@ pub async fn run_server (
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	let state = Arc::new (State {
 | 
						let state = Arc::new (State {
 | 
				
			||||||
		file_server: file_server::State {
 | 
							file_server: file_server::State::new (
 | 
				
			||||||
			config: file_server::Config {
 | 
								config_file.file_server_root,
 | 
				
			||||||
				file_server_root: config_file.file_server_root,
 | 
								&asset_root,
 | 
				
			||||||
			},
 | 
								config_file.name,
 | 
				
			||||||
			handlebars,
 | 
					 | 
				
			||||||
			metrics_startup,
 | 
					 | 
				
			||||||
			metrics_interval,
 | 
								metrics_interval,
 | 
				
			||||||
			hidden_path,
 | 
								hidden_path,
 | 
				
			||||||
		},
 | 
							)?,
 | 
				
			||||||
		config: Config {
 | 
							config: Config {
 | 
				
			||||||
			relay_url: config_file.relay_url,
 | 
								relay_url: config_file.relay_url,
 | 
				
			||||||
			throttle_upload: config_file.throttle_upload,
 | 
								throttle_upload: config_file.throttle_upload,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,7 +26,7 @@ fn load_inner <
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// For files that contain public-viewable information
 | 
					/// For files that contain public-viewable information
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn load_public <
 | 
					fn load_public <
 | 
				
			||||||
	T: DeserializeOwned,
 | 
						T: DeserializeOwned,
 | 
				
			||||||
	P: AsRef <Path> + Debug
 | 
						P: AsRef <Path> + Debug
 | 
				
			||||||
> (
 | 
					> (
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue