A simple light-weight network library to make network requesting simpler. It supports newer techonology such as async/await as well as traditional completion block.

How to install

Follow the tutorial provided by Apple to install this library as a package:

How to use

Library allows to decode a structure or class while performing a network request. In order to make a network request either use Request class or extend RequestTask class for custom request.


In order for the client to decode an object, it should implement the protocol SelfDecodable like:

struct MyCustomDecodable: SelfDecodable {
    let id: Int
    let name: String
    let age: String

    // Either use default decoder or create custom
    static var decoder: JSONDecoder = .default


To perform a request you can use one of the following functions:

Swift Combine:

func performRequest<Value: SelfDecodable>(_ request: RequestTask) -> AnyPublisher<Value, Error>

Swift Async/Await:

func performRequest<Value: SelfDecodable>(_ request: RequestTask) async throws -> Value

Completion block:

func performRequest<Value: SelfDecodable>(_ request: RequestTask, completion: @escaping ResultCompletion<Value>)

In each of the above function Value represents the Decodable response class.


Response object:

struct TestDecodable: SelfDecodable {
    static var decoder: JSONDecoder = {
        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase
        return decoder
    let  firstName: String
    let  lastName: String


let host = URLHost(rawValue: "")
let endpoint = Endpoint(path: "/items/42")
let request = Request(host: host, endpoint: endpoint)
let response: TestDecodable = try await NetworkClient.shared.performRequest(request)


Default URL base host:

While Request allows to change request host, scheme and other information before the call is initiated, you might wanna have a global standard host. For that extend URLHost

extension URLHost {
    static var `default`: Self {
        return URLHost(rawValue: "")

let endpoint = Endpoint(url: "/items/42")
let request = Request(host: .default, endpoint: endpoint)

Endpoints structure:

For better readability of endpoints, you might wanna extend the Endpoint struct to create readable paths.

extension Endpoint {
    static func getAllItems(offset: Int, limit: Int): Self {
        return Endpoint(path: "/api/v2/items", queryParameters: [
            URLQueryItem(name: "limit", value: String(limit)),
            URLQueryItem(name: "offset", value: String(offset))
let endpoint = Endpoint.getAllItems(offset: 0, limit: 20)
let request = Request(host: .default, endpoint: endpoint)