Skip to content

Commit 7ae6c30

Browse files
committed
Refactor redirect handling to improve URI resolution and error reporting
1 parent d8d7a08 commit 7ae6c30

File tree

2 files changed

+22
-22
lines changed

2 files changed

+22
-22
lines changed

src/acme.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,13 @@ fn try_get_header<K: http::header::AsHeaderName>(
111111
headers.get(key).and_then(|x| x.to_str().ok())
112112
}
113113

114+
fn resolve_uri(base: &Uri, relative: &str) -> Option<Uri> {
115+
let base_abs = UriAbsoluteString::try_from(base.to_string()).ok()?;
116+
let location_ref = UriReferenceStr::new(relative).ok()?;
117+
let resolved = location_ref.resolve_against(&base_abs).to_string();
118+
Uri::try_from(resolved).ok()
119+
}
120+
114121
impl<'a, Http> AcmeClient<'a, Http>
115122
where
116123
Http: HttpClient,
@@ -186,15 +193,14 @@ where
186193

187194
if res.status().is_redirection() {
188195
if let Some(location) = try_get_header(res.headers(), http::header::LOCATION) {
189-
let base = UriAbsoluteString::try_from(u.to_string())
190-
.map_err(RedirectError::InvalidBase)?;
191-
let location_ref =
192-
UriReferenceStr::new(location).map_err(RedirectError::InvalidLocation)?;
193-
let resolved = location_ref.resolve_against(&base).to_string();
194-
u = Uri::try_from(resolved).map_err(RedirectError::InvalidUri)?;
195-
continue;
196+
if let Some(new_u) = resolve_uri(&u, location) {
197+
u = new_u;
198+
continue;
199+
} else {
200+
return Err(RedirectError::InvalidRedirectUri.into());
201+
}
196202
} else {
197-
return Err(RedirectError::MissingLocation.into());
203+
return Err(RedirectError::MissingRedirectUri.into());
198204
}
199205
}
200206

src/acme/error.rs

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -116,20 +116,14 @@ impl NewCertificateError {
116116

117117
#[derive(Debug, Error)]
118118
pub enum RedirectError {
119-
#[error("missing Location header")]
120-
MissingLocation,
119+
#[error("invalid redirect URI")]
120+
InvalidRedirectUri,
121+
122+
#[error("missing redirect URI")]
123+
MissingRedirectUri,
121124

122125
#[error("too many redirects")]
123126
TooManyRedirects,
124-
125-
#[error("invalid base URI (IRI creation)")]
126-
InvalidBase(#[source] iri_string::types::CreationError<std::string::String>),
127-
128-
#[error("invalid redirect location (IRI validation)")]
129-
InvalidLocation(#[source] iri_string::validate::Error),
130-
131-
#[error("invalid resolved redirect URI")]
132-
InvalidUri(#[source] http::uri::InvalidUri),
133127
}
134128

135129
#[derive(Debug, Error)]
@@ -155,6 +149,9 @@ pub enum RequestError {
155149
#[error("rate limit exceeded, next attempt in {0:?}")]
156150
RateLimited(Duration),
157151

152+
#[error("redirect failed: {0}")]
153+
Redirect(#[from] RedirectError),
154+
158155
#[error("cannot serialize request ({0})")]
159156
RequestFormat(serde_json::Error),
160157

@@ -163,9 +160,6 @@ pub enum RequestError {
163160

164161
#[error("cannot sign request body ({0})")]
165162
Sign(#[from] crate::jws::Error),
166-
167-
#[error("redirect failed: {0}")]
168-
Redirect(#[from] RedirectError),
169163
}
170164

171165
impl From<HttpClientError> for RequestError {

0 commit comments

Comments
 (0)