From f6cbf58f3ee451eea09014d7faecc6834c244d33 Mon Sep 17 00:00:00 2001 From: Xuanwo Date: Mon, 15 Jan 2024 21:39:33 +0800 Subject: [PATCH 1/2] feat(services/ghac): Add workaround for AWS S3 based GHES Signed-off-by: Xuanwo --- core/src/services/ghac/backend.rs | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/core/src/services/ghac/backend.rs b/core/src/services/ghac/backend.rs index 596189eb264..6ce96c9971e 100644 --- a/core/src/services/ghac/backend.rs +++ b/core/src/services/ghac/backend.rs @@ -26,9 +26,9 @@ use http::header::CONTENT_LENGTH; use http::header::CONTENT_RANGE; use http::header::CONTENT_TYPE; use http::header::USER_AGENT; -use http::Request; use http::Response; use http::StatusCode; +use http::{header, Request}; use log::debug; use serde::Deserialize; use serde::Serialize; @@ -254,6 +254,11 @@ impl Accessor for GhacBackend { am } + /// Some self-hosted GHES instances are backed by AWS S3 services which only returns + /// signed url with `GET` method. So we will use `GET` with empty range to simulate + /// `HEAD` instead. + /// + /// In this way, we can support both self-hosted GHES and `github.com`. async fn stat(&self, path: &str, _: OpStat) -> Result { let req = self.ghac_query(path).await?; @@ -268,14 +273,25 @@ impl Accessor for GhacBackend { return Err(parse_error(resp).await?); }; - let req = self.ghac_head_location(&location).await?; + let req = Request::get(location) + .header(header::RANGE, "0-0") + .body(AsyncBody::Empty) + .map_err(new_request_build_error)?; let resp = self.client.send(req).await?; let status = resp.status(); match status { - StatusCode::OK => { - let meta = parse_into_metadata(path, resp.headers())?; + StatusCode::OK | StatusCode::PARTIAL_CONTENT | StatusCode::RANGE_NOT_SATISFIABLE => { + let mut meta = parse_into_metadata(path, resp.headers())?; + // Correct content length via returning content range. + meta.set_content_length( + meta.content_range() + .expect("content range must be valid") + .size() + .expect("content range must contains size"), + ); + resp.into_body().consume().await?; Ok(RpStat::new(meta)) } _ => Err(parse_error(resp).await?), @@ -402,12 +418,6 @@ impl GhacBackend { req.body(AsyncBody::Empty).map_err(new_request_build_error) } - async fn ghac_head_location(&self, location: &str) -> Result> { - Request::head(location) - .body(AsyncBody::Empty) - .map_err(new_request_build_error) - } - async fn ghac_reserve(&self, path: &str) -> Result> { let p = build_abs_path(&self.root, path); From 8d84cf794d9d0c3f090098f62e3b17f83439f761 Mon Sep 17 00:00:00 2001 From: Xuanwo Date: Mon, 15 Jan 2024 21:42:07 +0800 Subject: [PATCH 2/2] Fix header Signed-off-by: Xuanwo --- core/src/services/ghac/backend.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/services/ghac/backend.rs b/core/src/services/ghac/backend.rs index 6ce96c9971e..61b8b2598ac 100644 --- a/core/src/services/ghac/backend.rs +++ b/core/src/services/ghac/backend.rs @@ -274,7 +274,7 @@ impl Accessor for GhacBackend { }; let req = Request::get(location) - .header(header::RANGE, "0-0") + .header(header::RANGE, "bytes=0-0") .body(AsyncBody::Empty) .map_err(new_request_build_error)?; let resp = self.client.send(req).await?;