Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,36 @@

import PackageDescription

let approachableConcurrency: [SwiftSetting] = [
.enableUpcomingFeature("NonisolatedNonsendingByDefault"),
.enableUpcomingFeature("InferIsolatedConformances")
]

let package = Package(
name: "SimpleHTTP",
platforms: [.iOS(.v13), .macOS(.v10_15)],
platforms: [.iOS(.v13), .macOS(.v13)],
products: [
.library(name: "SimpleHTTPFoundation", targets: ["SimpleHTTPFoundation"]),
.library(name: "SimpleHTTP", targets: ["SimpleHTTP"])
],
dependencies: [
],
targets: [
.target(name: "SimpleHTTPFoundation", dependencies: []),
.target(name: "SimpleHTTP", dependencies: ["SimpleHTTPFoundation"]),
.testTarget(name: "SimpleHTTPFoundationTests", dependencies: ["SimpleHTTPFoundation"]),
.target(name: "SimpleHTTPFoundation", dependencies: [], swiftSettings: approachableConcurrency),
.target(name: "SimpleHTTP", dependencies: ["SimpleHTTPFoundation"], swiftSettings: approachableConcurrency),
.testTarget(
name: "SimpleHTTPFoundationTests",
dependencies: ["SimpleHTTPFoundation"],
swiftSettings: approachableConcurrency
),
.testTarget(
name: "SimpleHTTPTests",
dependencies: ["SimpleHTTP"],
resources: [
.copy("Ressources/Images/swift.png"),
.copy("Ressources/Images/swiftUI.png")
]
],
swiftSettings: approachableConcurrency
)
]
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ public typealias ContentDataEncodersConfiguration = [HTTPContentType: ContentDat
public typealias ContentDataDecodersConfiguration = [HTTPContentType: ContentDataDecoder]

/// Defines the list of encoders and decoders to use.
public struct ContentDataCodersConfiguration {
public struct ContentDataCodersConfiguration: Sendable {
public var encoders: ContentDataEncodersConfiguration
public var decoders: ContentDataDecodersConfiguration
public let defaultType: HTTPContentType
Expand Down
4 changes: 2 additions & 2 deletions Sources/SimpleHTTP/Interceptor/Interceptor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Foundation
public typealias Interceptor = RequestInterceptor & ResponseInterceptor

/// a protocol intercepting a session request
public protocol RequestInterceptor {
public protocol RequestInterceptor: Sendable {
/// Should be called before making the request to provide modifications to `request`
func adaptRequest<Output>(_ request: Request<Output>) async throws -> Request<Output>

Expand All @@ -14,7 +14,7 @@ public protocol RequestInterceptor {
}

/// a protocol intercepting a session response
public protocol ResponseInterceptor {
public protocol ResponseInterceptor: Sendable {
/// Should be called once the request is done and output was received. Let one last chance to modify the output
/// optionally throwing an error instead if needed
/// - Parameter request: the request that was sent to the server
Expand Down
4 changes: 2 additions & 2 deletions Sources/SimpleHTTP/Session/Session.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import Foundation

/// Primary class of the library used to perform http request using a `Request` object
public class Session {
final public class Session: Sendable {
/// a function returning a `RequestData` from a `URLRequest`
public typealias URLRequestTask = (URLRequest) async throws -> URLDataResponse
public typealias URLRequestTask = @Sendable (URLRequest) async throws -> URLDataResponse

let baseURL: URL
let config: SessionConfiguration
Expand Down
2 changes: 1 addition & 1 deletion Sources/SimpleHTTP/Session/SessionConfiguration.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Foundation

/// a type defining some parameters for a `Session`
public struct SessionConfiguration {
public struct SessionConfiguration: Sendable {
/// data encoders/decoders configuration per content type
let data: ContentDataCodersConfiguration
/// an interceptor to apply custom behavior on the session requests/responses.
Expand Down
8 changes: 4 additions & 4 deletions Sources/SimpleHTTPFoundation/Foundation/Coder/DataCoder.swift
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import Foundation

/// A encoder suited to encode to Data
public protocol DataEncoder {
public protocol DataEncoder: Sendable {
func encode<T: Encodable>(_ value: T) throws -> Data
}

/// A decoder suited to decode Data
public protocol DataDecoder {
public protocol DataDecoder: Sendable {
func decode<T: Decodable>(_ type: T.Type, from: Data) throws -> T
}

Expand All @@ -23,6 +23,6 @@ public protocol ContentDataDecoder: DataDecoder {
}

/// A function converting data when a http error occur into a custom error
public typealias DataErrorDecoder = (Data) throws -> Error
public typealias DataErrorDecoder = @Sendable (Data) throws -> Error

public typealias ContentDataErrorDecoder = (Data, HTTPContentType) throws -> Error
public typealias ContentDataErrorDecoder = @Sendable (Data, HTTPContentType) throws -> Error
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class CompositeInterceptorTests: XCTestCase {
}

private struct InterceptorStub: Interceptor {
var shouldRequestMock: (Error) throws -> Bool = { _ in false }
var shouldRequestMock: @Sendable (Error) throws -> Bool = { _ in false }

func shouldRescueRequest<Output>(_ request: Request<Output>, error: Error) async throws -> Bool {
try shouldRequestMock(error)
Expand All @@ -38,4 +38,4 @@ private struct InterceptorStub: Interceptor {

}

}
}
17 changes: 10 additions & 7 deletions Tests/SimpleHTTPTests/Session/SessionTests.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import XCTest
@testable import SimpleHTTP

@MainActor
class SessionAsyncTests: XCTestCase {
let baseURL = URL(string: "https://sessionTests.io")!
let data = ContentDataCodersConfiguration(
Expand Down Expand Up @@ -41,7 +42,7 @@ class SessionAsyncTests: XCTestCase {
}

func test_response_rescue_rescueIsSuccess_itRetryRequest() async throws {
var isRescued = false
nonisolated(unsafe) var isRescued = false
let interceptor = InterceptorStub()
let session = sesssionStub(interceptor: [interceptor]) {
URLDataResponse(data: Data(), response: isRescued ? .success : .unauthorized)
Expand Down Expand Up @@ -91,8 +92,10 @@ class SessionAsyncTests: XCTestCase {
}

/// helper to create a session for testing
private func sesssionStub(interceptor: CompositeInterceptor = [], response: @escaping () throws -> URLDataResponse)
-> Session {
private func sesssionStub(
interceptor: CompositeInterceptor = [],
response: @Sendable @escaping () throws -> URLDataResponse
) -> Session {
let config = SessionConfiguration(data: data, interceptors: interceptor)

return Session(baseURL: baseURL, configuration: config, dataTask: { _ in try response() })
Expand Down Expand Up @@ -121,10 +124,10 @@ private extension Request {
}
}

private class InterceptorStub: Interceptor {
var rescueRequestErrorMock: (Error) throws -> Bool = { _ in false }
var receivedResponseMock: ((Any, Any) -> Void)?
var adaptResponseMock: ((Any, Any) throws -> Any)?
final private class InterceptorStub: Interceptor, @unchecked Sendable {
var rescueRequestErrorMock: @Sendable (Error) throws -> Bool = { _ in false }
var receivedResponseMock: (@Sendable (Any, Any) -> Void)?
var adaptResponseMock: (@Sendable (Any, Any) throws -> Any)?

func adaptRequest<Output>(_ request: Request<Output>) -> Request<Output> {
request
Expand Down
Loading