Skip to content

Commit

Permalink
Use ephemeral URLSession to send .org REST API requests (#23715)
Browse files Browse the repository at this point in the history
* Use ephemeral URLSession to send .org REST API requests

* Fix grammar issues in code comment

* Change static functions to initialisers

* Remove an unnecessary throw
  • Loading branch information
crazytonyli authored Nov 4, 2024
1 parent df1ad84 commit 4731816
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 13 deletions.
34 changes: 25 additions & 9 deletions WordPress/Classes/Networking/WordPressClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,20 @@ struct WordPressSite {
case selfHosted(username: String, authToken: String)
}

let baseUrl: String
let baseUrl: URL
let type: WordPressSite.SiteType

init(baseUrl: ParsedUrl, type: WordPressSite.SiteType) {
self.baseUrl = baseUrl.url()
self.baseUrl = baseUrl.asURL()
self.type = type
}

static func from(blog: Blog) throws -> WordPressSite {
init(blog: Blog) throws {
let url = try ParsedUrl.parse(input: blog.getUrlString())
if let account = blog.account {
return WordPressSite(baseUrl: url, type: .dotCom(authToken: account.authToken))
self.init(baseUrl: url, type: .dotCom(authToken: account.authToken))
} else {
return WordPressSite(baseUrl: url, type: .selfHosted(
self.init(baseUrl: url, type: .selfHosted(
username: try blog.getUsername(),
authToken: try blog.getApplicationToken())
)
Expand All @@ -45,16 +45,32 @@ actor WordPressClient {
self.rootUrl = rootUrl.url()
}

static func `for`(site: WordPressSite, in session: URLSession) throws -> WordPressClient {
let parsedUrl = try ParsedUrl.parse(input: site.baseUrl)
init(site: WordPressSite) {
// `site.barUrl` is a legal HTTP URL, which should be convertable to the `ParsedUrl` type.
let parsedUrl: ParsedUrl
do {
parsedUrl = try ParsedUrl.parse(input: site.baseUrl.absoluteString)
} catch {
fatalError("Failed to cast URL (\(site.baseUrl.absoluteString)) to ParsedUrl: \(error)")
}

// Currently, the app supports both account passwords and application passwords.
// When a site is initially signed in with an account password, WordPress login cookies are stored
// in `URLSession.shared`. After switching the site to application password authentication,
// the stored cookies may interfere with application-password authentication, resulting in 401
// errors from the REST API.
//
// To avoid this issue, we'll use an ephemeral URLSession for now (which stores cookies in memory
// rather than using the shared one on disk).
let session = URLSession(configuration: .ephemeral)

switch site.type {
case let .dotCom(authToken):
let api = WordPressAPI(urlSession: session, baseUrl: parsedUrl, authenticationStategy: .authorizationHeader(token: authToken))
return WordPressClient(api: api, rootUrl: parsedUrl)
self.init(api: api, rootUrl: parsedUrl)
case .selfHosted(let username, let authToken):
let api = WordPressAPI.init(urlSession: session, baseUrl: parsedUrl, authenticationStategy: .init(username: username, password: authToken))
return WordPressClient(api: api, rootUrl: parsedUrl)
self.init(api: api, rootUrl: parsedUrl)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ final class BlogDashboardViewModel {
var _error: Error?

do {
self.wordpressClient = try WordPressClient.for(site: .from(blog: self.blog), in: .shared)
self.wordpressClient = try WordPressClient(site: .init(blog: self.blog))
} catch {
_error = error
self.wordpressClient = nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ extension BlogDetailsViewController {

@objc func shouldShowApplicationPasswordRow() -> Bool {
// Only available for application-password authenticated self-hosted sites.
return self.blog.account == nil && self.blog.userID != nil && (try? WordPressSite.from(blog: self.blog)) != nil
return self.blog.account == nil && self.blog.userID != nil && (try? WordPressSite(blog: self.blog)) != nil
}

private func createApplicationPasswordService() -> ApplicationPasswordService? {
Expand All @@ -129,8 +129,8 @@ extension BlogDetailsViewController {
}

do {
let site = try WordPressSite.from(blog: self.blog)
let client = try WordPressClient.for(site: site, in: .shared)
let site = try WordPressSite(blog: self.blog)
let client = WordPressClient(site: site)
return ApplicationPasswordService(api: client, currentUserId: userId)
} catch {
DDLogError("Failed to create WordPressClient: \(error)")
Expand Down

0 comments on commit 4731816

Please sign in to comment.