Skip to content

follow_redirect: expose previous and next request methods#559

Merged
jlizen merged 3 commits into
tower-rs:mainfrom
lucab:ups/redirect-methods
May 6, 2026
Merged

follow_redirect: expose previous and next request methods#559
jlizen merged 3 commits into
tower-rs:mainfrom
lucab:ups/redirect-methods

Conversation

@lucab

@lucab lucab commented Apr 17, 2025

Copy link
Copy Markdown
Contributor

This augments follow-redirect Attempt in order to expose two relevant HTTP methods during redirects:

  • the method for the original/previous request
  • the method to be performed on the next request upon following a redirection

This allows consumers to write policies based on both previous and next requests methods.

@lucab

lucab commented Apr 17, 2025

Copy link
Copy Markdown
Contributor Author

@lucab lucab marked this pull request as ready for review April 17, 2025 14:27

@jlizen jlizen left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the slow review @lucab . Looks good! The lifetimes on the methods need fixing, and the rest are nits.

Might be nice to have a module example like, detecting cycles:

if attempt.previous_method() != attempt.method() { }

}

/// Returns the method for the next request, after applying redirection logic.
pub fn next_method(&self) -> &Method {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should return 'a lifetime

}

/// Returns the method for the previous request, before redirection.
pub fn previous_method(&self) -> &Method {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should return 'a lifetime

}

/// Returns the method for the next request, after applying redirection logic.
pub fn next_method(&self) -> &Method {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should probably be method to match location

@@ -33,7 +33,7 @@ impl<B, E> Policy<B, E> for SameOrigin {
#[cfg(test)]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be nice to throw in some simple assertions using these new accessors, if they fit into any existing tests

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a stops_post_redirect_get test to cover this.

@lucab

lucab commented May 5, 2026

Copy link
Copy Markdown
Contributor Author

@jlizen thanks for the review! I'll try to find some time in the next days to rebase and address your feedback, I'll ping you when this is ready for another pass.

Just one question on:

Might be nice to have a module example like, detecting cycles

There is already a cyclic-redirection example at https://docs.rs/tower-http/latest/tower_http/follow_redirect/policy/trait.Policy.html#example, maybe it would be better to tweak that to use a HashSet<(Uri, Method)>?

@jlizen

jlizen commented May 5, 2026

Copy link
Copy Markdown
Member

I'll try to find some time in the next days to rebase and address your feedback

Sounds good! No rush.

cycle detection example

Yeah that sounds like a nice improvement, as long as we can capture cycles where it is flipping methods (which sounds like your HashSet idea would). Totally optional though. Just was thinking about an example that would realistically surface this new api's usage.

@lucab lucab force-pushed the ups/redirect-methods branch 3 times, most recently from e2189ad to 754d2a3 Compare May 5, 2026 16:39
@lucab

lucab commented May 5, 2026

Copy link
Copy Markdown
Contributor Author

@jlizen updated, PTAL.

@jlizen jlizen left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! Couple more nits, then another one that's up to you.

self.status
}

/// Returns the method for the next request, after applying redirection logic.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Returns the method for the next request, after applying redirection logic.
/// Returns the destination method of the redirection.

Comment thread tower-http/src/follow_redirect/mod.rs Outdated
let mut res = ready!(this.future.as_mut().poll(cx)?);
res.extensions_mut().insert(RequestUri(this.uri.clone()));

let previous_method = &this.method.clone();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let previous_method = &this.method.clone();
let previous_method = this.method.clone();

Comment thread tower-http/src/follow_redirect/mod.rs Outdated
status: res.status(),
method: this.method,
location: &location,
previous_method,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
previous_method,
previous_method: &previous_method

Comment thread tower-http/src/follow_redirect/mod.rs Outdated
}

#[tokio::test]
async fn stops_post_redirect_get() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional: This is a good opportunity to flesh out our test coverage a bit, since we have new accessors. Up to you if you care to!

We could test:

  • 307/308 POST preservation
  • 303 POST -> GET
  • 303 HEAD preservation

Probably is worth parameterizing a helper at that point.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. I added a shared redirection handler and then dedicated tests to cover the following matrix:

  • 301
    • POST -> GET
    • GET -> GET
  • 302
    • POST -> GET
    • PUT -> PUT
    • HEAD -> HEAD
  • 303
    • POST -> GET
    • PUT -> GET
    • HEAD -> HEAD
  • 307/308
    • POST -> POST

lucab added 3 commits May 6, 2026 09:56
This augments follow-redirect `Attempt` in order to expose two relevant HTTP methods
during redirects:
 - the method for the original/previous request
 - the method to be performed on the next request upon following a redirection

This allows consumers to write policies based on both previous and next
requests methods.
@lucab lucab force-pushed the ups/redirect-methods branch from 754d2a3 to 68fe5f0 Compare May 6, 2026 09:45
@lucab lucab requested a review from jlizen May 6, 2026 13:21

@jlizen jlizen left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thanks for the contribution!

@jlizen jlizen merged commit 8508cb2 into tower-rs:main May 6, 2026
12 checks passed
@lucab lucab deleted the ups/redirect-methods branch May 8, 2026 13:48
eleboucher pushed a commit to eleboucher/towonel that referenced this pull request May 9, 2026
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [tower-http](https://github.com/tower-rs/tower-http) | workspace.dependencies | patch | `0.6.9` → `0.6.10` |

---

### Release Notes

<details>
<summary>tower-rs/tower-http (tower-http)</summary>

### [`v0.6.10`](https://github.com/tower-rs/tower-http/releases/tag/tower-http-0.6.10)

[Compare Source](tower-rs/tower-http@tower-http-0.6.9...tower-http-0.6.10)

#### Added

- `follow-redirect`: expose `Attempt::method()` and `Attempt::previous_method()`
  so redirect policies can react to method changes across redirects (e.g.
  POST to GET on 301/303) ([#&#8203;559])

#### Fixed

- Restore `tokio` and `async-compression` as no-op features. These will be
  removed next breaking release ([#&#8203;667])

[#&#8203;559]: tower-rs/tower-http#559

[#&#8203;667]: tower-rs/tower-http#667

#### What's Changed

- fix: restore tokio and async-compression as no-op features by [@&#8203;jlizen](https://github.com/jlizen) in [#&#8203;667](tower-rs/tower-http#667)
- fix gate-ing of atomic64 in tests by [@&#8203;alexanderkjall](https://github.com/alexanderkjall) in [#&#8203;607](tower-rs/tower-http#607)
- follow\_redirect: expose previous and next request methods by [@&#8203;lucab](https://github.com/lucab) in [#&#8203;559](tower-rs/tower-http#559)
- chore: release tower-http 0.6.10 by [@&#8203;jlizen](https://github.com/jlizen) in [#&#8203;669](tower-rs/tower-http#669)

#### New Contributors

- [@&#8203;lucab](https://github.com/lucab) made their first contribution in [#&#8203;559](tower-rs/tower-http#559)

**Full Changelog**: <tower-rs/tower-http@tower-http-0.6.9...tower-http-0.6.10>

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMDEuMSIsInVwZGF0ZWRJblZlciI6IjQzLjEwMS4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJ0eXBlL3BhdGNoIl19-->

Reviewed-on: https://git.erwanleboucher.dev/eleboucher/towonel/pulls/34
eleboucher pushed a commit to eleboucher/towonel that referenced this pull request May 20, 2026
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [tower-http](https://github.com/tower-rs/tower-http) | workspace.dependencies | patch | `0.6.9` → `0.6.10` |

---

### Release Notes

<details>
<summary>tower-rs/tower-http (tower-http)</summary>

### [`v0.6.10`](https://github.com/tower-rs/tower-http/releases/tag/tower-http-0.6.10)

[Compare Source](tower-rs/tower-http@tower-http-0.6.9...tower-http-0.6.10)

#### Added

- `follow-redirect`: expose `Attempt::method()` and `Attempt::previous_method()`
  so redirect policies can react to method changes across redirects (e.g.
  POST to GET on 301/303) ([#&#8203;559])

#### Fixed

- Restore `tokio` and `async-compression` as no-op features. These will be
  removed next breaking release ([#&#8203;667])

[#&#8203;559]: tower-rs/tower-http#559

[#&#8203;667]: tower-rs/tower-http#667

#### What's Changed

- fix: restore tokio and async-compression as no-op features by [@&#8203;jlizen](https://github.com/jlizen) in [#&#8203;667](tower-rs/tower-http#667)
- fix gate-ing of atomic64 in tests by [@&#8203;alexanderkjall](https://github.com/alexanderkjall) in [#&#8203;607](tower-rs/tower-http#607)
- follow\_redirect: expose previous and next request methods by [@&#8203;lucab](https://github.com/lucab) in [#&#8203;559](tower-rs/tower-http#559)
- chore: release tower-http 0.6.10 by [@&#8203;jlizen](https://github.com/jlizen) in [#&#8203;669](tower-rs/tower-http#669)

#### New Contributors

- [@&#8203;lucab](https://github.com/lucab) made their first contribution in [#&#8203;559](tower-rs/tower-http#559)

**Full Changelog**: <tower-rs/tower-http@tower-http-0.6.9...tower-http-0.6.10>

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMDEuMSIsInVwZGF0ZWRJblZlciI6IjQzLjEwMS4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJ0eXBlL3BhdGNoIl19-->

Reviewed-on: https://git.erwanleboucher.dev/eleboucher/towonel/pulls/34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants