Swiftpack.co - radianttap/Alley as Swift Package

Swiftpack.co is a collection of thousands of indexed Swift packages. Search packages.
See all packages published by radianttap.
radianttap/Alley 3.0
Essential `URLSessionDataTask` micro-wrapper for communication with HTTP(S) web services, with built-in automatic request retries.
⭐️ 147
🕓 30 weeks ago
iOS macOS watchOS tvOS
.package(url: "https://github.com/radianttap/Alley.git", from: "3.0")


platforms: iOS|tvOS|watchOS|macOS|visionOS
SwiftPM ready Carthage compatible CocoaPods compatible

Alley

Essential URLSessionDataTask micro-wrapper for communication with HTTP(S) web services. This is built as framework but it’s so small that I encourage you to simply copy the Alley folder into your project directly.

Why

In most cases where you need to fetch something from the internet, you:

  1. Want to get the data at the URL you are targeting, no matter what
  2. In case when it’s simply not possible, display some useful error to the end-customer and display / log what error actually happened so you can troubleshoot and debug

Second point is nice to have. First one is vastly more important since that data is the reason you are doing this at all.

Thus main feature of Alley is automatic request retries for predefined conditions.

Integration

Manually

Just drag Alley folder into your project.

If you prefer to use dependency managers, see below. Releases are tagged with Semantic Versioning in mind.

Swift Package Manager

Ready, just add this repo URL as Package.

  • Version 2.x supports old school stuff with completion handlers.
  • Version 3.x is pure async/await.

CocoaPods

CocoaPods is a dependency manager for Cocoa projects. For usage and installation instructions, visit their website. To integrate Alley into your Xcode project using CocoaPods, specify it in your Podfile:

pod 'Alley', 	:git => 'https://github.com/radianttap/Alley.git'

Setting up with Carthage

Carthage is a decentralized dependency manager that automates the process of adding frameworks to your Cocoa application.

You can install Carthage with Homebrew using the following command:

$ brew update
$ brew install carthage

To integrate Alley into your Xcode project using Carthage, specify it in your Cartfile:

github "radianttap/Alley"

Usage

You would already have some URLSession instance to work with. Then instead of this:

let urlRequest = URLRequest(...)

do {
	let data = try await urlSession.data(for: urlRequest)
} catch let err {
	//...process error
}

with Alley you will do this:

let urlRequest = URLRequest(...)

do {
	let data = try await urlSession.alleyData(for: urlRequest)
} catch let err {
	//...process NetworkError
}

In case the request was successful, you would get the Data instance returned from the service which you can convert into whatever you expected it to be.

In case of failure you will get an instance of NetworkError.

NetworkError

This is custom Error (implemented by an enum) which – for starters – wraps stuff returned by URLSessionDataTask. Thus first few possible options are:

///	`URLSession` errors are passed-through, handle as appropriate.
case urlError(URLError)

///	URLSession returned an `Error` object which is not `URLError`
case generalError(Swift.Error)

Next, if the returned URLResponse is not HTTPURLResponse:

case invalidResponseType(URLResponse)

Now, if it is HTTPURLResponse but status code is 400 or higher, this is an error returned by the web service endpoint you are communicating with. Hence you get the entire HTTPURLResponse and Data (if it exists) so caller can figure out what happened.

case endpointError(HTTPURLResponse, Data?)

In the calling object, you can use these values and try to build instances of strongly-typed custom errors related to the given specific web service.

If status code is in 2xx range, you may have a case of missing response body.

case noResponseData(HTTPURLResponse)

This may or may not be an error. If you perform PUT or DELETE or even POST requests, your service may not return any data as valid response (just 200 OK or whatever). In that case, prevent this error by calling perform like this:

let urlRequest = URLRequest(...)

let data = try await urlSession.alleyData(for: urlRequest, allowEmptyData: true)

where you will get empty Data().

There’s one more possible NetworkError value, which is related to...

Automatic retries

Default number of retries is 10.

This value is automatically used for all networking calls but you can adjust it per call by simply supplying appropriate number to maxRetries argument:

let urlRequest = URLRequest(...)

let data = try await urlSession.alleyData(for: urlRequest, maxRetries: 5)

How automatic retries work?

In case of a NetworkError being raised, Alley will check its shouldRetry property and – if that’s true – it will increment retry counter by 1 and perform URLSessionDataTask again. And again. And again...until it reaches maxRetries value when it will return NetworkError.inaccessible as result.

Each retry is delayed by half a second but you can supply any value you want (including 0) in the call to alleyData, argument retryInterval.

let urlRequest = URLRequest(...)

let data = try await urlSession.alleyData(for: urlRequest, retryInterval: 0.3)

You can customize the behavior by changing the implementation of shouldRetry property (in this case I recommend to manually copy Alley folder into your project).


That’s about it. Alley is intentionally simple to encourage writing as little code as possible, hiding away often-repeated boilerplate.

License

MIT License, like all my open source code.

Give back

If you found this code useful, please consider buying me a coffee or two. ☕️😋

GitHub

link
Stars: 147
Last commit: 8 weeks ago
Advertisement: IndiePitcher.com - Cold Email Software for Startups

Release Notes

3.0
21 hours ago

Major rewrite to modernise the library to fit with async/await and modern concurrency features in Swift.

Full Changelog: https://github.com/radianttap/Alley/compare/2.1...3.0

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