Skip to content

Add option to retain request method on 301/302/303 redirects#887

Open
hamzahrmalik wants to merge 9 commits intoswift-server:mainfrom
hamzahrmalik:redirect_dont_convert_to_get
Open

Add option to retain request method on 301/302/303 redirects#887
hamzahrmalik wants to merge 9 commits intoswift-server:mainfrom
hamzahrmalik:redirect_dont_convert_to_get

Conversation

@hamzahrmalik
Copy link
Contributor

@hamzahrmalik hamzahrmalik commented Feb 16, 2026

Add a configuration option to retain the HTTP method and body receiving 301 or 302 responses.

Currently we automatically change the method to GET, and remove the body, before following a 301 or 302. This is compliant with the fetch specification: https://fetch.spec.whatwg.org/#http-redirect-fetch

However, it is useful to be able to override this behaviour and retain the method and body.

Changes

  • Add a new struct to encapsulate the (now 4) arguments of the follow case of the redirect mode
  • Add new options retainHTTPMethodAndBodyOn301 and retainHTTPMethodAndBodyOn302. Defaults to false because thats the existing behaviour today
  • When it is true, do not convert requests to GET after following a redirect
  • Note: this does not affect 307/308 (or any other) redirects. They always preserve their method

/// - Parameters:
/// - max: The maximum number of allowed redirects.
/// - allowCycles: Whether cycles are allowed.
/// - convertToGet: Whether to convert POST requests into GET requests when following a 301, 302 or 303 redirect. This does not apply to 307 or 308. Those always retain the original method.
Copy link
Member

Choose a reason for hiding this comment

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

I think we should call out that this should be true except, if users have clear needs.

Comment on lines 1321 to 1325
/// Redirects are followed with a specified limit.
///
/// - parameters
///
/// - warning: Cycle detection will keep all visited URLs in memory which means a malicious server could use this as a denial-of-service vector.
Copy link
Member

Choose a reason for hiding this comment

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

This comments looks weird.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

i copied it from the existing one above

Copy link
Member

@fabianfett fabianfett left a comment

Choose a reason for hiding this comment

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

Love the tests. Let the naming bike-shed begin.

Comment on lines 1281 to 1283
/// Whether to convert POST requests into GET requests when following a 301, 302 or 303 redirect.
/// This does not apply to 307 or 308. Those always retain the original method.
public var convertToGet: Bool
Copy link
Member

Choose a reason for hiding this comment

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

I like that curls specifically calls out 301, 302 and 303. I wonder if we should do the same here? convertToGet sounds too broad for me.

}

/// Configuration for following redirects.
public struct FollowConfiguration: Hashable, Sendable {
Copy link
Member

Choose a reason for hiding this comment

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

I wonder if it is worth adding this new struct now? If I see this correctly, we don't pass it around at all. Lets just add another property on the enum for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

given that we're doing 3 properties now, imo we should keep the struct. We can actually take advantage of it by holding the struct inside the RedirectState

Copy link
Contributor Author

Choose a reason for hiding this comment

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

see last commit

@fabianfett fabianfett added the 🆕 semver/minor Adds new public API. label Feb 20, 2026
Comment on lines 69 to 70
/// - `retainHTTPMethodAndBodyOn301` (bool, optional, default: false): Retain the original HTTP method and body on 301 redirect when mode is "follow". This is contrary to the fetch specification, but is allowed by RFC 9110.
/// - `retainHTTPMethodAndBodyOn302` (bool, optional, default: false): Retain the original HTTP method and body on 302 redirect when mode is "follow". This is contrary to the fetch specification, but is allowed by RFC 9110.
Copy link
Member

Choose a reason for hiding this comment

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

Lets call out POST here explicitly. Because this is just about POST.

Copy link
Member

@fabianfett fabianfett left a comment

Choose a reason for hiding this comment

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

This looks amazing! Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🆕 semver/minor Adds new public API.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments