Disable URLSession auto retry policy

We are developing an iOS application that is interacting with HTTP APIs that requires us to put a unique UUID (a nonce) as an header on every request (obviously there's more than that, but that's irrilevant to the question here).

If the same nonce is sent on two subsequent requests the server returns a 412 error. We should avoid generating this kind of errors as, if repeated, they may be flagged as a malicious activity by the HTTP APIs.

We are using URLSession.shared.dataTaskPublisher(for: request) to call the HTTP APIs with request being generated with the unique nonce as an header.

On our field tests we are seeing a few cases of the same HTTP request (same nonce) being repeated a few seconds on after the other. Our code has some retry logic only on 401 errors, but that involves a token refresh, and this is not what we are seeing from logs.

We were able to replicate this behaviour on our own device using Network Link Conditioner with very bad performance, with XCode's Network inspector attached we can be certain that two HTTP requests with identical headers are actually made automatically, the first request has an "End Reason" of "Retry", the second is "Success" with Status 412.

Our questions are:

  • can we disable this behaviour?
  • can we provide a new request for the retry (so that we can update headers)?

Thanks, Francesco

Answered by DTS Engineer in 852139022

Sorry I didn’t reply earlier. I remember seeing fpedron_omnys’s response but the task of replying seems to have slipped through the cracks )-:

The ideal solution for us would be to disable this behavior on the HTTP client.

I disagree. GET requests are meant to be both safe [1] and idempotent [2]. If you’ve created a server where that’s not the case, you’re not using HTTP in the way that it’s intended to be used. Even if you had a way to disable this on the client, you could still run into problems with middleboxes retrying requests.

IMO the correct fix here is to update your detection logic or use a different HTTP method (like POST), one that’s not idempotent.

Anyway, to answer your direct questions:

can we disable this behaviour?

No.

can we provide a new request for the retry (so that we can update headers)?

No.

You are, of course, free to file an enhancement request for such features.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] <https://developer.mozilla.org/en-US/docs/Glossary/Safe/HTTP>

[2] <https://developer.mozilla.org/en-US/docs/Glossary/Idempotent>

Are these all GET requests?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Yes, we have seen this happen on GET requests only, but please consider that at the moment we have found only two of these events as we are doing a private test with few devices and this is not yet released to the public.

Is this a server that you control?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Yes, we control the server and have already considered some workarounds for these situations. I can't discuss the details for security reasons, but they would reduce the implementation's security and fail to meet the requirements.

The ideal solution for us would be to disable this behavior on the HTTP client.

Any updates on this? I've been experiencing something similar. Only noticed it after implementing a "nonce" logic that rejects calls passing a nonce that was after used recently.

After some inspection I could see the duplicated requests are identical, and the time gap between them may vary from fraction of a second to 30s.

I couldn't reproduce the issue myself, so I can 't confirm it is a URLSession behavior.

Please correct me if I'm wrong byt from what I've informed myself the best strategy is not to try to avoid the retry request, but properly handle it on backend and possibly on the client – and also monitor spikes on the incidences caused by a single user.

Accepted Answer

Sorry I didn’t reply earlier. I remember seeing fpedron_omnys’s response but the task of replying seems to have slipped through the cracks )-:

The ideal solution for us would be to disable this behavior on the HTTP client.

I disagree. GET requests are meant to be both safe [1] and idempotent [2]. If you’ve created a server where that’s not the case, you’re not using HTTP in the way that it’s intended to be used. Even if you had a way to disable this on the client, you could still run into problems with middleboxes retrying requests.

IMO the correct fix here is to update your detection logic or use a different HTTP method (like POST), one that’s not idempotent.

Anyway, to answer your direct questions:

can we disable this behaviour?

No.

can we provide a new request for the retry (so that we can update headers)?

No.

You are, of course, free to file an enhancement request for such features.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] <https://developer.mozilla.org/en-US/docs/Glossary/Safe/HTTP>

[2] <https://developer.mozilla.org/en-US/docs/Glossary/Idempotent>

Thanks for your answer, it's importart that this behaviour of URLSession has been confirmed (and that it's confirmed it cannot be disabled) so we can adapt our implementation to it.

Disable URLSession auto retry policy
 
 
Q