Can update files
This commit is contained in:
parent
b462262ef1
commit
5832c02ff6
71
Cargo.lock
generated
71
Cargo.lock
generated
@ -89,6 +89,24 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "actix-multipart"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c9edfb0e7663d7fe18c8d5b668c9c1bcf79176b1dcc9d4da9592503209a6bfb0"
|
||||||
|
dependencies = [
|
||||||
|
"actix-utils",
|
||||||
|
"actix-web",
|
||||||
|
"bytes",
|
||||||
|
"derive_more",
|
||||||
|
"futures-core",
|
||||||
|
"httparse",
|
||||||
|
"local-waker",
|
||||||
|
"log",
|
||||||
|
"mime",
|
||||||
|
"twoway",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "actix-router"
|
name = "actix-router"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
@ -460,6 +478,18 @@ dependencies = [
|
|||||||
"termcolor",
|
"termcolor",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "filetime"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "firestorm"
|
name = "firestorm"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
@ -522,6 +552,7 @@ dependencies = [
|
|||||||
"futures-task",
|
"futures-task",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"pin-utils",
|
"pin-utils",
|
||||||
|
"slab",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -819,10 +850,14 @@ name = "pages_server"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"actix-files",
|
"actix-files",
|
||||||
|
"actix-multipart",
|
||||||
"actix-web",
|
"actix-web",
|
||||||
|
"bytes",
|
||||||
"clap",
|
"clap",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
|
"futures-util",
|
||||||
"log",
|
"log",
|
||||||
|
"tar",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1091,6 +1126,17 @@ dependencies = [
|
|||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tar"
|
||||||
|
version = "0.4.38"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6"
|
||||||
|
dependencies = [
|
||||||
|
"filetime",
|
||||||
|
"libc",
|
||||||
|
"xattr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "termcolor"
|
name = "termcolor"
|
||||||
version = "1.1.3"
|
version = "1.1.3"
|
||||||
@ -1206,12 +1252,28 @@ dependencies = [
|
|||||||
"lazy_static",
|
"lazy_static",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "twoway"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c57ffb460d7c24cd6eda43694110189030a3d1dfe418416d9468fd1c1d290b47"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
"unchecked-index",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.15.0"
|
version = "1.15.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
|
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unchecked-index"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eeba86d422ce181a719445e51872fa30f1f7413b62becb52e95ec91aa262d85c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicase"
|
name = "unicase"
|
||||||
version = "2.6.0"
|
version = "2.6.0"
|
||||||
@ -1346,6 +1408,15 @@ version = "0.32.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316"
|
checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "xattr"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zstd"
|
name = "zstd"
|
||||||
version = "0.10.0+zstd.1.5.2"
|
version = "0.10.0+zstd.1.5.2"
|
||||||
|
@ -9,5 +9,9 @@ edition = "2021"
|
|||||||
clap = { version = "3.1.6", features = ["derive", "env"] }
|
clap = { version = "3.1.6", features = ["derive", "env"] }
|
||||||
actix-web = "4"
|
actix-web = "4"
|
||||||
actix-files = "0.6"
|
actix-files = "0.6"
|
||||||
|
actix-multipart = "0.4"
|
||||||
env_logger = "0.9.0"
|
env_logger = "0.9.0"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
bytes = "1.1.0"
|
||||||
|
futures-util = { version = "0.3.7", default-features = false, features = ["std"] }
|
||||||
|
tar = "0.4.38"
|
88
src/main.rs
88
src/main.rs
@ -1,10 +1,15 @@
|
|||||||
|
use std::io::Read;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use actix_files::{Files, NamedFile};
|
use actix_files::{Files, NamedFile};
|
||||||
use actix_web::{App, HttpResponse, HttpServer};
|
use actix_multipart::Multipart;
|
||||||
|
use actix_web::{App, Error, HttpRequest, HttpResponse, HttpServer, web};
|
||||||
use actix_web::dev::{fn_service, ServiceRequest, ServiceResponse};
|
use actix_web::dev::{fn_service, ServiceRequest, ServiceResponse};
|
||||||
|
use actix_web::error::{ErrorInternalServerError, ErrorUnauthorized};
|
||||||
use actix_web::middleware::Logger;
|
use actix_web::middleware::Logger;
|
||||||
|
use bytes::BufMut;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
use futures_util::TryStreamExt;
|
||||||
|
|
||||||
/// Simple pages server
|
/// Simple pages server
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
@ -50,6 +55,82 @@ impl Args {
|
|||||||
|
|
||||||
static mut ARGS: Option<Args> = None;
|
static mut ARGS: Option<Args> = None;
|
||||||
|
|
||||||
|
struct NewFile {
|
||||||
|
path: PathBuf,
|
||||||
|
bytes: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Replace all the files of the website
|
||||||
|
async fn replace_files(args: web::Data<Args>, req: HttpRequest, mut payload: Multipart) -> Result<HttpResponse, Error> {
|
||||||
|
|
||||||
|
// Check token
|
||||||
|
let token = match req.headers().get("Token") {
|
||||||
|
None => {
|
||||||
|
return Err(ErrorUnauthorized("Token required!"));
|
||||||
|
}
|
||||||
|
Some(t) => t.to_str()
|
||||||
|
.map_err(|_| ErrorInternalServerError("Failed to parse token!"))?
|
||||||
|
};
|
||||||
|
|
||||||
|
if !token.eq(&args.update_token) || args.update_token.is_empty() {
|
||||||
|
return Err(ErrorUnauthorized("Invalid update token!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut new_files = Vec::new();
|
||||||
|
|
||||||
|
// iterate over multipart stream
|
||||||
|
if let Some(mut field) = payload.try_next().await? {
|
||||||
|
let mut b = bytes::BytesMut::new();
|
||||||
|
|
||||||
|
// Field in turn is stream of *Bytes* object
|
||||||
|
while let Some(chunk) = field.try_next().await? {
|
||||||
|
b.put(chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut archive = tar::Archive::new(b.as_ref());
|
||||||
|
for entry in archive.entries()
|
||||||
|
.map_err(|_| ErrorInternalServerError("Failed to parse TAR archive!"))? {
|
||||||
|
let mut file = entry?;
|
||||||
|
let inner_path = file.header().path()?;
|
||||||
|
|
||||||
|
if inner_path.is_absolute() {
|
||||||
|
return Err(ErrorInternalServerError("Cowardly refusing to unpack absolute file!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if inner_path.is_dir() || inner_path.to_string_lossy().ends_with("/") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let dest_file = args.storage_path().join(inner_path);
|
||||||
|
let mut buf = Vec::with_capacity(file.size() as usize);
|
||||||
|
file.read_to_end(&mut buf)?;
|
||||||
|
|
||||||
|
new_files.push(NewFile {
|
||||||
|
path: dest_file,
|
||||||
|
bytes: buf,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete all current files in storage
|
||||||
|
for entry in std::fs::read_dir(args.storage_path())? {
|
||||||
|
let entry = entry?;
|
||||||
|
if entry.path().is_dir() {
|
||||||
|
std::fs::remove_dir_all(entry.path())?;
|
||||||
|
} else {
|
||||||
|
std::fs::remove_file(entry.path())?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply new files
|
||||||
|
for file in new_files {
|
||||||
|
std::fs::create_dir_all(file.path.parent().unwrap())?;
|
||||||
|
std::fs::write(file.path, file.bytes)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(HttpResponse::Ok().into())
|
||||||
|
}
|
||||||
|
|
||||||
#[actix_web::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
let args: Args = Args::parse();
|
let args: Args = Args::parse();
|
||||||
@ -67,6 +148,10 @@ async fn main() -> std::io::Result<()> {
|
|||||||
HttpServer::new(move || {
|
HttpServer::new(move || {
|
||||||
App::new()
|
App::new()
|
||||||
|
|
||||||
|
// Update service
|
||||||
|
.service(web::resource("/_mgmt/replace_files")
|
||||||
|
.route(web::post().to(replace_files)))
|
||||||
|
|
||||||
// Serve a tree of static files at the web root and specify the index file.
|
// 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
|
// 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`
|
// resolved in the order they are defined. If this would be placed before the `/images`
|
||||||
@ -90,6 +175,7 @@ async fn main() -> std::io::Result<()> {
|
|||||||
|
|
||||||
// Enable the logger.
|
// Enable the logger.
|
||||||
.wrap(Logger::default())
|
.wrap(Logger::default())
|
||||||
|
.app_data(web::Data::new(args.clone()))
|
||||||
})
|
})
|
||||||
.bind(listen_address)?
|
.bind(listen_address)?
|
||||||
.run()
|
.run()
|
||||||
|
Loading…
Reference in New Issue
Block a user