Serve files
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,2 +1,3 @@
 | 
				
			|||||||
/target
 | 
					/target
 | 
				
			||||||
.idea
 | 
					.idea
 | 
				
			||||||
 | 
					storage
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1369
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1369
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -6,3 +6,8 @@ edition = "2021"
 | 
				
			|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 | 
					# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[dependencies]
 | 
					[dependencies]
 | 
				
			||||||
 | 
					clap = { version = "3.1.6", features = ["derive", "env"] }
 | 
				
			||||||
 | 
					actix-web = "4"
 | 
				
			||||||
 | 
					actix-files = "0.6"
 | 
				
			||||||
 | 
					env_logger = "0.9.0"
 | 
				
			||||||
 | 
					log = "0.4"
 | 
				
			||||||
							
								
								
									
										98
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										98
									
								
								src/main.rs
									
									
									
									
									
								
							@@ -1,3 +1,97 @@
 | 
				
			|||||||
fn main() {
 | 
					use std::path::{Path, PathBuf};
 | 
				
			||||||
    println!("Hello, world!");
 | 
					
 | 
				
			||||||
 | 
					use actix_files::{Files, NamedFile};
 | 
				
			||||||
 | 
					use actix_web::{App, HttpResponse, HttpServer};
 | 
				
			||||||
 | 
					use actix_web::dev::{fn_service, ServiceRequest, ServiceResponse};
 | 
				
			||||||
 | 
					use actix_web::middleware::Logger;
 | 
				
			||||||
 | 
					use clap::Parser;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Simple pages server
 | 
				
			||||||
 | 
					#[derive(Parser, Debug, Clone)]
 | 
				
			||||||
 | 
					#[clap(author, version, about, long_about = None)]
 | 
				
			||||||
 | 
					struct Args {
 | 
				
			||||||
 | 
					    /// The address and port this server will listen on
 | 
				
			||||||
 | 
					    #[clap(short, long, env, default_value = "0.0.0.0:8000")]
 | 
				
			||||||
 | 
					    listen_address: String,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// The place wheres files to serve are hosted
 | 
				
			||||||
 | 
					    #[clap(short, long, env)]
 | 
				
			||||||
 | 
					    files_path: String,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Update token
 | 
				
			||||||
 | 
					    #[clap(short, long, env)]
 | 
				
			||||||
 | 
					    update_token: String,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// The IP addresses allowed to perform updates
 | 
				
			||||||
 | 
					    #[clap(short, long, env, default_value = "*")]
 | 
				
			||||||
 | 
					    allowed_ips_for_update: String,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Index file name
 | 
				
			||||||
 | 
					    #[clap(short, long, env, default_value = "index.html")]
 | 
				
			||||||
 | 
					    index_file: String,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Handle for not found files. By default, a basic message is returned
 | 
				
			||||||
 | 
					    #[clap(short, long, env, default_value = "")]
 | 
				
			||||||
 | 
					    not_found_file: String,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Args {
 | 
				
			||||||
 | 
					    pub fn storage_path(&self) -> &Path {
 | 
				
			||||||
 | 
					        Path::new(&self.files_path)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn default_handler_path(&self) -> Option<PathBuf> {
 | 
				
			||||||
 | 
					        match self.not_found_file.is_empty() {
 | 
				
			||||||
 | 
					            true => None,
 | 
				
			||||||
 | 
					            false => Some(self.storage_path().join(&self.not_found_file))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static mut ARGS: Option<Args> = None;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[actix_web::main]
 | 
				
			||||||
 | 
					async fn main() -> std::io::Result<()> {
 | 
				
			||||||
 | 
					    let args: Args = Args::parse();
 | 
				
			||||||
 | 
					    env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    log::info!("starting HTTP server at {}", args.listen_address);
 | 
				
			||||||
 | 
					    let listen_address = args.listen_address.to_string();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if !args.storage_path().exists() {
 | 
				
			||||||
 | 
					        panic!("Specified files path does not exists!");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    unsafe { ARGS = Some(args.clone()); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    HttpServer::new(move || {
 | 
				
			||||||
 | 
					        App::new()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Serve a tree of static files at the web root and specify the index file.
 | 
				
			||||||
 | 
					            // Note that the root path should always be defined as the last item. The paths are
 | 
				
			||||||
 | 
					            // resolved in the order they are defined. If this would be placed before the `/images`
 | 
				
			||||||
 | 
					            // path then the service for the static images would never be reached.
 | 
				
			||||||
 | 
					            .service(Files::new("/", &args.files_path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                .index_file(&args.index_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                .default_handler(fn_service(|req: ServiceRequest| async {
 | 
				
			||||||
 | 
					                    let (req, _) = req.into_parts();
 | 
				
			||||||
 | 
					                    if let Some(h) = unsafe { ARGS.as_ref().unwrap() }.default_handler_path().as_ref() {
 | 
				
			||||||
 | 
					                        let file = NamedFile::open_async(h).await?;
 | 
				
			||||||
 | 
					                        let res = file.into_response(&req);
 | 
				
			||||||
 | 
					                        Ok(ServiceResponse::new(req, res))
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        Ok(ServiceResponse::new(req, HttpResponse::NotFound()
 | 
				
			||||||
 | 
					                            .body("404 Not found")))
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }))
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Enable the logger.
 | 
				
			||||||
 | 
					            .wrap(Logger::default())
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					        .bind(listen_address)?
 | 
				
			||||||
 | 
					        .run()
 | 
				
			||||||
 | 
					        .await
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user