Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a659a9399c | |||
|
|
03044604fd | ||
|
|
2c781fbac6 | ||
|
|
966b439277 |
@@ -26,10 +26,8 @@ import Foundation
|
||||
import Security
|
||||
#endif
|
||||
#if canImport(UIKit)
|
||||
#if canImport(UIKit)
|
||||
import UIKit
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/// A generic `Result` enumeration to represent either a success `Value` or a failure `Error`.
|
||||
public enum Result<Value, Error: Swift.Error> {
|
||||
@@ -47,6 +45,8 @@ public enum httpMethod: String {
|
||||
case get = "GET"
|
||||
/// The PUT method.
|
||||
case put = "PUT"
|
||||
/// The PATCH method.
|
||||
case patch = "PATCH"
|
||||
/// The DELETE method.
|
||||
case delete = "DELETE"
|
||||
}
|
||||
@@ -90,7 +90,7 @@ public struct API {
|
||||
/// - Parameters:
|
||||
/// - url: The URL string for the request.
|
||||
/// - params: Optional parameters for the request. Can be `[String: Any]` for JSON/form-data, or `Data` for raw body.
|
||||
/// - method: The HTTP method to use for the request (`.get`, `.post`, `.put`, `.delete`).
|
||||
/// - method: The HTTP method to use for the request (`.get`, `.post`, `.put`, `.delete`,`.patch` ).
|
||||
/// - headers: Optional custom HTTP headers to be added to the request. These override default headers if there are conflicts.
|
||||
/// - jsonEncoding: A boolean indicating whether parameters should be JSON encoded. Defaults to `true`.
|
||||
/// - debug: A boolean indicating whether to print debug logs for the request and response. Defaults to `true`.
|
||||
@@ -110,8 +110,8 @@ public struct API {
|
||||
persistConnection: Bool = false) async throws -> T {
|
||||
|
||||
if let urlReq = URL(string: url.replaceURL(params as? [String: Any] ?? [:] )) {
|
||||
var request = URLRequest(url: urlReq, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 30)
|
||||
if method == .post || method == .put || method == .delete {
|
||||
var request = URLRequest(url: urlReq, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: timeoutInterval)
|
||||
if method == .post || method == .put || method == .delete || method == .patch {
|
||||
if let params = params as? [String: Any],
|
||||
let pathFile = params["file"] as? String,
|
||||
let fileURL = URL(string: pathFile) {
|
||||
@@ -194,7 +194,18 @@ public struct API {
|
||||
API.requestLOG(method: method, request: request)
|
||||
}
|
||||
|
||||
let session = URLSession(
|
||||
// Only spin up a dedicated session (with its own @MainActor
|
||||
// delegate hop for every TLS/auth challenge) when client
|
||||
// certificate auth is actually configured. Creating one of
|
||||
// these per request unconditionally — and never invalidating
|
||||
// it — could stall the async challenge callback waiting on an
|
||||
// already-busy MainActor, hanging the request indefinitely with
|
||||
// no timeout or error ever surfacing. The common case (no
|
||||
// client cert) uses the shared session, which has none of this
|
||||
// risk and is what URLSession is designed to be reused as.
|
||||
let usesCertSession = API.certData != nil
|
||||
let session: URLSession = usesCertSession
|
||||
? URLSession(
|
||||
configuration: .default,
|
||||
delegate: URLSessionDelegateHandler(
|
||||
certData: API.certData,
|
||||
@@ -202,6 +213,12 @@ public struct API {
|
||||
),
|
||||
delegateQueue: nil
|
||||
)
|
||||
: URLSession.shared
|
||||
defer {
|
||||
if usesCertSession {
|
||||
session.finishTasksAndInvalidate()
|
||||
}
|
||||
}
|
||||
do {
|
||||
let (data, response) = try await session.data(for: request)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user