From cd6c4674dc560d9c1dc355cac627edac32138f2c Mon Sep 17 00:00:00 2001 From: Gabriela Moldovan Date: Wed, 16 Aug 2023 15:09:52 +0100 Subject: [PATCH] tor-dirclient: Make Requestable return requests with String bodies. It's simpler to always use a `String` to represent directory request bodies. We no longer need the `StringBody` trait. --- crates/tor-dirclient/semver.md | 2 +- crates/tor-dirclient/src/request.rs | 45 +++++++++-------------------- crates/tor-dirclient/src/util.rs | 29 ++++++------------- crates/tor-dirmgr/src/docid.rs | 2 +- 4 files changed, 25 insertions(+), 53 deletions(-) diff --git a/crates/tor-dirclient/semver.md b/crates/tor-dirclient/semver.md index 3f8224dbf..8b90a06a8 100644 --- a/crates/tor-dirclient/semver.md +++ b/crates/tor-dirclient/semver.md @@ -1,5 +1,5 @@ DEPRECATED: `download()` ADDED: `send_request()` -BREAKING: `Requestable` now has an associated `Body` type ADDED: `StringBody` trait ADDED: `tor-dirclient::request::HsDescUploadRequest`. +BREAKING: `Requestable::make_request` now returns `http::Request` diff --git a/crates/tor-dirclient/src/request.rs b/crates/tor-dirclient/src/request.rs index 615600d11..b82d36ea1 100644 --- a/crates/tor-dirclient/src/request.rs +++ b/crates/tor-dirclient/src/request.rs @@ -52,12 +52,9 @@ impl StringBody for &str { /// A request for an object that can be served over the Tor directory system. pub trait Requestable { - /// The body type of the [`http::Request`]. - type Body: StringBody; - /// Build an [`http::Request`] from this Requestable, if /// it is well-formed. - fn make_request(&self) -> Result>; + fn make_request(&self) -> Result>; /// Return true if partial downloads are potentially useful. This /// is true for request types where we're going to be downloading @@ -219,9 +216,7 @@ impl Default for ConsensusRequest { } impl Requestable for ConsensusRequest { - type Body = (); - - fn make_request(&self) -> Result> { + fn make_request(&self) -> Result> { // Build the URL. let mut uri = "/tor/status-vote/current/consensus".to_string(); match self.flavor { @@ -256,7 +251,7 @@ impl Requestable for ConsensusRequest { req = req.header("X-Or-Diff-From-Consensus", &ids); } - Ok(req.body(())?) + Ok(req.body(String::new())?) } fn partial_docs_ok(&self) -> bool { @@ -304,9 +299,7 @@ impl AuthCertRequest { } impl Requestable for AuthCertRequest { - type Body = (); - - fn make_request(&self) -> Result> { + fn make_request(&self) -> Result> { if self.ids.is_empty() { return Err(RequestError::EmptyRequest); } @@ -329,7 +322,7 @@ impl Requestable for AuthCertRequest { let req = http::Request::builder().method("GET").uri(uri); let req = add_common_headers(req); - Ok(req.body(())?) + Ok(req.body(String::new())?) } fn partial_docs_ok(&self) -> bool { @@ -376,9 +369,7 @@ impl MicrodescRequest { } impl Requestable for MicrodescRequest { - type Body = (); - - fn make_request(&self) -> Result> { + fn make_request(&self) -> Result> { let d_encode_b64 = |d: &[u8; 32]| Base64Unpadded::encode_string(&d[..]); let ids = digest_list_stringify(&self.digests, d_encode_b64, "-") .ok_or(RequestError::EmptyRequest)?; @@ -387,7 +378,7 @@ impl Requestable for MicrodescRequest { let req = add_common_headers(req); - Ok(req.body(())?) + Ok(req.body(String::new())?) } fn partial_docs_ok(&self) -> bool { @@ -453,9 +444,7 @@ impl RouterDescRequest { #[cfg(feature = "routerdesc")] impl Requestable for RouterDescRequest { - type Body = (); - - fn make_request(&self) -> Result> { + fn make_request(&self) -> Result> { let mut uri = "/tor/server/".to_string(); match self.requested_descriptors { @@ -475,7 +464,7 @@ impl Requestable for RouterDescRequest { let req = http::Request::builder().method("GET").uri(uri); let req = add_common_headers(req); - Ok(req.body(())?) + Ok(req.body(String::new())?) } fn partial_docs_ok(&self) -> bool { @@ -521,14 +510,12 @@ impl RoutersOwnDescRequest { #[cfg(feature = "routerdesc")] impl Requestable for RoutersOwnDescRequest { - type Body = (); - - fn make_request(&self) -> Result> { + fn make_request(&self) -> Result> { let uri = "/tor/server/authority.z"; let req = http::Request::builder().method("GET").uri(uri); let req = add_common_headers(req); - Ok(req.body(())?) + Ok(req.body(String::new())?) } fn partial_docs_ok(&self) -> bool { @@ -569,16 +556,14 @@ impl HsDescDownloadRequest { #[cfg(feature = "hs-client")] impl Requestable for HsDescDownloadRequest { - type Body = (); - - fn make_request(&self) -> Result> { + fn make_request(&self) -> Result> { let hsid = Base64Unpadded::encode_string(self.hsid.as_ref()); // We hardcode version 3 here; if we ever have a v4 onion service // descriptor, it will need a different kind of Request. let uri = format!("/tor/hs/3/{}", hsid); let req = http::Request::builder().method("GET").uri(uri); let req = add_common_headers(req); - Ok(req.body(())?) + Ok(req.body(String::new())?) } fn partial_docs_ok(&self) -> bool { @@ -607,9 +592,7 @@ impl HsDescUploadRequest { #[cfg(feature = "hs-service")] impl Requestable for HsDescUploadRequest { - type Body = String; - - fn make_request(&self) -> Result> { + fn make_request(&self) -> Result> { /// The upload URI. const URI: &str = "/tor/hs/3/publish"; diff --git a/crates/tor-dirclient/src/util.rs b/crates/tor-dirclient/src/util.rs index 24b224bf3..9e407b2f4 100644 --- a/crates/tor-dirclient/src/util.rs +++ b/crates/tor-dirclient/src/util.rs @@ -2,10 +2,8 @@ use std::fmt::Write; -use crate::request::StringBody; - /// Encode an HTTP request in a quick and dirty HTTP 1.0 format. -pub(crate) fn encode_request(req: &http::Request) -> String { +pub(crate) fn encode_request(req: &http::Request) -> String { let mut s = format!("{} {} HTTP/1.0\r\n", req.method(), req.uri()); for (key, val) in req.headers().iter() { @@ -19,7 +17,7 @@ pub(crate) fn encode_request(req: &http::Request) -> String { .unwrap(); } s.push_str("\r\n"); - s.push_str(req.body().as_str()); + s.push_str(req.body()); s } @@ -38,16 +36,7 @@ mod test { //! use super::*; - #[derive(Copy, Clone, Debug)] - struct TestBody; - - impl StringBody for TestBody { - fn as_str(&self) -> &str { - "hello" - } - } - - fn build_request(body: B, headers: &[(&str, &str)]) -> http::Request { + fn build_request(body: String, headers: &[(&str, &str)]) -> http::Request { let mut builder = http::Request::builder().method("GET").uri("/index.html"); for (name, value) in headers { @@ -59,21 +48,21 @@ mod test { #[test] fn format() { - fn chk_format(body: B, expected_body: &str) { + fn chk_format(body: String) { let req = build_request(body.clone(), &[]); assert_eq!( encode_request(&req), - format!("GET /index.html HTTP/1.0\r\n\r\n{expected_body}") + format!("GET /index.html HTTP/1.0\r\n\r\n{body}") ); - let req = build_request(body, &[("X-Marsupial", "Opossum")]); + let req = build_request(body.clone(), &[("X-Marsupial", "Opossum")]); assert_eq!( encode_request(&req), - format!("GET /index.html HTTP/1.0\r\nx-marsupial: Opossum\r\n\r\n{expected_body}") + format!("GET /index.html HTTP/1.0\r\nx-marsupial: Opossum\r\n\r\n{body}") ); } - chk_format((), ""); - chk_format(TestBody, "hello"); + chk_format(Default::default()); + chk_format("hello".into()); } } diff --git a/crates/tor-dirmgr/src/docid.rs b/crates/tor-dirmgr/src/docid.rs index 78f5622d3..9486a6a64 100644 --- a/crates/tor-dirmgr/src/docid.rs +++ b/crates/tor-dirmgr/src/docid.rs @@ -84,7 +84,7 @@ pub(crate) enum ClientRequest { impl ClientRequest { /// Turn a ClientRequest into a Requestable. - pub(crate) fn as_requestable(&self) -> &(dyn request::Requestable + Send + Sync) { + pub(crate) fn as_requestable(&self) -> &(dyn request::Requestable + Send + Sync) { use ClientRequest::*; match self { Consensus(a) => a,