Make minor codes modification for method computing and add unit tests.

This commit is contained in:
jcamiel 2023-07-10 17:18:17 +02:00
parent cef2e80c1a
commit 45bb522794
No known key found for this signature in database
GPG Key ID: 07FF11CFD55356CC
11 changed files with 107 additions and 42 deletions

View File

@ -1,2 +1,3 @@
curl --location 'http://localhost:8000/follow-redirect'
curl --location --request POST 'http://localhost:8000/follow-redirect-308'
curl --request POST --location 'http://localhost:8000/follow-redirect'
curl --request POST --location 'http://localhost:8000/follow-redirect-308'

View File

@ -2,6 +2,12 @@
</span><span class="response"><span class="line"><span class="version">HTTP</span> <span class="number">200</span></span>
<span class="line"><span class="string">`Followed redirect!`</span></span>
</span></span><span class="hurl-entry"><span class="request"><span class="line"></span>
<span class="line"></span><span class="comment"># On 301, 302, 303, redirected request switch to GET.</span>
<span class="line"></span><span class="comment"># Otherwise, method are untouched.</span>
<span class="line"><span class="method">POST</span> <span class="url">http://localhost:8000/follow-redirect</span></span>
</span><span class="response"><span class="line"><span class="version">HTTP</span> <span class="number">200</span></span>
<span class="line"><span class="string">`Followed redirect!`</span></span>
</span></span><span class="hurl-entry"><span class="request"><span class="line"></span>
<span class="line"><span class="method">POST</span> <span class="url">http://localhost:8000/follow-redirect-308</span></span>
</span><span class="response"><span class="line"><span class="version">HTTP</span> <span class="number">200</span></span>
<span class="line"><span class="string">`Followed redirect POST!`</span></span>

View File

@ -2,6 +2,12 @@ GET http://localhost:8000/follow-redirect
HTTP 200
`Followed redirect!`
# On 301, 302, 303, redirected request switch to GET.
# Otherwise, method are untouched.
POST http://localhost:8000/follow-redirect
HTTP 200
`Followed redirect!`
POST http://localhost:8000/follow-redirect-308
HTTP 200
`Followed redirect POST!`

View File

@ -1 +1 @@
{"entries":[{"request":{"method":"GET","url":"http://localhost:8000/follow-redirect"},"response":{"status":200,"body":{"type":"text","value":"Followed redirect!"}}},{"request":{"method":"POST","url":"http://localhost:8000/follow-redirect-308"},"response":{"status":200,"body":{"type":"text","value":"Followed redirect POST!"}}}]}
{"entries":[{"request":{"method":"GET","url":"http://localhost:8000/follow-redirect"},"response":{"status":200,"body":{"type":"text","value":"Followed redirect!"}}},{"request":{"method":"POST","url":"http://localhost:8000/follow-redirect"},"response":{"status":200,"body":{"type":"text","value":"Followed redirect!"}}},{"request":{"method":"POST","url":"http://localhost:8000/follow-redirect-308"},"response":{"status":200,"body":{"type":"text","value":"Followed redirect POST!"}}}]}

View File

@ -2,7 +2,7 @@ from app import app
from flask import redirect, Response
@app.route("/follow-redirect")
@app.route("/follow-redirect", methods=["GET", "POST"])
def follow_redirect():
return redirect("http://localhost:8000/following-redirect")

View File

@ -1,3 +1,5 @@
curl 'http://localhost:8000/follow-redirect'
curl 'http://localhost:8000/follow-redirect'
curl --location 'http://localhost:8000/follow-redirect'
curl --request POST --location 'http://localhost:8000/follow-redirect'
curl --request POST --location 'http://localhost:8000/follow-redirect-308'

View File

@ -23,5 +23,26 @@
<span class="line"><span class="section-header">[Asserts]</span></span>
<span class="line"><span class="query-type">header</span> <span class="string">"Location"</span> <span class="not">not</span> <span class="predicate-type">exists</span></span>
<span class="line"><span class="string">`Followed redirect!`</span></span>
</span></span><span class="line"></span>
</code></pre>
</span></span><span class="hurl-entry"><span class="request"><span class="line"></span>
<span class="line"></span>
<span class="line"></span><span class="comment"># On 301, 302, 303, redirected request switch to GET.</span>
<span class="line"></span><span class="comment"># Otherwise, method are untouched.</span>
<span class="line"><span class="method">POST</span> <span class="url">http://localhost:8000/follow-redirect</span></span>
<span class="line"><span class="section-header">[Options]</span></span>
<span class="line"><span class="string">location</span>: <span class="boolean">true</span></span>
</span><span class="response"><span class="line"></span>
<span class="line"><span class="version">HTTP</span> <span class="number">200</span></span>
<span class="line"><span class="section-header">[Asserts]</span></span>
<span class="line"><span class="query-type">header</span> <span class="string">"Location"</span> <span class="not">not</span> <span class="predicate-type">exists</span></span>
<span class="line"><span class="string">`Followed redirect!`</span></span>
</span></span><span class="hurl-entry"><span class="request"><span class="line"></span>
<span class="line"></span>
<span class="line"><span class="method">POST</span> <span class="url">http://localhost:8000/follow-redirect-308</span></span>
<span class="line"><span class="section-header">[Options]</span></span>
<span class="line"><span class="string">location</span>: <span class="boolean">true</span></span>
</span><span class="response"><span class="line"></span>
<span class="line"><span class="version">HTTP</span> <span class="number">200</span></span>
<span class="line"><span class="section-header">[Asserts]</span></span>
<span class="line"><span class="query-type">header</span> <span class="string">"Location"</span> <span class="not">not</span> <span class="predicate-type">exists</span></span>
<span class="line"><span class="string">`Followed redirect POST!`</span></span>
</span></span></code></pre>

View File

@ -24,3 +24,24 @@ HTTP 200
header "Location" not exists
`Followed redirect!`
# On 301, 302, 303, redirected request switch to GET.
# Otherwise, method are untouched.
POST http://localhost:8000/follow-redirect
[Options]
location: true
HTTP 200
[Asserts]
header "Location" not exists
`Followed redirect!`
POST http://localhost:8000/follow-redirect-308
[Options]
location: true
HTTP 200
[Asserts]
header "Location" not exists
`Followed redirect POST!`

View File

@ -1 +1 @@
{"entries":[{"request":{"method":"GET","url":"http://localhost:8000/follow-redirect"},"response":{"status":302,"asserts":[{"query":{"type":"header","name":"Location"},"predicate":{"type":"equal","value":"http://localhost:8000/following-redirect"}}]}},{"request":{"method":"GET","url":"http://localhost:8000/follow-redirect","options":[{"name":"location","value":false}]},"response":{"status":302,"asserts":[{"query":{"type":"header","name":"Location"},"predicate":{"type":"equal","value":"http://localhost:8000/following-redirect"}}]}},{"request":{"method":"GET","url":"http://localhost:8000/follow-redirect","options":[{"name":"location","value":true}]},"response":{"status":200,"asserts":[{"query":{"type":"header","name":"Location"},"predicate":{"not":true,"type":"exist"}}],"body":{"type":"text","value":"Followed redirect!"}}}]}
{"entries":[{"request":{"method":"GET","url":"http://localhost:8000/follow-redirect"},"response":{"status":302,"asserts":[{"query":{"type":"header","name":"Location"},"predicate":{"type":"equal","value":"http://localhost:8000/following-redirect"}}]}},{"request":{"method":"GET","url":"http://localhost:8000/follow-redirect","options":[{"name":"location","value":false}]},"response":{"status":302,"asserts":[{"query":{"type":"header","name":"Location"},"predicate":{"type":"equal","value":"http://localhost:8000/following-redirect"}}]}},{"request":{"method":"GET","url":"http://localhost:8000/follow-redirect","options":[{"name":"location","value":true}]},"response":{"status":200,"asserts":[{"query":{"type":"header","name":"Location"},"predicate":{"not":true,"type":"exist"}}],"body":{"type":"text","value":"Followed redirect!"}}},{"request":{"method":"POST","url":"http://localhost:8000/follow-redirect","options":[{"name":"location","value":true}]},"response":{"status":200,"asserts":[{"query":{"type":"header","name":"Location"},"predicate":{"not":true,"type":"exist"}}],"body":{"type":"text","value":"Followed redirect!"}}},{"request":{"method":"POST","url":"http://localhost:8000/follow-redirect-308","options":[{"name":"location","value":true}]},"response":{"status":200,"asserts":[{"query":{"type":"header","name":"Location"},"predicate":{"not":true,"type":"exist"}}],"body":{"type":"text","value":"Followed redirect POST!"}}}]}

View File

@ -1 +1 @@
Followed redirect!
Followed redirect POST!

View File

@ -86,7 +86,7 @@ impl Client {
let call = self.execute(&request_spec, options, logger)?;
let base_url = call.request.base_url()?;
let redirect_url = self.get_follow_location(&call.response, &base_url);
let call_response_status = call.response.status;
let status = call.response.status;
calls.push(call);
if !options.follow_location || redirect_url.is_none() {
break;
@ -94,21 +94,16 @@ impl Client {
let redirect_url = redirect_url.unwrap();
logger.debug("");
logger.debug(format!("=> Redirect to {redirect_url}").as_str());
logger.debug("");
redirect_count += 1;
if let Some(max_redirect) = options.max_redirect {
if redirect_count > max_redirect {
return Err(HttpError::TooManyRedirect);
}
}
let new_request_method = self.get_redirected_request_method(
options,
logger,
call_response_status,
request_spec.method,
);
logger.debug("");
let redirect_method = get_redirect_method(status, request_spec.method);
request_spec = RequestSpec {
method: new_request_method,
method: redirect_method,
url: redirect_url,
..Default::default()
};
@ -116,32 +111,6 @@ impl Client {
Ok(calls)
}
pub fn get_redirected_request_method(
&self,
options: &ClientOptions,
logger: &Logger,
response_status: u32,
original_method: Method,
) -> Method {
// this replicates curls behavior
return match response_status {
301 | 302 | 303 => {
// spaces at the start to align with the arrow used in a previous
// debug line
logger.debug(
format!(
" Resending with method GET because response code was {response_status}"
)
.as_str(),
);
Method("GET".to_string())
}
// Could be only 307 and 308, but curl does this for all 3xx
// codes not converted to GET above.
_ => original_method,
};
}
/// Executes an HTTP request `request_spec`, without following redirection and returns a
/// pair of [`Request`], [`Response`].
pub fn execute(
@ -685,6 +654,17 @@ fn get_redirect_url(location: &str, base_url: &str) -> String {
}
}
/// Returns the method used for redirecting a request/response with `response_status`.
fn get_redirect_method(response_status: u32, original_method: Method) -> Method {
// This replicates curl's behavior
match response_status {
301 | 302 | 303 => Method("GET".to_string()),
// Could be only 307 and 308, but curl does this for all 3xx
// codes not converted to GET above.
_ => original_method,
}
}
/// Returns cookies from both cookies from the cookie storage and the request.
pub fn all_cookies(cookie_storage: &[Cookie], request_spec: &RequestSpec) -> Vec<RequestCookie> {
let mut cookies = request_spec.cookies.clone();
@ -844,4 +824,32 @@ mod tests {
"http://localhost:8000/redirected".to_string()
);
}
#[test]
fn test_redirect_method() {
// Status of the response to be redirected | method of the original request | method of the new request
let datas = [
(301, "GET", "GET"),
(301, "POST", "GET"),
(301, "DELETE", "GET"),
(302, "GET", "GET"),
(302, "POST", "GET"),
(302, "DELETE", "GET"),
(303, "GET", "GET"),
(303, "POST", "GET"),
(303, "DELETE", "GET"),
(304, "GET", "GET"),
(304, "POST", "POST"),
(304, "DELETE", "DELETE"),
(308, "GET", "GET"),
(308, "POST", "POST"),
(308, "DELETE", "DELETE"),
];
for (status, original, redirected) in datas {
assert_eq!(
get_redirect_method(status, Method(original.to_string())),
Method(redirected.to_string())
);
}
}
}