I'm happy to announce that we shipped Alamofire 5 beta 1 just over a week ago! This is the most significant release of Alamofire since the original in 2014! I've been working on this release on and off for a year now and I'm hoping you'll all take a look.
During the beta process I hope to gather feedback about migration and what we can do to help the process given the substantial renames for some of the APIs. Also, I'll be working to rewrite the documentation, including a migration guide, for modern Alamofire usage. So please, post your experiences adopting Alamofire 5 in a new topics here so we can help everyone make the migration.
So what does Alamofire 5 include? Well, here are the brief release notes, but I'll provide more detail here:
Rewritten Core: Over the years, the core types of Alamofire had grown far beyond their original designs. Much of this complexity was due to added features that touched all of the internal types, but some was due to issues with the original design. One of those issues was improper separation of concerns, where features were spread over multiple types, making it hard to understand and maintain over time. Another issue was haphazard thread-safety, as Alamofire was originally developed without the benefit of the Thread Sanitizer. This meant threading fixes were grafted on over the years and Alamofire's queue usage became hazardous to the system if the user tried to enqueue many requests at the same time, as every Alamofire
Requesthad it's own queue, starving the system of resources. These rewritten types were able to rectify these issues by ensuring features were implemented in a single place, removing some complex but less used API, and reengineering Alamofire to use a single serial queue by default (as recommend in Modernizing Grand Central Dispatch from WWDC '17). I gave a presentation about this rewrite at dev/world 2018 in Melbourne, Australia. Overall these core types are faster, lighter, and smaller, while enabling more features and higher fidelity.
EncodableParameters: Alamofire 5 now supports making requests with parameters from
Encodabletypes. The implementation of this features includes a
URLEncodedFormEncoderfor query and body encoding, largely based off of Vapor's type of the same name. This feature actually turned out to be more powerful than I had initially thought and it enables some very elegant possibilities for generic request abstractions. In fact, this is so powerful that we'll likely deprecate the older
[String: Any]parameter type in a later 5.X please and remove it in a future major release.
DecodableResponses: Alamofire 5 now supports generic response serialization of
Decodabletypes. This is enabled through Alamofire's new
DataDecoderprotocol, which abstracts over any
Decoderthat can decode
Data. This protocol allows you to use any
Decoderwith a single response method, maximizing flexibility for users which need to handle multiple response types, but at the same time defaulting to JSON for simplicity.
Customizable Empty Response Handling: With the addition of
Decodableresponse parsing, it was necessary for Alamofire to further enhance its empty response handling. This now includes exposing default response codes and request methods that may return empty responses as well as customization points for the built in response serializers. More flexibility is coming in a future release.
HTTPHeaders: Alamofire 5 includes simple
HTTPHeadertypes to provide a single header API for all Alamofire and Foundation types, as well as convenience API for the most popular headers.
- Certificate Pinning API Rewritten: Alamofire 5 rewrites the top level certificate pinning APIs while keeping the tested core implementations, creating a much more flexible design. With some of the changes enabled by the core type rewrite, Alamofire 5 can now return individual errors for certificate pinning failures, rather than the previous cancellation error that was easily confused with manual and automatic cancellation of tasks. This ability, along with the new protocol abstraction, enables powerful pinning capabilities that can return informative errors.
EventMonitor: Alamofire 5 removes the previous closure API that was sometimes used to allow visibility into certain Alamofire events and replaces it with a standardized protocol abstraction that allows read-only access to 36 different events between both
URLSessionand Alamofire. This new abstraction allowed us to clean up our notification integration that was spread between multiple files into a single type that hooks into just the events that it needs. I've used this protocol on my own projects to enable easy logging of specific events in only a few lines of code.
Asynchronous Request Pipeline: In Alamofire 5, all request creation is now asynchronous, allowing us to unify the awkwardly different multipart form encoding process with Alamofire's standard request creation process. This means that not only is multipart form encoding much simpler now (no encoding completion!) but request creation no longer blocks the calling thread. These changes also allow for full fidelity request retry. Previous versions of Alamofire lost data when converting incoming parameters into
URLRequests to be performed. Now, all parameters are maintained and every step of the process is retried when
URLSessionTaskMetrics: Alamofire 5 now captures and exposes all
URLSessionTaskMetricsfor every request and removes the custom
Timelinetype that previously captured just a fraction of the same data. Not only are metrics captured for the last
URLSessionTaskissued, but since Alamofire 5 now captures all tasks associated with a
Request, even during retry, the full history of associated values is available, including metrics. This makes is very easy to see the local performance of your requests without additional analytics libraries.
Top Level API Removed from Global Namespace: Previous versions of Alamofire's documentation introduced users to making requests with the
Alamofire.request()API. This dates back to version 1 and I think it reflects Mattt's belief that Swift would gain qualified module references, allowing users to refer to modules that weren't imported by just using the module name. This never came to pass, so this API was actually misleading. What was actually happening was that
import Alamofirewas exposing global
request()API everywhere, and the
Alamofire.wasn't actually necessary. This API, since it's valuable simple introduction to Alamofire, has been moved inside an
AFenum (attempt to use an
Alamofireenum failed due to collision with the module name) as static methods.
RequestAdapterNow Asynchronous: As part of the new asynchronous request pipeline, the requirement for the
RequestAdapterprotocol was changed to be asynchronous as well, allowing adapters to grab async resources to add to a request.
- Older OS support: Alamofire 5 supports iOS 10+, macOS 10.12+, watchOS 3+, and tvOS 10+. Due to missing functionality in Foundation on Linux, Alamofire does not yet support Linux.
responsePropertyList, as we're pretty sure no one ever used them.
- Support for
URLSessionStreamTask, as that integration was never tested and yet had no issues filed against it, so we're pretty sure it was also never used.
- Alamofire's closure API, which allowed users to mutate Alamofire's core types by setting closures that could override specific behaviors. While this was a final escape hatch for full control over Alamofire's interaction with
URLSession, it was bug-prone and invasive. We hope to replace most of the functionality users gained by using the API by offering specific functionality that's better, but that will come in the future. This includes things like full control over response caching at the
URLSessionlevel, as well as client certificate verification.
As you can see, this is a huge list, so please ask questions in topics here, and if you find bugs or want to submit a feature, feel free to create issues and PRs on our GitHub.