Swiftpack.co -  shortcut/NetworkKit as Swift Package
Swiftpack.co is a collection of thousands of indexed Swift packages. Search packages.
shortcut/NetworkKit
Networking
.package(url: "https://github.com/shortcut/NetworkKit.git", from: "0.1.8")

CircleCI

NetworkKit

This package provides basic Networking.

Usage

Request

You can make requests on the shared Network object at NK or create your own Network. For example if you wanted to request a decoded User object, you could do:

NK.request(UsersAPI.getUser(id: 123)).responseDecoded(of: User.self) { response in
    switch response.result {
    case let .success(data):
        print("success \(data)")
    case let .failure(error):
        print("error: \(error)")
    }
}

You can request a urlString, URL, URLRequest or a TargetType:

NK.request("http://google")
NK.request(URL(string: "http://google"))
NK.request(URLRequest(url: URL(string:"http://google")))
NK.request(target)

You can also do .response if you just want the data, or .responseString if you want a string

Response

The type of object you get back from a response is Response, which is a wrapper around the Result<SomeModel, NetworkError> and holds everything you might need about the response, such as the originating URLRequest, the URLResponse object and raw data.

public struct Response<Success, Failure: Error> {
    public var request: URLRequest?
    public var response: URLResponse?

    public var data: Data?
    public let result: Result<SuccessType, NetworkError>
}

extension Response {
    public var statusCode: Int?
    public func localizedStringForStatusCode() -> String? 
    public var allHeaderFields: [AnyHashable: Any]? 
}

To cancel a request, hold on to the Request object and cancel it whenever.

let request = NK.request(UsersAPI.getUsers)
request.response { response in 
// blabla
}

request.cancel()

TargetType

Create an object that conforms to TargetType to define the HTTP details of your API's endpoints

enum UsersAPI {
    case createUser(id: String)
    case getUsers(name: String)
}

extension UsersAPI: TargetType {
    var baseURL: URL { URL(string: "http://example.com/")! }
    
    var headerValues: HTTPHeaders? {
        ["api-subscription-key": "asdkfhaskjdfh",
         "Accept": "application/json"]
    }
    
    var path: String {
        switch self {
        case .createUser(let id, _):
            return "/\(id)"
        case .getUsers(let name):
            return "/session/nfc/\(name)"
        }
    }
    
    var method: HTTPMethod {
        switch self {
        case .createUser:
            return .post
        case .getUsers:
            return .get
        }
    }
    
    var bodyType: HTTPBodyType {
        switch self {
        case .createUser:
            return .json
        case .getUsers:
            return .none
        }
    }
    
    var body: Encodable? {
        switch self {
        case .createUser(_, let payload):
            return payload
        case .getUsers:
            return nil
        }
    }
}

Validation

You can validate requests after the response if you need to define what counts as an error, for example if the HTTP status code is not 200. You can chain multiple validations, custom or not

NK.request(UserAPI.getUser("bob").validate().responseDecoded(of: TestModel.self) { response in
    
}

Custom error parsing

If your server returns different schemas on errors that you'd like to parse, you can supply a type that will be used to parse that, in the cases when validation fails.

So for example if you are calling an authorization server that returns status code 401 and some json describing the error, you can parse that and get it in the NetworkError


network?.request(AuthAPI.authenticate(with: credentials))
    .validate()
    .responseDecoded(of: AuthState.self,
                     errorType: AuthError.self) { response in

        switch response.result {
        case .success:
            // do fun stuff
        case let .failure(error):
            // get the AuthError object
            if case let .errorResponse(errorObject) = error {
                // do fun stuff with your AuthError object
            }
        }
}

Request Adaptors

If you'd like to adapt the URLRequest before transport, you can pass in a RequestAdaptor to your request, for example if you'd like to add runtime authentication headers:

public struct AuthenticationAdapter: RequestAdapter {
    let accessToken: AccessToken

    public func adapt(_ urlRequest: URLRequest) -> URLRequest {
        var urlRequest = urlRequest
        urlRequest.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
        return urlRequest
    }
}

self.network.request(target)
    .withAdapter(AuthenticationAdapter(accessToken: accessToken))
    .responseDecoded(of: T.self) { response in
        switch response.result {
        case let .success(products):
            completion(.success(products))
        case let .failure(error):
            completion(.failure(ApplicationError.networkError(error)))
        }
}

GitHub

link
Stars: 1
Last commit: 2 weeks ago

Ad: Job Offers

iOS Software Engineer @ Perry Street Software
Perry Street Software is Jack’d and SCRUFF. We are two of the world’s largest gay, bi, trans and queer social dating apps on iOS and Android. Our brands reach more than 20 million members worldwide so members can connect, meet and express themselves on a platform that prioritizes privacy and security. We invest heavily into SwiftUI and using Swift Packages to modularize the codebase.

Release Notes

Data in data even if server responds with 0 bytes
1 year ago

Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API