Skip to content

wmalloc/HTTPRequestable

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

211 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Swift Platforms Swift Package Manager License

HTTPRequestable

A lightweight WebService API for Apple devices, written in Swift 5.x and using Structured Concurrency. It builds on top of HTTPTypes library by Apple.

Getting Started

Add the following dependency clause to your Package.swift:

// swift-tools-version:5.11
import PackageDescription

let package = Package(
  name: "MyPackage",
  platforms: [.iOS(.v16), .tvOS(.v16), .macOS(.v12), .watchOS(.v9), .macCatalyst(.v16), .visionOS(.v1)],
  products: [
    .executable(name: "MyApp", targets: ["MyApp"])
  ],
  dependencies: [
    .package(url: "https://github.com/wmalloc/HTTPRequestable.git", from: "0.21.0")
  ],
  targets: [
    .target(name: "MyApp", dependencies: 
      [.product(name: "HTTPRequestable", package: "HTTPRequestable")])
  ]
)

Features

Protocol Features
HTTPRequestConfigurable Define your request
HTTPTransferable To create your API client
HTTPRequestConvertible To create your HTTPRequest
URLRequestConvertible To create your URLRequest
URLConvertible To create your URL

Usage

Creating an API Manager

final class HackerNews: HTTPTransferable, @unchecked Sendable {
  var requestModifiers: [any HTTPRequestModifier] = []
  var interceptors: [any HTTPInterceptor] = []

  let session: URLSession

  required init(session: URLSession = .shared) {
    self.session = session
    let logger = LoggerInterceptor()
    requestModifiers.append(logger)
    interceptors.append(logger)
  }

 func storyList(type: String) async throws -> StoryList.ResultType {
    let request = try StoryListRequest(environment, storyType: type)
    return try await object(for: request, delegate: nil).value ?? []
  }
}

To defineing a request

struct StoryListRequest: HTTPRequestConfigurable {
  typealias ResultType = [Int]
  
  let environment: HTTPEnvironment
  let headerFields: HTTPFields? = .init([.accept(.json)])
  let queryItems: [URLQueryItem]? = [URLQueryItem(name: "print", value: "pretty")]
  let path: String?
  
  var responseDataTransformer: Transformer<Data, ResultType>? {
    Self.jsonDecoder
  }
  
  init(_ environment: HTTPEnvironment, storyType: String) throws {
    precondition(!storyType.isEmpty, "Story type cannot be empty")
    self.environment = environment
    self.path = "/\(storyType).json"
  }
}

Then you can create an instantiate your API object to make calls

var api = HackerNews()
let topStories = try await api.storyList(type: "topstories.json")

URLSession

If you intend to make direct calls to URLSession, there are APIs defined to accept configuration and facilitate the execution of API calls.

HTTPRequestModifier

If you wish to modify the requests before they are sent to the server, you can create an object that conforms to the HTTPRequestModifier interface and add it to the requestModifiers.

For instance, you could create an authorization modifier that would add the Authorization header to the request.

HTTPInterceptor

If you wish to intercept the requests before they are finished, you can create an object that conforms to the HTTPInterceptor interface and add it to the interceptors. They are called in the reverse order.

Logging interceptors are provided if you would like to log you responses.

License

HTTPRequestable is released under the MIT license. See LICENSE for details.

Support

If you would like to support this project, please consider donating.
Bitcoin: bc1qzxs3wk29vfxlr9e4frq9cdmgkvrp62m5xhm93l
Ethereum: 0xa824353280d2A0F32b2d258904509EFAEaE6603d

About

Generic protocol to make swift requests

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages