Skip to content

Instantly share code, notes, and snippets.

@aronbudinszky
Last active December 24, 2023 11:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save aronbudinszky/66cdb71d734ae48a2609c7f2c094a02d to your computer and use it in GitHub Desktop.
Save aronbudinszky/66cdb71d734ae48a2609c7f2c094a02d to your computer and use it in GitHub Desktop.
An extension that provides async support for URLSession data function on Linux. See: https://medium.com/hoursofoperation/use-async-urlsession-with-server-side-swift-67821a64fa91?sk=bc142f8d3b6a444253eea660646aa822
import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
/// Defines the possible errors
public enum URLSessionAsyncErrors: Error {
case invalidUrlResponse, missingResponseData
}
/// An extension that provides async support for fetching a URL
///
/// Needed because the Linux version of Swift does not support async URLSession yet.
public extension URLSession {
/// A reimplementation of `URLSession.shared.data(from: url)` required for Linux
///
/// - Parameter url: The URL for which to load data.
/// - Returns: Data and response.
///
/// - Usage:
///
/// let (data, response) = try await URLSession.shared.asyncData(from: url)
func asyncData(from url: URL) async throws -> (Data, URLResponse) {
return try await withCheckedThrowingContinuation { continuation in
let task = self.dataTask(with: url) { data, response, error in
if let error = error {
continuation.resume(throwing: error)
return
}
guard let response = response as? HTTPURLResponse else {
continuation.resume(throwing: URLSessionAsyncErrors.invalidUrlResponse)
return
}
guard let data = data else {
continuation.resume(throwing: URLSessionAsyncErrors.missingResponseData)
return
}
continuation.resume(returning: (data, response))
}
task.resume()
}
}
}
@GustavoHernandezP
Copy link

Hi!... This solution worked perfect in my Xcode project. But, when I try to build into a Ubuntu Server, the process sent me this message:
non-nominal type 'URLSession' (aka 'AnyObject') cannot be extended
Do you know what it means?.
Thank you in advance!

@aronbudinszky
Copy link
Author

@GustavoHernandezP It is quite possible that the conditional import was missing. I have now added this to the gist to clarify that it too is required. Lemme know if this works!

@GustavoHernandezP
Copy link

Thanks for your answer. My solution was to extend the NSObject. With this modification, the process works fine!.

public extension NSObject {

@aronbudinszky
Copy link
Author

That would also work - since you are avoiding using URLSession (which is the one defined in FoundationNetworking on Linux).

@sherwinzadeh
Copy link

One small error, I believe. You shouldn't use URLSession.shared as this is an extension on URLSession itself and you may have different ones for different configurations (e.g. headers, auth, etc.)

@aronbudinszky
Copy link
Author

One small error, I believe. You shouldn't use URLSession.shared as this is an extension on URLSession itself and you may have different ones for different configurations (e.g. headers, auth, etc.)

Very good point, fixed!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment