refactor with actix-web 1.0.0
* actix-web 1.0.0 brought some changes in how associated data is accessed, and how handlers are written. * static files are now a separate crate `actix-files`. * web::run now creates the App and the Server and runs the server. they really want to have HttpServer::new and App::new in the same scope (I couldn't find a proper signature for the create_app function) * replace .trim_right_matches (depreceated in rust 1.33) with .trim_end_matches https://github.com/actix/actix-web/blob/web-v1.0.0/MIGRATION.md
This commit is contained in:
parent
6e76b4c5df
commit
85f1df81a1
3 changed files with 40 additions and 43 deletions
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "http-server"
|
name = "http-server"
|
||||||
version = "0.9.0"
|
version = "0.10.0"
|
||||||
authors = ["Damjan Georgievski <gdamjan@gmail.com>"]
|
authors = ["Damjan Georgievski <gdamjan@gmail.com>"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
@ -8,7 +8,8 @@ homepage = "https://github.com/gdamjan/http-server-rs"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "0.7"
|
actix-web = "1.0"
|
||||||
|
actix-files = "0.1.1"
|
||||||
bytes = "0.4"
|
bytes = "0.4"
|
||||||
clap = "2"
|
clap = "2"
|
||||||
env_logger = "*"
|
env_logger = "*"
|
||||||
|
|
19
src/main.rs
19
src/main.rs
|
@ -1,13 +1,7 @@
|
||||||
use actix_web::server;
|
|
||||||
use actix_web::actix;
|
|
||||||
use env_logger;
|
|
||||||
use log;
|
|
||||||
use clap;
|
|
||||||
|
|
||||||
mod channel;
|
mod channel;
|
||||||
mod web;
|
mod web;
|
||||||
|
|
||||||
fn main() -> Result<(), std::io::Error> {
|
fn main() -> std::io::Result<()> {
|
||||||
let app = clap::App::new(clap::crate_name!())
|
let app = clap::App::new(clap::crate_name!())
|
||||||
.author(clap::crate_authors!("\n"))
|
.author(clap::crate_authors!("\n"))
|
||||||
.version(clap::crate_version!())
|
.version(clap::crate_version!())
|
||||||
|
@ -42,14 +36,5 @@ fn main() -> Result<(), std::io::Error> {
|
||||||
let root = std::path::PathBuf::from(chdir).canonicalize()?;
|
let root = std::path::PathBuf::from(chdir).canonicalize()?;
|
||||||
std::env::set_current_dir(&root)?;
|
std::env::set_current_dir(&root)?;
|
||||||
|
|
||||||
|
web::run(&bind_addr, &root)
|
||||||
let sys = actix::System::new("http_server_rs");
|
|
||||||
|
|
||||||
log::info!("Serving files from {:?}", root);
|
|
||||||
server::new(move || web::create_app(&root).unwrap())
|
|
||||||
.bind(&bind_addr)?
|
|
||||||
.start();
|
|
||||||
|
|
||||||
let _ = sys.run();
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
59
src/web.rs
59
src/web.rs
|
@ -1,5 +1,6 @@
|
||||||
use actix_web::{error, fs, App, HttpRequest, HttpResponse, Responder, middleware};
|
use actix_web::{error, HttpRequest, HttpResponse, Responder, web};
|
||||||
use actix_web::dev::FromParam;
|
use actix_web::dev::ServiceResponse;
|
||||||
|
use actix_files as fs;
|
||||||
use futures::Stream;
|
use futures::Stream;
|
||||||
use percent_encoding::{utf8_percent_encode, DEFAULT_ENCODE_SET};
|
use percent_encoding::{utf8_percent_encode, DEFAULT_ENCODE_SET};
|
||||||
use htmlescape::encode_minimal as escape_html_entity;
|
use htmlescape::encode_minimal as escape_html_entity;
|
||||||
|
@ -8,26 +9,34 @@ use crate::channel;
|
||||||
|
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std;
|
|
||||||
use bytes;
|
|
||||||
|
|
||||||
pub fn create_app(directory: &PathBuf) -> Result<App<PathBuf>, error::Error> {
|
|
||||||
let root = directory.to_path_buf(); // practically makes a copy, so it can be used as state
|
pub fn run(bind_addr: &str, root: &PathBuf) -> std::io::Result<()> {
|
||||||
let static_files = fs::StaticFiles::new(&root)?
|
let root = root.clone();
|
||||||
.show_files_listing()
|
actix_web::HttpServer::new(move || {
|
||||||
.files_listing_renderer(handle_directory);
|
log::info!("Serving files from {:?}", &root);
|
||||||
let app = App::with_state(root)
|
|
||||||
.middleware(middleware::Logger::default())
|
let static_files = fs::Files::new("/", &root)
|
||||||
.resource(r"/{tail:.*}.tar", |r| r.get().f(handle_tar))
|
.show_files_listing()
|
||||||
.resource(r"/favicon.ico", |r| r.get().f(favicon_ico))
|
.files_listing_renderer(handle_directory);
|
||||||
.handler("/", static_files);
|
|
||||||
Ok(app)
|
actix_web::App::new()
|
||||||
|
.data(root.clone())
|
||||||
|
.wrap(actix_web::middleware::Logger::default())
|
||||||
|
.service(web::resource(r"/{tail:.*}.tar").to(handle_tar))
|
||||||
|
.service(web::resource(r"/favicon.ico").to(favicon_ico))
|
||||||
|
.service(static_files)
|
||||||
|
})
|
||||||
|
.bind(bind_addr)?
|
||||||
|
.workers(1)
|
||||||
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn handle_directory<'a, 'b>(
|
fn handle_directory<'a, 'b>(
|
||||||
dir: &'a fs::Directory,
|
dir: &'a fs::Directory,
|
||||||
req: &'b HttpRequest<PathBuf>,
|
req: &'b HttpRequest,
|
||||||
) -> std::io::Result<HttpResponse> {
|
) -> Result<ServiceResponse, std::io::Error> {
|
||||||
|
|
||||||
let rd = std::fs::read_dir(&dir.path)?;
|
let rd = std::fs::read_dir(&dir.path)?;
|
||||||
|
|
||||||
|
@ -39,7 +48,7 @@ fn handle_directory<'a, 'b>(
|
||||||
paths.sort_by_key(|entry| (!optimistic_is_dir(entry), entry.file_name()));
|
paths.sort_by_key(|entry| (!optimistic_is_dir(entry), entry.file_name()));
|
||||||
|
|
||||||
|
|
||||||
let dir_tar_path = String::from(req.path().trim_right_matches('/')) + ".tar";
|
let dir_tar_path = String::from(req.path().trim_end_matches('/')) + ".tar";
|
||||||
let tar_url = utf8_percent_encode(&dir_tar_path, DEFAULT_ENCODE_SET).to_string();
|
let tar_url = utf8_percent_encode(&dir_tar_path, DEFAULT_ENCODE_SET).to_string();
|
||||||
|
|
||||||
let mut body = String::new();
|
let mut body = String::new();
|
||||||
|
@ -77,13 +86,15 @@ fn handle_directory<'a, 'b>(
|
||||||
writeln!(html, "<body>\n{}</body>", body).unwrap();
|
writeln!(html, "<body>\n{}</body>", body).unwrap();
|
||||||
writeln!(html, "</html>").unwrap();
|
writeln!(html, "</html>").unwrap();
|
||||||
|
|
||||||
Ok(HttpResponse::Ok().content_type("text/html; charset=utf-8").body(html))
|
let resp = HttpResponse::Ok().content_type("text/html; charset=utf-8").body(html);
|
||||||
|
|
||||||
|
Ok(ServiceResponse::new(req.clone(), resp))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_tar(req: &HttpRequest<PathBuf>) -> impl Responder {
|
fn handle_tar(req: HttpRequest) -> impl Responder {
|
||||||
let root = req.state();
|
let root = req.app_data::<PathBuf>().unwrap();
|
||||||
let tail: String = req.match_info().query("tail")?;
|
let tail = req.match_info().query("tail");
|
||||||
let relpath = PathBuf::from_param(tail.trim_left_matches('/'))?;
|
let relpath = PathBuf::from(tail.trim_end_matches('/'));
|
||||||
let fullpath = root.join(&relpath).canonicalize()?;
|
let fullpath = root.join(&relpath).canonicalize()?;
|
||||||
|
|
||||||
if !(fullpath.is_dir()) {
|
if !(fullpath.is_dir()) {
|
||||||
|
@ -97,7 +108,7 @@ fn handle_tar(req: &HttpRequest<PathBuf>) -> impl Responder {
|
||||||
Ok(resp)
|
Ok(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn favicon_ico(_req: &HttpRequest<PathBuf>) -> impl Responder {
|
fn favicon_ico() -> impl Responder {
|
||||||
HttpResponse::Ok()
|
HttpResponse::Ok()
|
||||||
.content_type("image/png")
|
.content_type("image/png")
|
||||||
.header("Cache-Control", "only-if-cached, max-age=86400")
|
.header("Cache-Control", "only-if-cached, max-age=86400")
|
||||||
|
|
Loading…
Add table
Reference in a new issue