feat: add api to get the hash of a file (#375)
This commit is contained in:
parent
a277698322
commit
9353b2e759
4 changed files with 55 additions and 0 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -507,6 +507,7 @@ dependencies = [
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_yaml",
|
"serde_yaml",
|
||||||
"sha-crypt",
|
"sha-crypt",
|
||||||
|
"sha2",
|
||||||
"smart-default",
|
"smart-default",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
|
|
@ -52,6 +52,7 @@ hyper-util = { version = "0.1", features = ["server-auto", "tokio"] }
|
||||||
http-body-util = "0.1"
|
http-body-util = "0.1"
|
||||||
bytes = "1.5"
|
bytes = "1.5"
|
||||||
pin-project-lite = "0.2"
|
pin-project-lite = "0.2"
|
||||||
|
sha2 = "0.10.8"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["tls"]
|
default = ["tls"]
|
||||||
|
|
|
@ -29,6 +29,7 @@ use hyper::{
|
||||||
Method, StatusCode, Uri,
|
Method, StatusCode, Uri,
|
||||||
};
|
};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
use sha2::{Digest, Sha256};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
@ -307,6 +308,8 @@ impl Server {
|
||||||
} else if query_params.contains_key("view") {
|
} else if query_params.contains_key("view") {
|
||||||
self.handle_edit_file(path, DataKind::View, head_only, user, &mut res)
|
self.handle_edit_file(path, DataKind::View, head_only, user, &mut res)
|
||||||
.await?;
|
.await?;
|
||||||
|
} else if query_params.contains_key("hash") {
|
||||||
|
self.handle_hash_file(path, head_only, &mut res).await?;
|
||||||
} else {
|
} else {
|
||||||
self.handle_send_file(path, headers, head_only, &mut res)
|
self.handle_send_file(path, headers, head_only, &mut res)
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -915,6 +918,24 @@ impl Server {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn handle_hash_file(
|
||||||
|
&self,
|
||||||
|
path: &Path,
|
||||||
|
head_only: bool,
|
||||||
|
res: &mut Response,
|
||||||
|
) -> Result<()> {
|
||||||
|
let output = sha256_file(path).await?;
|
||||||
|
res.headers_mut()
|
||||||
|
.typed_insert(ContentType::from(mime_guess::mime::TEXT_HTML_UTF_8));
|
||||||
|
res.headers_mut()
|
||||||
|
.typed_insert(ContentLength(output.as_bytes().len() as u64));
|
||||||
|
if head_only {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
*res.body_mut() = body_full(output);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
async fn handle_propfind_dir(
|
async fn handle_propfind_dir(
|
||||||
&self,
|
&self,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
|
@ -1716,3 +1737,20 @@ fn parse_upload_offset(headers: &HeaderMap<HeaderValue>, size: u64) -> Result<Op
|
||||||
let (start, _) = parse_range(value, size).ok_or_else(err)?;
|
let (start, _) = parse_range(value, size).ok_or_else(err)?;
|
||||||
Ok(Some(start))
|
Ok(Some(start))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn sha256_file(path: &Path) -> Result<String> {
|
||||||
|
let mut file = fs::File::open(path).await?;
|
||||||
|
let mut hasher = Sha256::new();
|
||||||
|
let mut buffer = [0u8; 8192];
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let bytes_read = file.read(&mut buffer).await?;
|
||||||
|
if bytes_read == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
hasher.update(&buffer[..bytes_read]);
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = hasher.finalize();
|
||||||
|
Ok(format!("{:x}", result))
|
||||||
|
}
|
||||||
|
|
|
@ -189,6 +189,21 @@ fn head_file(server: TestServer) -> Result<(), Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn hash_file(server: TestServer) -> Result<(), Error> {
|
||||||
|
let resp = reqwest::blocking::get(format!("{}index.html?hash", server.url()))?;
|
||||||
|
assert_eq!(
|
||||||
|
resp.headers().get("content-type").unwrap(),
|
||||||
|
"text/html; charset=utf-8"
|
||||||
|
);
|
||||||
|
assert_eq!(resp.status(), 200);
|
||||||
|
assert_eq!(
|
||||||
|
resp.text()?,
|
||||||
|
"c8dd395e3202674b9512f7b7f956e0d96a8ba8f572e785b0d5413ab83766dbc4"
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn get_file_404(server: TestServer) -> Result<(), Error> {
|
fn get_file_404(server: TestServer) -> Result<(), Error> {
|
||||||
let resp = reqwest::blocking::get(format!("{}404", server.url()))?;
|
let resp = reqwest::blocking::get(format!("{}404", server.url()))?;
|
||||||
|
|
Loading…
Reference in a new issue