Skip to content

Split WebDAVSession into foreground data and background transfer sessions#40

Closed
tobihagemann wants to merge 1 commit into
developfrom
feature/split-webdav-background-session
Closed

Split WebDAVSession into foreground data and background transfer sessions#40
tobihagemann wants to merge 1 commit into
developfrom
feature/split-webdav-background-session

Conversation

@tobihagemann

Copy link
Copy Markdown
Member

The File Provider extension uses a background URLSession so transfers continue while it's suspended. But Apple's background sessions only support upload and download tasks, so issuing PROPFIND and the other metadata/control requests as data tasks on that session is undefined behavior and can stall transfers.

WebDAVSession now holds two sessions and routes by intent: a foreground .default data session for metadata/control ops, and the background transfer session for file transfers. The foreground-only path collapses both to one session, and both carry the same cookie/credential hardening.

Includes a routing regression test that stands up the two sessions with distinct recording URLProtocols and asserts each operation rides its intended session.

Flow

flowchart LR
  C[WebDAVClient] -->|OPTIONS, HEAD, PROPFIND, MKCOL, DELETE, MOVE| D["Foreground data session (.default)"]
  C -->|GET, PUT| T[Background transfer session]
Loading

@coderabbitai

coderabbitai Bot commented May 30, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

This PR introduces a two-session architecture for WebDAV operations: a foreground dataSession for metadata/control operations and a background transferSession for file transfers. WebDAVSession is refactored to hold both sessions, with its initializer and factory method updated to wire both with the same delegate. Download and upload methods are routed to appropriate sessions, and a new performDataDownloadTask method enables downloads via the data session. WebDAVClient is updated to use the renamed factory and new download method. Test infrastructure with recording protocol mocks validates that operations route correctly to their intended sessions.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Split WebDAVSession into foreground data and background transfer sessions' clearly and specifically summarizes the main architectural change in the changeset.
Description check ✅ Passed The description is directly related to the changeset, explaining the motivation (undefined behavior with background sessions), the solution (two-session routing), configuration details, and includes a regression test.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/split-webdav-background-session

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Sources/CryptomatorCloudAccess/WebDAV/WebDAVSession.swift`:
- Around line 203-208: The two URLSessionConfiguration instances create separate
HTTPCookieStorage objects causing cookies from metadata requests to not be
available to transfers; create a single shared HTTPCookieStorage instance (e.g.
let sharedCookieStorage = HTTPCookieStorage()) and assign that same instance to
both transferConfiguration.httpCookieStorage and
dataConfiguration.httpCookieStorage so transferSession and dataSession share
cookies; ensure any existing explicit nil for urlCredentialStorage remains
unchanged and reuse the sharedCookieStorage when constructing the sessions
(transferSession, dataSession).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: db610bdd-0352-48ba-849e-a214779675da

📥 Commits

Reviewing files that changed from the base of the PR and between 0f87299 and 5ece3a3.

📒 Files selected for processing (4)
  • Sources/CryptomatorCloudAccess/WebDAV/WebDAVClient.swift
  • Sources/CryptomatorCloudAccess/WebDAV/WebDAVSession.swift
  • Tests/CryptomatorCloudAccessTests/WebDAV/URLProtocolMock.swift
  • Tests/CryptomatorCloudAccessTests/WebDAV/WebDAVClientTests.swift

Comment on lines +203 to +208
transferConfiguration.httpCookieStorage = HTTPCookieStorage()
transferConfiguration.urlCredentialStorage = nil
let transferSession = URLSession(configuration: transferConfiguration, delegate: delegate, delegateQueue: nil)
let dataConfiguration = URLSessionConfiguration.default
dataConfiguration.httpCookieStorage = HTTPCookieStorage()
dataConfiguration.urlCredentialStorage = nil

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Sessions do not share cookie storage.

Each session creates its own HTTPCookieStorage() instance. Cookies received during metadata operations (dataSession) will not be sent with file transfers (transferSession), which may break WebDAV servers relying on session cookies for authentication.

Consider using a shared cookie storage instance:

Proposed fix to share cookie storage
 static func withBackgroundSession(with delegate: WebDAVClientURLSessionDelegate, sessionIdentifier: String, sharedContainerIdentifier: String? = nil) -> WebDAVSession {
+    let sharedCookieStorage = HTTPCookieStorage()
     let transferConfiguration = URLSessionConfiguration.background(withIdentifier: sessionIdentifier)
     transferConfiguration.sharedContainerIdentifier = sharedContainerIdentifier
-    transferConfiguration.httpCookieStorage = HTTPCookieStorage()
+    transferConfiguration.httpCookieStorage = sharedCookieStorage
     transferConfiguration.urlCredentialStorage = nil
     let transferSession = URLSession(configuration: transferConfiguration, delegate: delegate, delegateQueue: nil)
     let dataConfiguration = URLSessionConfiguration.default
-    dataConfiguration.httpCookieStorage = HTTPCookieStorage()
+    dataConfiguration.httpCookieStorage = sharedCookieStorage
     dataConfiguration.urlCredentialStorage = nil
     let dataSession = URLSession(configuration: dataConfiguration, delegate: delegate, delegateQueue: nil)
     return WebDAVSession(dataSession: dataSession, transferSession: transferSession, delegate: delegate)
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
transferConfiguration.httpCookieStorage = HTTPCookieStorage()
transferConfiguration.urlCredentialStorage = nil
let transferSession = URLSession(configuration: transferConfiguration, delegate: delegate, delegateQueue: nil)
let dataConfiguration = URLSessionConfiguration.default
dataConfiguration.httpCookieStorage = HTTPCookieStorage()
dataConfiguration.urlCredentialStorage = nil
static func withBackgroundSession(with delegate: WebDAVClientURLSessionDelegate, sessionIdentifier: String, sharedContainerIdentifier: String? = nil) -> WebDAVSession {
let sharedCookieStorage = HTTPCookieStorage()
let transferConfiguration = URLSessionConfiguration.background(withIdentifier: sessionIdentifier)
transferConfiguration.sharedContainerIdentifier = sharedContainerIdentifier
transferConfiguration.httpCookieStorage = sharedCookieStorage
transferConfiguration.urlCredentialStorage = nil
let transferSession = URLSession(configuration: transferConfiguration, delegate: delegate, delegateQueue: nil)
let dataConfiguration = URLSessionConfiguration.default
dataConfiguration.httpCookieStorage = sharedCookieStorage
dataConfiguration.urlCredentialStorage = nil
let dataSession = URLSession(configuration: dataConfiguration, delegate: delegate, delegateQueue: nil)
return WebDAVSession(dataSession: dataSession, transferSession: transferSession, delegate: delegate)
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Sources/CryptomatorCloudAccess/WebDAV/WebDAVSession.swift` around lines 203 -
208, The two URLSessionConfiguration instances create separate HTTPCookieStorage
objects causing cookies from metadata requests to not be available to transfers;
create a single shared HTTPCookieStorage instance (e.g. let sharedCookieStorage
= HTTPCookieStorage()) and assign that same instance to both
transferConfiguration.httpCookieStorage and dataConfiguration.httpCookieStorage
so transferSession and dataSession share cookies; ensure any existing explicit
nil for urlCredentialStorage remains unchanged and reuse the sharedCookieStorage
when constructing the sessions (transferSession, dataSession).

@tobihagemann

Copy link
Copy Markdown
Member Author

Closing this. I tested it and it doesn't fix the original problem, and I'm not confident the split is a net improvement either way. Not worth carrying the churn without a clear win.

@tobihagemann tobihagemann deleted the feature/split-webdav-background-session branch June 1, 2026 15:00
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.

1 participant