Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 17 additions & 6 deletions src/http/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,26 @@ async fn execute_inner(cli: &Cli) -> Result<i32, FetchError> {
} else {
None
};
let mut grpc_method = if let Some(schema) = &grpc_schema {
let grpc_method = if let Some(schema) = &grpc_schema {
Some(proto::method_for_url(schema, &url)?)
} else {
None
};
let session = load_session(cli)?;
let result = execute_request(cli, http_version, url, grpc_method, session.as_ref()).await;
if !cli.dry_run {
save_session(cli, session.as_ref());
}
result
}

async fn execute_request(
cli: &Cli,
http_version: Option<HttpVersion>,
url: Url,
mut grpc_method: Option<prost_reflect::MethodDescriptor>,
session: Option<&crate::session::Session>,
) -> Result<i32, FetchError> {
let request_start = Instant::now();
let request_timeout = cli
.timeout
Expand All @@ -138,7 +151,7 @@ async fn execute_inner(cli: &Cli) -> Result<i32, FetchError> {
request_timeout,
connect_timeout,
request_start,
session: session.as_ref(),
session,
connect_timing: Some(&connect_timing),
};
let mut initial_client = None;
Expand Down Expand Up @@ -228,7 +241,7 @@ async fn execute_inner(cli: &Cli) -> Result<i32, FetchError> {
let total_attempts = total_attempts_for_retry(retry_count)?;
let original_body_replayable = request_body_replayable(&body);
let mut attempt = 0;
let result = loop {
loop {
let mut request_method = method.clone();
let mut request_url = url.clone();
let mut request_body = body.clone();
Expand Down Expand Up @@ -452,9 +465,7 @@ async fn execute_inner(cli: &Cli) -> Result<i32, FetchError> {
break Err(FetchError::Runtime(message));
}
}
};
save_session(cli, session.as_ref());
result
}
}

fn record_request_dns_timing(
Expand Down
71 changes: 71 additions & 0 deletions tests/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,77 @@ fn redirects_range_status_and_timeouts() {
assert_exit(&res, 0);
}

#[test]
fn session_cookies_persist_after_invalid_redirect() {
let server = TestServer::start(|req| match req.path.as_str() {
"/start" => TestResponse::status(302, "Found", "")
.header("Set-Cookie", "sid=redirect; Path=/")
.header("Location", "http://[::1"),
"/check" if req.header("cookie").contains("sid=redirect") => TestResponse::ok("saved"),
"/check" => TestResponse::status(400, "Bad Request", "cookie missing"),
_ => TestResponse::status(404, "Not Found", ""),
});
let dir = TempDir::new().unwrap();
let sessions_dir = dir.path().join("sessions");
let env = vec![(
"FETCH_INTERNAL_SESSIONS_DIR".to_string(),
sessions_dir.display().to_string(),
)];

let res = run_fetch_opts(
FetchOpts {
env: env.clone(),
..Default::default()
},
&[
&format!("{}/start", server.url),
"--session",
"redirect-error",
],
);
assert_exit(&res, 1);
assert!(res.stderr.contains("invalid redirect location"));

let res = run_fetch_opts(
FetchOpts {
env,
..Default::default()
},
&[
&format!("{}/check", server.url),
"--session",
"redirect-error",
],
);
assert_exit(&res, 0);
assert_eq!(res.stdout, "saved");
}

#[test]
fn dry_run_leaves_corrupted_session_unchanged() {
let dir = TempDir::new().unwrap();
let sessions_dir = dir.path().join("sessions");
fs::create_dir_all(&sessions_dir).unwrap();
let session_path = sessions_dir.join("dry-run.json");
let original = b"not valid session json\n";
fs::write(&session_path, original).unwrap();

let res = run_fetch_opts(
FetchOpts {
env: vec![(
"FETCH_INTERNAL_SESSIONS_DIR".to_string(),
sessions_dir.display().to_string(),
)],
..Default::default()
},
&["https://example.com", "--dry-run", "--session", "dry-run"],
);

assert_exit(&res, 0);
assert!(res.stderr.contains("session 'dry-run' is corrupted"));
assert_eq!(fs::read(session_path).unwrap(), original);
}

#[test]
fn post_to_get_redirect_strips_entity_headers() {
let server = TestServer::start(|req| match req.path.as_str() {
Expand Down
Loading