TUSKit icon indicating copy to clipboard operation
TUSKit copied to clipboard

Problem with background file upload and token refresh handling

Open Serg-Pogrebnyak opened this issue 7 months ago • 3 comments

Hello,
I'm encountering an issue when using background file uploads with token-based authorization.

In my app, uploads are authorized via a bearer token. For testing purposes, I've set short-lived tokens (30 seconds) to simulate token expiry during background uploads.

Each time an error occurs due to an expired token, I refresh the token manually, recreate the URLSessionConfiguration with the new token, and then reinitialize the TUSClient. This is necessary, otherwise the internal URLSession in TUSClient continues using the old token from its original configuration.

Setup example:

let urlSessionConfig = URLSessionConfiguration
    .background(withIdentifier: sessionId.uuidString)
urlSessionConfig.httpAdditionalHeaders = [
    "Authorization": accessAPIToken.token
]

tusClient = try TUSClient(
    server: tusServerURL,
    sessionIdentifier: UUID().uuidString,
    sessionConfiguration: urlSessionConfig,
    storageDirectory: tusDirectory
)

The issue

  • When the token expires and I recreate the TUSClient with a new session config and token:
  • The upload fails silently - no error is delivered via URLSessionDataDelegate or TUSClient.
  • The upload does not resume.
  • No error message is available, which leads to the app becoming stuck in a hanging state.
  • Calling stopAndCancelAll() doesn’t resolve the issue.
  • It seems that after recreating the client, the error from the background session is no longer captured.

Questions / Suggestions

  • Would it be possible to allow passing a delegate explicitly to TUSClient, so background errors can be handled externally?
  • Is there a recommended way to refresh the token without recreating the whole URLSessionConfiguration or TUSClient?
  • Alternatively, is there a way to invalidate and recreate a URLSession with a new header while keeping the same background identifier?

Any advice or guidance would be greatly appreciated - thank you!

Image

Serg-Pogrebnyak avatar Jun 20 '25 11:06 Serg-Pogrebnyak

Hi @Serg-Pogrebnyak, these are all really good suggestions. I understand your need for a fix and will spend some time thinking about the most appropriate solution here since remaking the session is something that we'd generally like to avoid whenever possible. For example, maybe instead of passing your standard headers to URLSession we could have you pass them into the TUSClient so we add the headers on your behalf.

I could also see this take the shape of a closure where we can pass in information about the specific request we're about to make and you'd be able to provide custom headers that are tailored to the exact request we're about to make.

I feel like both of these would be a lot simpler to implement than allowing a complete session swap.

What do you think?

donnywals avatar Jun 23 '25 13:06 donnywals

Hi @donnywals, thank you for your response and for taking the time to consider this.

I think the idea of passing my standard headers into the TUSClient, instead of directly to URLSession, sounds like a good approach. Since these headers are often static (the same across all uploads), this could indeed solve the problem in a clean and efficient way.

I also have a quick question - how would background uploads work in case if we’re splitting the file into 50MB chunks?

When handing control over to the system for background uploads, would it continue uploading the file chunk by chunk until it’s complete, or would it only upload the current chunk and stop there? Could you clarify how this would work in practice, and whether this approach is fully supported for background uploads at all?

Serg-Pogrebnyak avatar Jun 23 '25 15:06 Serg-Pogrebnyak

I think the idea of passing my standard headers into the TUSClient, instead of directly to URLSession, sounds like a good approach. Since these headers are often static (the same across all uploads), this could indeed solve the problem in a clean and efficient way.

Sounds good, I'll look into making this change in the next week or so. If you'd like, you're more than welcome to try and make a PR of your own.

I also have a quick question - how would background uploads work in case if we’re splitting the file into 50MB chunks?

When handing control over to the system for background uploads, would it continue uploading the file chunk by chunk until it’s complete, or would it only upload the current chunk and stop there? Could you clarify how this would work in practice, and whether this approach is fully supported for background uploads at all?

Essentially, it would more or less work in most case but it's not supported. iOS doesn't want apps scheduling new background work while the app is in the background, they punish apps by deprioritizing and delaying new uploads more based on how frequently you attempt to start downloads from the background.

The recommendation is to not chunk uploads, especially when you want to support backgrounds. Resuming uploads if/when they fail is handled by the TUS protocol so chunking has very little benefits for most people.

donnywals avatar Jun 26 '25 12:06 donnywals