Support CORS
This commit is contained in:
parent
83bdcecd83
commit
9794f37842
@ -14,7 +14,7 @@ crate-type = ["cdylib"]
|
||||
async-trait = "0.1.74"
|
||||
base64 = "0.21.5"
|
||||
lazy_static = "1.4.0"
|
||||
worker = "0.0.15"
|
||||
worker = "0.0.18"
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
|
92
src/dav.rs
92
src/dav.rs
@ -10,9 +10,9 @@ pub struct Dav {
|
||||
fs: R2,
|
||||
}
|
||||
|
||||
type DavResponse = (u16, HashMap<String, String>, String);
|
||||
type DavErrResponse = (u16, Option<HashMap<String, String>>, Option<String>);
|
||||
type DavStreamResponse = (u16, HashMap<String, String>, ByteStream);
|
||||
pub type DavResponse = (u16, HashMap<String, String>, String);
|
||||
pub type DavErrResponse = (u16, Option<HashMap<String, String>>, Option<String>);
|
||||
pub type DavStreamResponse = (u16, HashMap<String, String>, ByteStream);
|
||||
|
||||
pub enum DavResponseType {
|
||||
DavResponse(Result<DavResponse, DavErrResponse>),
|
||||
@ -32,8 +32,16 @@ impl From<Result<DavStreamResponse, DavErrResponse>> for DavResponseType {
|
||||
}
|
||||
|
||||
static DAV_CLASS: &str = "1";
|
||||
static SUPPORT_METHODS: [&str; 8] = [
|
||||
"OPTIONS", "PROPFIND", "MKCOL", "GET", "HEAD", "PUT", "COPY", "MOVE",
|
||||
static SUPPORT_METHODS: [&str; 9] = [
|
||||
"OPTIONS",
|
||||
"PROPFIND",
|
||||
"PROPPATCH",
|
||||
"MKCOL",
|
||||
"GET",
|
||||
"HEAD",
|
||||
"PUT",
|
||||
"COPY",
|
||||
"MOVE",
|
||||
];
|
||||
|
||||
impl Dav {
|
||||
@ -61,9 +69,9 @@ impl Dav {
|
||||
depth: Depth,
|
||||
req_body: String,
|
||||
) -> Result<DavResponse, DavErrResponse> {
|
||||
if req_body.len() > 0 {
|
||||
return Err((415, None, None));
|
||||
}
|
||||
// if req_body.len() > 0 {
|
||||
// return Err((415, None, None));
|
||||
// }
|
||||
|
||||
let mut headers = HashMap::new();
|
||||
headers.insert(
|
||||
@ -78,7 +86,7 @@ impl Dav {
|
||||
Some(vec![("xmlns:D".to_string(), "DAV:".to_string())]),
|
||||
None,
|
||||
);
|
||||
match self.fs.list(path).await {
|
||||
match self.fs.list(path.clone()).await {
|
||||
Ok(items) => {
|
||||
for (href, properties) in items {
|
||||
let mut response =
|
||||
@ -124,7 +132,7 @@ impl Dav {
|
||||
|
||||
Ok((207, headers, multistatus.build()))
|
||||
}
|
||||
Err(_) => return Err((404, None, None)),
|
||||
Err(message) => return Err((404, None, Some(message))),
|
||||
}
|
||||
}
|
||||
Depth::Zero => {
|
||||
@ -133,12 +141,17 @@ impl Dav {
|
||||
Some(vec![("xmlns:D".to_string(), "DAV:".to_string())]),
|
||||
None,
|
||||
);
|
||||
match self.fs.get(path).await {
|
||||
match self.fs.get(path.clone()).await {
|
||||
Ok((href, properties)) => {
|
||||
let mut response = XMLBuilder::new("D:response".to_string(), None, None);
|
||||
let response = multistatus.elem("D:response".to_string(), None, None);
|
||||
response.elem("D:href".to_string(), None, Some(href));
|
||||
let mut propstat = XMLBuilder::new("D:propstat".to_string(), None, None);
|
||||
let mut prop = XMLBuilder::new("D:prop".to_string(), None, None);
|
||||
let propstat = response.elem("D:propstat".to_string(), None, None);
|
||||
propstat.elem(
|
||||
"D:status".to_string(),
|
||||
None,
|
||||
Some("HTTP/1.1 200 OK".to_string()),
|
||||
);
|
||||
let prop = propstat.elem("D:prop".to_string(), None, None);
|
||||
prop.elem("D:creationdate".to_string(), None, properties.creation_date);
|
||||
prop.elem("D:displayname".to_string(), None, properties.display_name);
|
||||
prop.elem(
|
||||
@ -164,28 +177,63 @@ impl Dav {
|
||||
None,
|
||||
properties.get_last_modified,
|
||||
);
|
||||
propstat.add(prop);
|
||||
|
||||
Ok((207, (headers), (multistatus.build())))
|
||||
}
|
||||
Err(_) => {
|
||||
if !path.ends_with("/") {
|
||||
return Err((404, None, None));
|
||||
}
|
||||
let response = multistatus.elem("D:response".to_string(), None, None);
|
||||
response.elem("D:href".to_string(), None, Some(path));
|
||||
let propstat = response.elem("D:propstat".to_string(), None, None);
|
||||
propstat.elem(
|
||||
"D:status".to_string(),
|
||||
None,
|
||||
Some("HTTP/1.1 200 OK".to_string()),
|
||||
);
|
||||
response.add(propstat);
|
||||
multistatus.add(response);
|
||||
propstat.elem("D:prop".to_string(), None, None);
|
||||
|
||||
Ok((207, (headers), (multistatus.build())))
|
||||
}
|
||||
Err(_) => return Err((404, None, None)),
|
||||
}
|
||||
}
|
||||
Depth::Infinity => return Err((400, None, None)),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn handle_mkcol(
|
||||
pub async fn handle_proppatch(
|
||||
&self,
|
||||
path: String,
|
||||
req_body: String,
|
||||
) -> Result<DavResponse, DavErrResponse> {
|
||||
let mut headers = HashMap::new();
|
||||
headers.insert(
|
||||
"Content-Type".to_string(),
|
||||
"application/xml; charset=utf-8".to_string(),
|
||||
);
|
||||
let mut multistatus = XMLBuilder::new(
|
||||
"D:multistatus".to_string(),
|
||||
Some(vec![("xmlns:D".to_string(), "DAV:".to_string())]),
|
||||
None,
|
||||
);
|
||||
let response = multistatus.elem("D:response".to_string(), None, None);
|
||||
response.elem("D:href".to_string(), None, Some(path));
|
||||
let propstat = response.elem("D:propstat".to_string(), None, None);
|
||||
let prop = propstat.elem("D:prop".to_string(), None, None);
|
||||
// TODO
|
||||
propstat.elem(
|
||||
"D:status".to_string(),
|
||||
None,
|
||||
Some("HTTP/1.1 200 OK".to_string()),
|
||||
);
|
||||
Ok((207, HashMap::new(), multistatus.build()))
|
||||
}
|
||||
|
||||
pub async fn handle_mkcol(
|
||||
&self,
|
||||
_: String,
|
||||
req_body: String,
|
||||
) -> Result<DavResponse, DavErrResponse> {
|
||||
if req_body.len() > 0 {
|
||||
return Err((415, None, None));
|
||||
@ -233,7 +281,7 @@ impl Dav {
|
||||
_ => Ok((200, (headers), stream)),
|
||||
}
|
||||
}
|
||||
Err(_) => return Err((404, None, None)),
|
||||
Err(message) => return Err((404, None, Some(message))),
|
||||
}
|
||||
}
|
||||
|
||||
@ -261,7 +309,9 @@ impl Dav {
|
||||
.join(", ");
|
||||
return Ok((200, (headers), (html)));
|
||||
}
|
||||
Err(_) => return Err((404, None, None)),
|
||||
Err(message) => {
|
||||
return Err((404, None, Some(message)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
392
src/lib.rs
392
src/lib.rs
@ -1,6 +1,6 @@
|
||||
use crate::values::Depth;
|
||||
use base64;
|
||||
use dav::DavResponseType;
|
||||
use dav::{DavErrResponse, DavResponse, DavResponseType, DavStreamResponse};
|
||||
use r2::R2;
|
||||
use values::Overwrite;
|
||||
use worker::*;
|
||||
@ -11,7 +11,7 @@ mod values;
|
||||
mod xml;
|
||||
|
||||
#[event(fetch)]
|
||||
async fn main(req: Request, env: Env, _: Context) -> Result<Response> {
|
||||
async fn main(mut req: Request, env: Env, _: Context) -> Result<Response> {
|
||||
let username = env.var("USERNAME").unwrap().to_string();
|
||||
let password = env.var("PASSWORD").unwrap().to_string();
|
||||
let protocol = env.var("PROTOCOL").unwrap().to_string();
|
||||
@ -29,7 +29,103 @@ async fn main(req: Request, env: Env, _: Context) -> Result<Response> {
|
||||
"r2" => R2::new(env.bucket(bucket_name.as_str()).unwrap()),
|
||||
_ => panic!("PROTOCOL {} not supported", protocol),
|
||||
});
|
||||
worker(req, dav).await
|
||||
|
||||
let mut response = match match req.inner().method().as_str() {
|
||||
"PROPFIND" => {
|
||||
let request_body = req.text().await?;
|
||||
console_debug!("request_body {:?}", request_body);
|
||||
dav.handle_propfind(req.path(), parse_depth(&req), request_body)
|
||||
.await
|
||||
.into()
|
||||
}
|
||||
"PROPPATCH" => {
|
||||
let request_body = req.text().await?;
|
||||
console_debug!("request_body {:?}", request_body);
|
||||
dav.handle_proppatch(req.path(), request_body).await.into()
|
||||
}
|
||||
"OPTIONS" => dav.handle_options().await.into(),
|
||||
"MKCOL" => dav.handle_mkcol(req.path(), req.text().await?).await.into(),
|
||||
"GET" => {
|
||||
if req.path().ends_with("/") {
|
||||
dav.handle_get_dir(req.path()).await.into()
|
||||
} else {
|
||||
dav.handle_get_obj(req.path(), parse_range(&req))
|
||||
.await
|
||||
.into()
|
||||
}
|
||||
}
|
||||
"HEAD" => {
|
||||
if req.path().ends_with("/") {
|
||||
dav.handle_head_dir(req.path()).await.into()
|
||||
} else {
|
||||
dav.handle_head_obj(req.path(), parse_range(&req))
|
||||
.await
|
||||
.into()
|
||||
}
|
||||
}
|
||||
"DELETE" => dav.handle_delete(req.path()).await.into(),
|
||||
"PUT" => dav
|
||||
.handle_put(
|
||||
req.path(),
|
||||
req.stream().unwrap(),
|
||||
req.headers()
|
||||
.get("content-length")
|
||||
.unwrap()
|
||||
.map_or(0, |v| v.parse::<u64>().unwrap()),
|
||||
)
|
||||
.await
|
||||
.into(),
|
||||
"COPY" => dav
|
||||
.handle_copy(
|
||||
req.path(),
|
||||
parse_destination(&req),
|
||||
parse_depth(&req),
|
||||
parse_overwrite(&req),
|
||||
)
|
||||
.await
|
||||
.into(),
|
||||
"MOVE" => dav
|
||||
.handle_move(
|
||||
req.path(),
|
||||
parse_destination(&req),
|
||||
parse_depth(&req),
|
||||
parse_overwrite(&req),
|
||||
)
|
||||
.await
|
||||
.into(),
|
||||
_ => dav.handle_unsupport_method().await.into(),
|
||||
} {
|
||||
DavResponseType::DavResponse(r) => r.map_or_else(from_dav_err_response, from_dav_response),
|
||||
DavResponseType::DavStreamResponse(r) => {
|
||||
r.map_or_else(from_dav_err_response, from_dav_stream_response)
|
||||
}
|
||||
};
|
||||
|
||||
let cors = Cors::new()
|
||||
.with_origins(
|
||||
req.headers()
|
||||
.get("origin")
|
||||
.unwrap()
|
||||
.map_or(vec![], |v| vec![v.to_string()]),
|
||||
)
|
||||
.with_methods(Method::all())
|
||||
.with_allowed_headers([
|
||||
"authorization",
|
||||
"content-type",
|
||||
"depth",
|
||||
"overwrite",
|
||||
"destination",
|
||||
"range",
|
||||
])
|
||||
.with_exposed_headers([
|
||||
"content-length",
|
||||
"content-type",
|
||||
"etag",
|
||||
"last-modified",
|
||||
"range",
|
||||
]);
|
||||
response = response.map(|response| response.with_cors(&cors).unwrap());
|
||||
response
|
||||
}
|
||||
|
||||
fn basic_authorization(
|
||||
@ -47,208 +143,102 @@ fn basic_authorization(
|
||||
}))
|
||||
};
|
||||
|
||||
match authorization_header {
|
||||
Some(text) => {
|
||||
let a: Vec<&str> = text.split(" ").collect();
|
||||
if a.len() != 2 || a[0] != "Basic" {
|
||||
return basic_authorization_error_response();
|
||||
}
|
||||
if let Ok(v) = base64::decode(a[1]) {
|
||||
let v = match String::from_utf8(v) {
|
||||
Ok(v) => v,
|
||||
Err(_) => return basic_authorization_error_response(),
|
||||
};
|
||||
let v: Vec<&str> = v.split(":").collect();
|
||||
if v.len() != 2 {
|
||||
return basic_authorization_error_response();
|
||||
}
|
||||
if v[0] != username || v[1] != password {
|
||||
return basic_authorization_error_response();
|
||||
}
|
||||
|
||||
return None;
|
||||
} else {
|
||||
return basic_authorization_error_response();
|
||||
}
|
||||
if let Some(text) = authorization_header {
|
||||
let a: Vec<&str> = text.split(" ").collect();
|
||||
if a.len() != 2 || a[0] != "Basic" {
|
||||
return basic_authorization_error_response();
|
||||
}
|
||||
None => {
|
||||
if let Ok(v) = base64::decode(a[1]) {
|
||||
let v = match String::from_utf8(v) {
|
||||
Ok(v) => v,
|
||||
Err(_) => return basic_authorization_error_response(),
|
||||
};
|
||||
let v: Vec<&str> = v.split(":").collect();
|
||||
if v.len() != 2 {
|
||||
return basic_authorization_error_response();
|
||||
}
|
||||
if v[0] != username || v[1] != password {
|
||||
return basic_authorization_error_response();
|
||||
}
|
||||
|
||||
return None;
|
||||
} else {
|
||||
return basic_authorization_error_response();
|
||||
}
|
||||
}
|
||||
|
||||
return basic_authorization_error_response();
|
||||
}
|
||||
|
||||
async fn worker(mut req: Request, dav: dav::Dav) -> Result<Response> {
|
||||
let dav_response: DavResponseType = match req.inner().method().as_str() {
|
||||
"PROPFIND" => {
|
||||
let depth: Depth = req
|
||||
.headers()
|
||||
.get("depth")
|
||||
.unwrap()
|
||||
.map_or("infinity".to_string(), |v| v)
|
||||
.into();
|
||||
let resource_path = req.path();
|
||||
dav.handle_propfind(resource_path, depth, req.text().await?)
|
||||
.await
|
||||
.into()
|
||||
}
|
||||
"OPTIONS" => dav.handle_options().await.into(),
|
||||
"MKCOL" => {
|
||||
let resource_path = req.path();
|
||||
dav.handle_mkcol(resource_path, req.text().await?)
|
||||
.await
|
||||
.into()
|
||||
}
|
||||
"GET" => {
|
||||
let resource_path = req.path();
|
||||
let range = req.headers().get("range").unwrap().map_or(
|
||||
values::Range {
|
||||
start: None,
|
||||
end: None,
|
||||
},
|
||||
|v| values::Range::from(v.to_string().split("bytes=").next().unwrap().to_string()),
|
||||
);
|
||||
if resource_path.ends_with("/") {
|
||||
dav.handle_get_dir(resource_path).await.into()
|
||||
} else {
|
||||
dav.handle_get_obj(resource_path, range).await.into()
|
||||
}
|
||||
}
|
||||
"HEAD" => {
|
||||
let resource_path = req.path();
|
||||
let range = req.headers().get("range").unwrap().map_or(
|
||||
values::Range {
|
||||
start: None,
|
||||
end: None,
|
||||
},
|
||||
|v| values::Range::from(v.to_string().split("bytes=").next().unwrap().to_string()),
|
||||
);
|
||||
if resource_path.ends_with("/") {
|
||||
dav.handle_head_dir(resource_path).await.into()
|
||||
} else {
|
||||
dav.handle_head_obj(resource_path, range).await.into()
|
||||
}
|
||||
}
|
||||
"DELETE" => {
|
||||
let resource_path = req.path();
|
||||
dav.handle_delete(resource_path).await.into()
|
||||
}
|
||||
"PUT" => {
|
||||
let resource_path = req.path();
|
||||
let content_length = req
|
||||
.headers()
|
||||
.get("content-length")
|
||||
.unwrap()
|
||||
.map_or(0, |v| v.parse::<u64>().unwrap());
|
||||
println!("content-length: {}", content_length);
|
||||
dav.handle_put(resource_path, req.stream().unwrap(), content_length)
|
||||
.await
|
||||
.into()
|
||||
}
|
||||
"COPY" => {
|
||||
let resource_path = req.path();
|
||||
let destination =
|
||||
req.headers()
|
||||
.get("destination")
|
||||
.unwrap()
|
||||
.map_or("".to_string(), |v| {
|
||||
v.split("http://")
|
||||
.nth(1)
|
||||
.unwrap()
|
||||
.split("/")
|
||||
.skip(1)
|
||||
.collect::<Vec<&str>>()
|
||||
.join("/")
|
||||
});
|
||||
let depth: Depth = req
|
||||
.headers()
|
||||
.get("depth")
|
||||
.unwrap()
|
||||
.map_or("infinity".to_string(), |v| v)
|
||||
.into();
|
||||
let overwrite: Overwrite = req
|
||||
.headers()
|
||||
.get("overwrite")
|
||||
.unwrap()
|
||||
.map_or("T".to_string(), |v| v.to_string())
|
||||
.into();
|
||||
dav.handle_copy(resource_path, destination, depth, overwrite)
|
||||
.await
|
||||
.into()
|
||||
}
|
||||
"MOVE" => {
|
||||
let resource_path = req.path();
|
||||
let destination =
|
||||
req.headers()
|
||||
.get("destination")
|
||||
.unwrap()
|
||||
.map_or("".to_string(), |v| {
|
||||
v.split("http://")
|
||||
.nth(1)
|
||||
.unwrap()
|
||||
.split("/")
|
||||
.skip(1)
|
||||
.collect::<Vec<&str>>()
|
||||
.join("/")
|
||||
});
|
||||
let depth: Depth = req
|
||||
.headers()
|
||||
.get("depth")
|
||||
.unwrap()
|
||||
.map_or("infinity".to_string(), |v| v)
|
||||
.into();
|
||||
let overwrite: Overwrite = req
|
||||
.headers()
|
||||
.get("overwrite")
|
||||
.unwrap()
|
||||
.map_or("T".to_string(), |v| v.to_string())
|
||||
.into();
|
||||
dav.handle_move(resource_path, destination, depth, overwrite)
|
||||
.await
|
||||
.into()
|
||||
}
|
||||
_ => dav.handle_unsupport_method().await.into(),
|
||||
};
|
||||
|
||||
match dav_response {
|
||||
DavResponseType::DavResponse(r) => r.map_or_else(
|
||||
|e| {
|
||||
let (status_code, headers, body) = e;
|
||||
Response::error(body.unwrap_or("".to_string()), status_code).map(|response| {
|
||||
match headers {
|
||||
Some(headers) => response.with_headers(Headers::from_iter(headers)),
|
||||
None => response,
|
||||
}
|
||||
.with_status(status_code)
|
||||
})
|
||||
},
|
||||
|r| {
|
||||
let (status_code, headers, body) = r;
|
||||
Response::from_body(ResponseBody::Body(body.into_bytes())).map(|response| {
|
||||
response
|
||||
.with_headers(Headers::from_iter(headers))
|
||||
.with_status(status_code)
|
||||
})
|
||||
},
|
||||
),
|
||||
DavResponseType::DavStreamResponse(r) => r.map_or_else(
|
||||
|e| {
|
||||
let (status_code, headers, body) = e;
|
||||
Response::error(body.unwrap_or("".to_string()), status_code).map(|response| {
|
||||
match headers {
|
||||
Some(headers) => response.with_headers(Headers::from_iter(headers)),
|
||||
None => response,
|
||||
}
|
||||
.with_status(status_code)
|
||||
})
|
||||
},
|
||||
|r| {
|
||||
let (status_code, headers, body) = r;
|
||||
Response::from_stream(body).map(|response| {
|
||||
response
|
||||
.with_headers(Headers::from_iter(headers))
|
||||
.with_status(status_code)
|
||||
})
|
||||
},
|
||||
),
|
||||
}
|
||||
fn parse_depth(req: &Request) -> Depth {
|
||||
req.headers()
|
||||
.get("depth")
|
||||
.unwrap()
|
||||
.map_or("infinity".to_string(), |v| v)
|
||||
.into()
|
||||
}
|
||||
|
||||
fn parse_range(req: &Request) -> values::Range {
|
||||
req.headers().get("range").unwrap().map_or(
|
||||
values::Range {
|
||||
start: None,
|
||||
end: None,
|
||||
},
|
||||
|v| values::Range::from(v.to_string().split("bytes=").next().unwrap().to_string()),
|
||||
)
|
||||
}
|
||||
|
||||
fn parse_destination(req: &Request) -> String {
|
||||
req.headers()
|
||||
.get("destination")
|
||||
.unwrap()
|
||||
.map_or("".to_string(), |v| {
|
||||
v.split("http://")
|
||||
.nth(1)
|
||||
.unwrap()
|
||||
.split("/")
|
||||
.skip(1)
|
||||
.collect::<Vec<&str>>()
|
||||
.join("/")
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_overwrite(req: &Request) -> Overwrite {
|
||||
req.headers()
|
||||
.get("overwrite")
|
||||
.unwrap()
|
||||
.map_or("T".to_string(), |v| v.to_string())
|
||||
.into()
|
||||
}
|
||||
|
||||
fn from_dav_err_response(response: DavErrResponse) -> Result<Response> {
|
||||
let (status_code, headers, body) = response;
|
||||
console_debug!("{} {:?} {:?}", status_code, headers, body);
|
||||
Response::error(body.unwrap_or("".to_string()), status_code).map(|response| {
|
||||
match headers {
|
||||
Some(headers) => response.with_headers(Headers::from_iter(headers)),
|
||||
None => response,
|
||||
}
|
||||
.with_status(status_code)
|
||||
})
|
||||
}
|
||||
|
||||
fn from_dav_response(response: DavResponse) -> Result<Response> {
|
||||
let (status_code, headers, body) = response;
|
||||
console_debug!("{} {:?} {:?}", status_code, headers, body);
|
||||
Response::from_bytes(body.into_bytes()).map(|response| {
|
||||
response
|
||||
.with_headers(Headers::from_iter(headers))
|
||||
.with_status(status_code)
|
||||
})
|
||||
}
|
||||
|
||||
fn from_dav_stream_response(response: DavStreamResponse) -> Result<Response> {
|
||||
let (status_code, headers, body) = response;
|
||||
console_debug!("{} {:?} {:?}", status_code, headers, body);
|
||||
Response::from_stream(body).map(|response| {
|
||||
response
|
||||
.with_headers(Headers::from_iter(headers))
|
||||
.with_status(status_code)
|
||||
})
|
||||
}
|
||||
|
26
src/r2.rs
26
src/r2.rs
@ -1,5 +1,5 @@
|
||||
use crate::values::{DavProperties, Range};
|
||||
use worker::{Bucket, ByteStream, FixedLengthStream, Range as R2Range};
|
||||
use worker::{console_debug, Bucket, ByteStream, FixedLengthStream, Headers, Range as R2Range};
|
||||
|
||||
pub struct R2 {
|
||||
bucket: Bucket,
|
||||
@ -11,10 +11,9 @@ impl R2 {
|
||||
}
|
||||
|
||||
pub async fn get(&self, path: String) -> Result<(String, DavProperties), String> {
|
||||
let result = self.bucket.get(path).execute().await;
|
||||
match result {
|
||||
match self.bucket.get(path).execute().await {
|
||||
Ok(f) => f.map_or(Err("Resource not found".to_string()), |file| {
|
||||
Ok((file.key(), DavProperties::from_r2(&file)))
|
||||
Ok((file.key(), DavProperties::from(&file)))
|
||||
}),
|
||||
Err(error) => Err(error.to_string()),
|
||||
}
|
||||
@ -25,7 +24,8 @@ impl R2 {
|
||||
Ok(files) => {
|
||||
let mut result = Vec::new();
|
||||
for file in files.objects() {
|
||||
result.push((file.key(), DavProperties::from_r2(&file)))
|
||||
console_debug!("Access {}", file.key());
|
||||
result.push((file.key(), DavProperties::from(&file)))
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
@ -33,6 +33,18 @@ impl R2 {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn patch_metadata(&self, path: String, metadata: Headers) -> Result<(), String> {
|
||||
match self.bucket.get(path).execute().await {
|
||||
Ok(f) => f.map_or(Err("Resource not found".to_string()), |file| {
|
||||
match file.write_http_metadata(metadata) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(error) => Err(error.to_string()),
|
||||
}
|
||||
}),
|
||||
Err(error) => Err(error.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn download(
|
||||
&self,
|
||||
path: String,
|
||||
@ -66,7 +78,7 @@ impl R2 {
|
||||
.map_or(Err("Failed to get file body stream".to_string()), |b| {
|
||||
b.stream().map_or(
|
||||
Err("Failed to get file body stream".to_string()),
|
||||
|stream| Ok((DavProperties::from_r2(&file), stream)),
|
||||
|stream| Ok((DavProperties::from(&file), stream)),
|
||||
)
|
||||
})
|
||||
}),
|
||||
@ -93,7 +105,7 @@ impl R2 {
|
||||
.execute()
|
||||
.await
|
||||
{
|
||||
Ok(file) => Ok(DavProperties::from_r2(&file)),
|
||||
Ok(file) => Ok(DavProperties::from(&file)),
|
||||
Err(error) => Err(error.to_string()),
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use worker::Object;
|
||||
use worker::{console_debug, Object};
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Hash, Eq)]
|
||||
pub enum Depth {
|
||||
@ -90,9 +90,11 @@ pub struct DavProperties {
|
||||
pub get_last_modified: Option<String>,
|
||||
}
|
||||
|
||||
impl DavProperties {
|
||||
pub fn from_r2(file: &Object) -> DavProperties {
|
||||
impl From<&Object> for DavProperties {
|
||||
fn from(file: &Object) -> DavProperties {
|
||||
console_debug!("Calling from Object for DavProperties");
|
||||
let http_metedata = file.http_metadata();
|
||||
console_debug!("http_metedata {:?}", http_metedata);
|
||||
DavProperties {
|
||||
creation_date: Some(file.uploaded().to_string()),
|
||||
display_name: http_metedata.content_disposition,
|
||||
|
Loading…
Reference in New Issue
Block a user