Repository: algesten/ureq (rust)

Issue:
404 when downloading a GitHub release
In a project of mine I wrap a pre-built C library in a `-sys` crate (https://github.com/nbigaouette/onnxruntime-rs).

For better ergonomics I download the pre-built library in my build.rs using ureq (still on 1.4.0). This allows running tests against the library+wrapper in my CI (GitHub Actions). See: https://github.com/nbigaouette/onnxruntime-rs/blob/issue22/onnxruntime-sys/build.rs#L80-L87

The archive I want to download is `onnxruntime-linux-x64-1.4.0.tgz` from this release:
https://github.com/microsoft/onnxruntime/releases/tag/v1.4.0

The download used to work, but now it doesn't anymore. I specifically added this download so my GitHub Actions could have access to the library. Here's an example PR where the download passed: https://github.com/nbigaouette/onnxruntime-rs/pull/21

Here's an example of failure: https://github.com/nbigaouette/onnxruntime-rs/runs/1191121056?check_suite_focus=true (part of PR https://github.com/nbigaouette/onnxruntime-rs/pull/23 )

My build script prints the URL (https://github.com/nbigaouette/onnxruntime-rs/blob/issue22/onnxruntime-sys/build.rs#L210-L214) so I copy-pasted and used `curl -LO https://...` and it worked. GitHub releases uses a redirect to point to the real AWS S3 url to download. Maybe something changed in GitHub that broke how `ureq` is handling the redirects?

Pull request description:
Use correct host on redirect.
As of 1.5.0, redirects to a different host are broken. This broke as part of #153,
which set the hostname from `req` instead of from `unit.url`.

Fixes #179.

Patch:
diff --git a/src/unit.rs b/src/unit.rs
index bb080f0..3ec4794 100644
--- a/src/unit.rs
+++ b/src/unit.rs
@@ -145,7 +145,10 @@ pub(crate) fn connect(
 ) -> Result<Response, Error> {
     //
 
-    let host = req.get_host()?;
+    let host = unit
+        .url
+        .host_str()
+        .ok_or(Error::BadUrl("no host".to_string()))?;
     let url = &unit.url;
     let method = &unit.req.method;
     // open socket
@@ -361,6 +364,7 @@ fn send_prelude(unit: &Unit, stream: &mut Stream, redir: bool) -> io::Result<()>
     // finish
     write!(prelude, "\r\n")?;
 
+    debug!("writing prelude: {}", String::from_utf8_lossy(&prelude));
     // write all to the wire
     stream.write_all(&prelude[..])?;
 


Test patch:
diff --git a/src/test/redirect.rs b/src/test/redirect.rs
index 03639e2..5ec1a41 100644
--- a/src/test/redirect.rs
+++ b/src/test/redirect.rs
@@ -1,3 +1,9 @@
+use std::{
+    io::{self, Write},
+    net::TcpStream,
+};
+use test::testserver::{self, TestServer};
+
 use crate::test;
 
 use super::super::*;
@@ -76,6 +82,25 @@ fn redirect_get() {
     assert_eq!(resp.header("x-foo").unwrap(), "bar");
 }
 
+#[test]
+fn redirect_host() {
+    // Set up a redirect to a host that doesn't exist; it should fail.
+    let srv = TestServer::new(|mut stream: TcpStream| -> io::Result<()> {
+        testserver::read_headers(&stream);
+        write!(stream, "HTTP/1.1 302 Found\r\n")?;
+        write!(stream, "Location: http://example.invalid/\r\n")?;
+        write!(stream, "\r\n")?;
+        Ok(())
+    });
+    let url = format!("http://localhost:{}/", srv.port);
+    let resp = crate::get(&url).call();
+    assert!(
+        matches!(resp.synthetic_error(), Some(Error::DnsFailed(_))),
+        "{:?}",
+        resp.synthetic_error()
+    );
+}
+
 #[test]
 fn redirect_post() {
     test::set_handler("/redirect_post1", |_| {