fix(runtime): set Response.url and Response.redirected correctly after fetch redirects#5320
fix(runtime): set Response.url and Response.redirected correctly after fetch redirects#5320Cypher-CP0 wants to merge 1 commit intoboa-dev:mainfrom
Conversation
| // The spec says: return true if this's response's URL list's size is greater than 1. | ||
| // TODO: track the full URL list to implement this properly. | ||
| false | ||
| self.redirected |
There was a problem hiding this comment.
how does your change align with the TODO comment and spec?
There was a problem hiding this comment.
TODO was about tracking every hop in the redirect chain, but Response.redirected only needs to know if there was any redirect, not the full list. Since reqwest already follows redirects and exposes the final URL, comparing that to the original request URL gives us exactly what we need. Full URL list tracking could still be a follow-up if needed for other spec requirements.
There was a problem hiding this comment.
Response.redirected only needs to know if there was any redirect, not the full list
But according to the comment here, spec requires the check to be done via url list, and not a "quick" check like this?
E.g. what if A redirects to B and B redirects back to A? Does your check consider scenario like this?
There was a problem hiding this comment.
Thanks for catching that!
You're right, A→B→A would break my check. What approach would you recommend, manual redirect handling to build the full URL list, or something simpler?
There was a problem hiding this comment.
Currently the response only has url, but according to spec and the TODO comment, url list is also required: https://fetch.spec.whatwg.org/#concept-response-url-list . So i guess you should implement that and follow the spec for where to modify it in what way.
But fetch api is in general not complete in boa, so idk how much work that actually might be
There was a problem hiding this comment.
I am guessing once you have the list, then A -> B -> A would be handled correctly because of the url list containing multiple urls even though the resulting url might be the same as the original.
There was a problem hiding this comment.
Yup, we need to keep a list of urls as described in the specification, since we are using reqwest we can create a client that has custom redirect policy, that will collect the url attempts.
// part of fetcher initialization:
let url_list = Arc::new(Mutex::new(Vec::new()));
let url_list_clone = Arc::clone(&history);
let custom_policy = redirect::Policy::custom(move |attempt| {
url_list_clone.lock().expect("should not be poisoned").push(attempt.url().clone());
reqwest::redirect::Policy::default().redirect(attempt)
});
let client = Client::builder()
.redirect(custom_policy)
.build()?;
// making the request
let result = self.client.execute(req);
// clears and takes the list for the previous request.
let url_list = std::mem::take(&mut *self.url_list.lock().expect("should not be poisoned"));
let response = result.map_err(JsError::from_rust)?;
This Pull Request fixes/closes #5310.
It changes the following:
redirected: boolfield toJsResponsestruct inresponse.rsJsResponse::basic()to accept aredirectedparameter and store itResponse.redirectedgetter to return the stored value instead of always returningfalsefetchers.rsto capture the final URL from reqwest before consumingthe response body, and derive
redirectedby comparing it to the original request URLResponse.urlto return the final URL after redirects instead of the original request URLresponse_redirected_flagtest ine2e.rscovering both the redirected and non-redirected cases