Skip to content

Instantly share code, notes, and snippets.

@sherwinzadeh
Forked from aronbudinszky/URLSession+async.swift
Last active January 25, 2023 07:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sherwinzadeh/67357234bcfd9c91084c1b219bf116c9 to your computer and use it in GitHub Desktop.
Save sherwinzadeh/67357234bcfd9c91084c1b219bf116c9 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 = 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()
}
}
/// A reimplementation of `URLSession.shared.data(for: request)` required for Linux
///
/// - Parameter request: The URLRequest for which to load data.
/// - Returns: Data and response.
///
/// - Usage:
///
/// let (data, response) = try await URLSession.shared.asyncData(for: request)
func asyncData(for request: URLRequest) async throws -> (Data, URLResponse) {
return try await withCheckedThrowingContinuation { continuation in
let task = dataTask(with: request) { 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()
}
}
}
@sherwinzadeh
Copy link
Author

I have updated to support URLRequest as well as URLs. Also calling dataTask on the session itself, not the global shared one as you may have multiple.

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