Просмотр исходного кода

fix web server URI handling (again)

Extract out into its own function, and add tests.
Justin Tracey 7 месяцев назад
Родитель
Сommit
de05d322e0
1 измененных файлов с 36 добавлено и 18 удалено
  1. 36 18
      src/bin/mgen-client.rs

+ 36 - 18
src/bin/mgen-client.rs

@@ -62,6 +62,18 @@ impl tokio_rustls::rustls::client::ServerCertVerifier for NoCertificateVerificat
     }
 }
 
+/// Create a URL the web server can use to accept or produce traffic.
+/// `target` is the IP or host name of the web server,
+/// `size` is the number of bytes to download or upload,
+/// `user` is to let the server log the user making the request.
+/// Panics if the arguments do not produce a valid URI.
+fn web_url(target: &str, size: usize, user: &str) -> hyper::Uri {
+    let formatted = format!("https://{}/?size={}&user={}", target, size, user);
+    formatted
+        .parse()
+        .unwrap_or_else(|_| panic!("Invalid URI: {}", formatted))
+}
+
 /// The thread responsible for getting incoming messages,
 /// checking for any network errors while doing so,
 /// and giving messages to the state thread.
@@ -141,21 +153,7 @@ async fn reader(
                 };
 
                 if msg.body.has_attachment() {
-                    let url: hyper::Uri = format!(
-                        "https://{}/?size={}&user={}",
-                        target,
-                        msg.body.total_size(),
-                        user
-                    )
-                    .parse()
-                    .unwrap_or_else(|_| {
-                        panic!(
-                            "Invalid URI: {}/?size={}&user={}",
-                            target,
-                            msg.body.total_size(),
-                            user
-                        )
-                    });
+                    let url = web_url(&target, msg.body.total_size(), &user);
                     let client = client.clone();
                     tokio::spawn(async move {
                         let mut res = client.get(url.clone()).await;
@@ -233,9 +231,7 @@ async fn uploader(
         loop {
             let size = size_channel.recv().await.expect("Size channel closed");
             let client = client.clone();
-            let url: hyper::Uri = format!("{}/?size={}&user={}", target, size, user)
-                .parse()
-                .expect("Invalid URI");
+            let url = web_url(&target, size, &user);
             let request = hyper::Request::put(url.clone())
                 .body(hyper::Body::empty())
                 .expect("Invalid HTTP request attempted to construct");
@@ -506,3 +502,25 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
     }
     Ok(())
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_uri_generation() {
+        // should panic if any of these are invalid
+        web_url("192.0.2.1", 0, "Alice");
+        web_url("hostname", 65536, "Bob");
+        web_url("web0", 4294967295, "Carol");
+        web_url("web1", 1, "");
+        web_url("foo.bar.baz", 1, "Dave");
+
+        // IPv6 is not a valid in a URI
+        //web_url("2001:0db8:85a3:0000:0000:8a2e:0370:7334", 1, "1");
+
+        // hyper does not automatically convert to punycode
+        //web_url("web2", 1, "🦀");
+        //web_url("🦀", 1, "Ferris");
+    }
+}