A file's revision reads the same after a save as it does when listed (#3)
This commit was merged in pull request #3.
This commit is contained in:
+27
-3
@@ -185,7 +185,7 @@ pub fn multistatus(body: &[u8]) -> Result<Vec<Found>, ErrorCode> {
|
|||||||
b"getcontentlength" => {
|
b"getcontentlength" => {
|
||||||
entry.length = value.trim().parse().unwrap_or(0);
|
entry.length = value.trim().parse().unwrap_or(0);
|
||||||
}
|
}
|
||||||
b"getetag" => entry.etag = Some(value.trim().to_owned()),
|
b"getetag" => entry.etag = Some(etag(&value)),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -207,6 +207,22 @@ pub fn multistatus(body: &[u8]) -> Result<Vec<Found>, ErrorCode> {
|
|||||||
Ok(found)
|
Ok(found)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An entity tag in the quoted form an `ETag` header carries.
|
||||||
|
///
|
||||||
|
/// Some servers, WsgiDAV among them, list `getetag` bare while their `ETag`
|
||||||
|
/// header quotes the same tag, so a revision read from a listing and one
|
||||||
|
/// returned by a write would differ for the same bytes. Quoting a bare tag
|
||||||
|
/// gives every revision one spelling, and `If-Match` accepts that form. A tag
|
||||||
|
/// that is already quoted, weak or strong, is kept as it is.
|
||||||
|
pub fn etag(value: &str) -> String {
|
||||||
|
let value = value.trim();
|
||||||
|
if value.starts_with('"') || value.starts_with("W/\"") {
|
||||||
|
value.to_owned()
|
||||||
|
} else {
|
||||||
|
format!("\"{value}\"")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Strips any namespace prefix, so `d:href` and `D:href` read the same.
|
/// Strips any namespace prefix, so `d:href` and `D:href` read the same.
|
||||||
fn local(name: &[u8]) -> &[u8] {
|
fn local(name: &[u8]) -> &[u8] {
|
||||||
match name.iter().position(|byte| *byte == b':') {
|
match name.iter().position(|byte| *byte == b':') {
|
||||||
@@ -264,8 +280,8 @@ pub fn removable(found: &[Found]) -> Result<(), ErrorCode> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{
|
use super::{
|
||||||
Body, Found, basic, children, multistatus, name_of, outcome, range_outcome,
|
Body, Found, basic, children, etag, multistatus, name_of, outcome,
|
||||||
removable, url,
|
range_outcome, removable, url,
|
||||||
};
|
};
|
||||||
use crate::sdk::ErrorCode;
|
use crate::sdk::ErrorCode;
|
||||||
|
|
||||||
@@ -414,4 +430,12 @@ mod tests {
|
|||||||
assert_eq!(name_of(&found[1].href), "a b.md");
|
assert_eq!(name_of(&found[1].href), "a b.md");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bare_etags_are_quoted_like_headers() {
|
||||||
|
assert_eq!(etag("1996000-1790356720-264"), "\"1996000-1790356720-264\"");
|
||||||
|
assert_eq!(etag(" \"v1\" "), "\"v1\"");
|
||||||
|
assert_eq!(etag("W/\"v1\""), "W/\"v1\"");
|
||||||
|
assert_eq!(etag("W/v1"), "\"W/v1\"");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -246,7 +246,7 @@ impl GuestWriter for DavWriter {
|
|||||||
.headers
|
.headers
|
||||||
.iter()
|
.iter()
|
||||||
.find(|header| header.name.eq_ignore_ascii_case("etag"))
|
.find(|header| header.name.eq_ignore_ascii_case("etag"))
|
||||||
.map(|header| header.value.clone());
|
.map(|header| dav::etag(&header.value));
|
||||||
Ok(Some(FileInfo {
|
Ok(Some(FileInfo {
|
||||||
kind: EntryKind::File,
|
kind: EntryKind::File,
|
||||||
size: self.written.get(),
|
size: self.written.get(),
|
||||||
@@ -369,7 +369,7 @@ impl Guest for Webdav {
|
|||||||
.headers
|
.headers
|
||||||
.iter()
|
.iter()
|
||||||
.find(|header| header.name.eq_ignore_ascii_case("etag"))
|
.find(|header| header.name.eq_ignore_ascii_case("etag"))
|
||||||
.map(|header| header.value.clone())
|
.map(|header| dav::etag(&header.value))
|
||||||
});
|
});
|
||||||
Ok(Reader::new(DavReader {
|
Ok(Reader::new(DavReader {
|
||||||
call,
|
call,
|
||||||
|
|||||||
Reference in New Issue
Block a user