Skip to content

Refactor redirect logic to be reusable for async/await #522

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Dec 8, 2021

Conversation

dnadoba
Copy link
Collaborator

@dnadoba dnadoba commented Dec 7, 2021

Motivation

We want to reuse the current redirect logic, which was mainly located inside the RedirectHandler, for the upcoming async/await implementation.

Changes

  • move HTTPClient.Request.RedirectState to the top level and a separate file
  • refactor redirect logic from RedirectHandler into methods on HTTPHeaders and methods on RedirectState
  • use the refactored methods in RedirectHandler

@dnadoba dnadoba requested a review from fabianfett December 7, 2021 11:41
@dnadoba dnadoba force-pushed the dn-redirect-refactor branch 2 times, most recently from eff9ef4 to 57ddf52 Compare December 7, 2021 13:59
fix compilation fro Swift 5.3

remove double whitespace

save progress
@dnadoba dnadoba force-pushed the dn-redirect-refactor branch from 57ddf52 to 2879863 Compare December 7, 2021 15:16
Comment on lines 118 to 120
} else if responseStatus == .movedPermanently || responseStatus == .found, requestMethod == .POST {
convertToGet = true
}
Copy link
Member

Choose a reason for hiding this comment

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

I know that this is just the code that existed before. @Lukasa does that make any sense?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yup, that's exactly right, see step 12 in this algorithm.

@fabianfett fabianfett requested a review from Lukasa December 7, 2021 17:17
@Lukasa Lukasa added the 🔨 semver/patch No public API change. label Dec 7, 2021
}
redirectHandler = RedirectHandler<Delegate.Response>(request: request) { newRequest in
guard request.redirectState != nil else { return nil }
Copy link
Collaborator

Choose a reason for hiding this comment

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

I find this pattern pretty oblique: it's not obvious to me that having no redirect state means "don't follow redirects". Can we use a computed property on request to make it clearer?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

redirectState is now no longer a property on request. It never really belonged there in the first place and is now passed explicitly to the RedirectHandler. I also didn't like that nil means don't follow redirects but now that we explicitly forward it is a bit better.

If we still want to make it more explicit, I think we need to make RedirectState aware of the "don't follow redirects" case and ask it before we create a RedirectHandler.

do {
var redirectState = self.request.redirectState
try redirectState?.redirect(to: redirectURL.absoluteString)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is it acceptable for redirectState to be nil here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No, I have removed redirectState from Request and moved it to RedirectHandler itself. We now explicitly forward the RedirectState and don't carry it implicitly through the Request.

/// Returns nil if the user disallowed redirects,
/// otherwise an instance of `RedirectState` which respects the user defined settings.
init?(
_ configuration: HTTPClient.Configuration.RedirectConfiguration.Configuration,
Copy link
Collaborator

Choose a reason for hiding this comment

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

This type name is awful. Is it possible we could give some of these types clearer names? If not, can we use a typealias?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

sadly HTTPClient.Configuration.RedirectConfiguration is public API but we can change the last Configuration to e.g. Mode. In addition, we can add a typealias:

internal typealias RedirectMode = HTTPClient.Configuration.RedirectConfiguration.Mode

WDYT?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd like both of those changes, great idea!

throw HTTPClientError.redirectCycleDetected
}

self.count -= 1
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we store count or just derive it from self.visited?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

self.visited.count counts up, self.count counts down until it hits zero where we know we reached the limit.
Because we need to know when we reach the limit, self.visited wouldn't be enough and we would still need to store the limit. Nevertheless, I think it's clearer to only count up and compare self.visited.count agains the constant limit to deduplicate counting.

- `redirectState` is no longer a property of `HTTPClient.Request`. RedirectHandler now stores this state directly and therefore no longer optional.
- we no longer count the number of allowed redirects down. Instead the number of redirects is dervied from `self.visited.count` and we compare it to the maxRedirect to check if we git the limit.
… called `HTTPClient.Configuration.RedirectConfiguration.Mode`

only two `Configuration`s left in the type name
@fabianfett fabianfett requested a review from Lukasa December 8, 2021 17:03
@dnadoba dnadoba merged commit c4feafd into swift-server:main Dec 8, 2021
@dnadoba dnadoba deleted the dn-redirect-refactor branch December 8, 2021 18:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🔨 semver/patch No public API change.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants