Skip to content

Commit 1d09ed9

Browse files
committed
fix bugs
1 parent 716af06 commit 1d09ed9

File tree

12 files changed

+81
-106
lines changed

12 files changed

+81
-106
lines changed

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,5 @@ tracing-core = "0.1.32"
4343
tracing-subscriber = { version = "0.3"}
4444
walkdir = "2.5"
4545
warp = "0.4.2"
46-
salvo = "0.85.0"
46+
salvo = "0.85.0"
47+
dunce = "1"

client/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,5 @@ md-5 = { workspace = true }
4848
# util
4949
anyhow = { workspace = true, features = ["backtrace"] }
5050
walkdir = { workspace = true }
51-
if_chain = { workspace = true }
51+
if_chain = { workspace = true }
52+
dunce = { workspace = true }

client/src/api.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,6 @@ impl API {
107107
string_resp!(resp)
108108
}
109109

110-
pub async fn reload_spa_server(&self) -> anyhow::Result<()> {
111-
let resp = self.async_client.post(self.url("reload")).send().await?;
112-
handle!(resp)
113-
}
114-
115110
pub async fn remove_files(
116111
&self,
117112
domain: Option<String>,

client/src/commands.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ pub enum Commands {
2020
domain: String,
2121
version: Option<u32>,
2222
},
23-
Reload,
2423
Delete {
2524
domain: Option<String>,
2625
max_reserve: Option<u32>,

client/src/lib.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,6 @@ async fn run_with_commands(commands: CliCommand) -> anyhow::Result<()> {
5151
let resp = api.release_domain_version(domain, version).await?;
5252
success(&resp);
5353
}
54-
Commands::Reload => {
55-
api.reload_spa_server().await?;
56-
success("reload success!");
57-
}
5854
Commands::Delete {
5955
domain,
6056
max_reserve,

client/src/upload_files.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,6 @@ pub async fn upload_files(
3131
if !path.is_dir() {
3232
return Err(anyhow!("{:?} is not a directory", path));
3333
}
34-
35-
let prefix_path = path
36-
.to_str()
37-
.ok_or_else(|| anyhow!("upload path can not parse"))?
38-
.to_string();
3934
let version = get_upload_version(&api, &domain, version).await?;
4035
println!("begin to fetch server file metadata with md5, you may need to wait if there are large number of files.");
4136
let server_metadata = api.get_file_metadata(&domain, version).await?;
@@ -53,6 +48,7 @@ pub async fn upload_files(
5348
.collect::<HashMap<String, ShortMetaData>>();
5449

5550
let mut byte_buffer = vec![0u8; 1024 * 1024];
51+
let parent = path.clone();
5652
let uploading_files = WalkDir::new(path)
5753
.min_depth(1)
5854
.into_iter()
@@ -61,10 +57,11 @@ pub async fn upload_files(
6157
if let Some(entity) = entity.ok();
6258
if let Some(metadata) = entity.metadata().ok();
6359
if metadata.is_file();
64-
if let Some(path) = entity.path().to_str().map(|x|x.to_string());
60+
if let Ok(key) = entity.path().strip_prefix(&parent);
6561
then {
66-
let prefix = format!("{prefix_path}/");
67-
let key = path.replace(&prefix,"");
62+
let key = key.components().map(|c| c.as_os_str().to_string_lossy())
63+
.collect::<Vec<_>>()
64+
.join("/");
6865
if server_metadata.get(&key).filter(|x|{
6966
let md5 = md5_file(entity.path(), &mut byte_buffer);
7067
x.length == metadata.len() &&

server/src/domain_storage.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ impl DomainStorage {
333333
let data = self.cache.cache_dir(host, path, version, &new_path)?;
334334
self.cache.update(host.to_string(), path, version, data);
335335
debug!(
336-
"domain: {host} all keys:{:?}",
336+
"domain: {host} sub_path: {path:?} all keys:{:?}",
337337
self.cache.get_all_keys(host)
338338
);
339339
info!(

server/src/file_cache.rs

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -90,36 +90,31 @@ impl FileCache {
9090
version: u32,
9191
path: &PathBuf,
9292
) -> anyhow::Result<HashMap<String, Arc<CacheItem>>> {
93-
let prefix = path
93+
let _ = path
9494
.to_str()
9595
.map(|x| Ok(format!("{x}/")))
9696
.unwrap_or(Err(anyhow!("can not parse path")))?;
97+
let parent = path.clone();
9798
let mut result: HashMap<String, Arc<CacheItem>> = WalkDir::new(path)
9899
.min_depth(1)
99100
.into_iter()
100101
.filter_map(|x| x.ok())
101102
.filter_map(|entry| {
102103
if let Ok(metadata) = entry.metadata() {
103104
if metadata.is_file() {
104-
let path = entry.path();
105-
let file = File::open(path).ok()?;
106-
let mut reader = BufReader::new(file);
107-
let mut bytes: Vec<u8> = vec![];
108-
reader.read_to_end(&mut bytes).ok()?;
109-
let entry_path = entry.into_path();
110-
return entry_path.clone().to_str().map(|x| {
111-
let key = x.replace(&prefix, "");
105+
if let Ok(key) = entry.path().strip_prefix(&parent) {
106+
let key = key.components()
107+
.map(|c| c.as_os_str().to_string_lossy())
108+
.collect::<Vec<_>>()
109+
.join("/");
112110
let key = sub_path
113111
.map(|sub_path| format!("{sub_path}/{key}"))
114112
.unwrap_or(key);
115-
(
116-
key,
117-
Arc::new(CacheItem {
118-
data: entry_path,
119-
version,
120-
}),
121-
)
122-
});
113+
return Some((key , Arc::new(CacheItem {
114+
data: entry.path().to_path_buf(),
115+
version,
116+
})))
117+
}
123118
}
124119
}
125120
None

server/src/web_server.rs

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1+
use std::borrow::Cow;
12
use crate::config::Config;
23
use crate::domain_storage::DomainStorage;
34
use crate::service::ServiceConfig;
45
use salvo::fs::NamedFile;
56
use salvo::http::header::LOCATION;
6-
use salvo::http::uri::{Authority, Uri};
7+
use salvo::http::uri::{Authority, PathAndQuery, Uri};
78
use salvo::prelude::*;
89
use std::str::FromStr;
910
use std::sync::Arc;
11+
use salvo::http::{ParseError, ResBody};
1012

1113
#[inline]
1214
pub(crate) fn decode_url_path_safely(path: &str) -> String {
@@ -60,11 +62,26 @@ fn alias_redirect(uri: &Uri, https: bool, host: &str, external_port: u16, res: &
6062
res.status_code(StatusCode::MOVED_PERMANENTLY);
6163
}
6264

65+
fn replace_uri_path(original_uri: &Uri, new_path: &str) -> Result<Uri, ParseError> {
66+
let mut uri_parts = original_uri.clone().into_parts();
67+
uri_parts.authority = None;
68+
uri_parts.scheme = None;
69+
let path = match original_uri.query() {
70+
Some(query) => Cow::from(format!("{new_path}?{query}")),
71+
None => Cow::from(new_path),
72+
};
73+
74+
uri_parts.path_and_query = Some(PathAndQuery::from_str(path.as_ref())?);
75+
Ok(Uri::from_parts(uri_parts)?)
76+
}
77+
78+
6379
#[handler]
6480
async fn file_resp(req: &mut Request, depot: &mut Depot, res: &mut Response, _ctrl: &mut FlowCtrl) {
81+
6582
let domain_storage = depot.obtain::<Arc<DomainStorage>>().unwrap();
6683
let service_config = depot.obtain::<Arc<ServiceConfig>>().unwrap();
67-
let config = depot.obtain::<Arc<Config>>().unwrap();
84+
// let config = depot.obtain::<Arc<Config>>().unwrap();
6885

6986
let author_opt = get_authority(req);
7087
if let Some(author) = author_opt {
@@ -96,13 +113,37 @@ async fn file_resp(req: &mut Request, depot: &mut Depot, res: &mut Response, _ct
96113
&*decode_url_path_safely(req_path)
97114
};
98115
let rel_path = format_url_path_safely(rel_path);
116+
tracing::debug!("hit {rel_path}");
99117
match domain_storage.get_file(host, &rel_path) {
100118
Some(item) => {
101119
NamedFile::builder(&item.data)
102120
.send(req.headers(), res)
103121
.await;
104122
}
105123
None => {
124+
// trailing slash
125+
let original_path = req.uri().path();
126+
if !original_path.is_empty() && original_path != "/" {
127+
let ends_with_slash = original_path.ends_with('/');
128+
129+
if !ends_with_slash {
130+
if let Ok(new_uri) = replace_uri_path(req.uri(), &format!("{original_path}/")) {
131+
res.body(ResBody::None);
132+
133+
match Redirect::with_status_code(StatusCode::MOVED_PERMANENTLY, new_uri) {
134+
Ok(redirect)=> {
135+
res.render(redirect);
136+
}
137+
Err(e) => {
138+
tracing::error!(error = ?e, "redirect failed");
139+
}
140+
}
141+
return
142+
}
143+
144+
}
145+
}
146+
106147
res.status_code(StatusCode::NOT_FOUND);
107148
}
108149
}
@@ -122,13 +163,11 @@ pub async fn init_http_server(
122163
.await;
123164

124165
// StaticDir::new();
125-
let router = Router::with_hoop(trailing_slash::add_slash())
126-
.hoop(
166+
let router = Router::with_hoop(
127167
affix_state::inject(service_config.clone())
128168
.inject(storage.clone())
129169
.inject(conf.clone()),
130-
)
131-
.path("{*path}")
170+
).path("{*path}")
132171
.get(file_resp);
133172

134173
Server::new(listener).serve(router).await;

0 commit comments

Comments
 (0)