Redirects no longer have url fragments
There's a regression introduced in d9cf60e8f69bcabf9df3d69a8c0216409e7835a1 (last good commit 75f62f2) that makes redirected URLs no longer keep the URL fragments.
For example:
Before this location with a URL fragment was preserved https://example.com/subsite#var=something
And after this commit, the URL is: https://example.com/subsite (doesn't have the URL fragment).
The client is built in the following way:
let client = ClientBuilder::new()
.use_rustls_tls()
.cookie_store(true)
.redirect(redirect::Policy::custom(|attempt| {
println!("Redirecting to: {}", attempt.url());
attempt.follow()
}))
.build()
.unwrap();
Here's a minimal reproducible example:
// [dependencies]
// axum = "0.8"
// tokio = { version = "1", features = ["full"] }
use axum::{Router, response::Redirect, routing::get};
#[tokio::main]
async fn main() {
let app = Router::new()
.route(
"/",
get(|| async { Redirect::permanent("/redirect#frag=sdafsa") }),
)
.route("/redirect", get(final_page));
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
.await
.unwrap();
println!("Listening on http://127.0.0.1:3000");
axum::serve(listener, app).await.unwrap();
}
async fn final_page() -> &'static str {
"Final destination reached!"
}
EDIT: Removed a user agent because it doesn't matter.
After that refactor PR, reqwest uses tower-http to handle the redirect loop, so the redirection url is retrievaled from the tower-http uri. The cause is that tower-http uri doesn't keep the fragement.
See this https://github.com/hyperium/http/issues/127, if http::uri could support parse fragment, then this issuse will be fixed automatically. Otherwise, we need to trace LOCATION as URL in tower-http also.
Hm, were you inspecting the fragment in a custom policy? Or checking the Response::url() at the end?
I put together a small test at the good commit, and while the response url does have the fragment, the fragment is never transmitted to the server in any of the HTTP requests.
Hm, were you inspecting the fragment in a custom policy? Or checking the
Response::url()at the end?I put together a small test at the good commit, and while the response url does have the fragment, the fragment is never transmitted to the server in any of the HTTP requests.
I was just checking the URL at the end and the println output (in the custom policy). The server is just an example and I use reqwest with a site over which I have no control. I just created it to provide a better example.
It seems that neither axum nor actix are capable of that.
It looks like HTTP protocol doesn't even allow sending URL fragment (the server will generally just leave it out).
I suppose that everything works as intended and my code was just based on a bug. The final request URL shouldn't contain the fragment, since it doesn't make a request to it (as browsers also don't send such requests) and the attempt in a redirect policy also doesn't have the fragment, since it won't be the URL the next request will be made to.
Then I just have a question left. Would you consider adding a per-request redirect policy? So the first (let's say GET) request and each subsequent (until the last one which doesn't redirect) requests would have a specified redirect policy. This would allow a user to disable redirects just for this one request, while retaining the redirect policy for others.
Example:
client.get(url).redirect(redirect::Policy::none()).send()?;