URLSession based networking supporting Swift Concurrency and completion block handler style APIs.
DZNetworking exposes simple APIs that make constructing networking models with REST APIs easy.
The API is straight-forward, well tested and extensible. DZNetworking should be treated as a simple wrapper around URLSession.
URLSessiondata, download and upload tasks- Generic
Decodablesupport for responses - Uploads to S3 buckets
- OAuth2 session handler
DZURLSession makes it really easy to get started. Here's a sample:
let session = DZURLSession()
session.baseURL = URL(string: "https://api.myapp.com/")!DZNetworking provides generic methods that automatically decode responses into your models.
// GET with automatic decoding
let (posts, response) = try await session.GET("/posts", type: [Post].self, query: ["userID": "1"])
// POST with JSON body and decoding
let (user, response) = try await session.POST("/signup", type: User.self, json: [
"name": "John Doe",
"email": "john@example.com"
])You can provide a custom JSONDecoder if your API uses specific date formats or key strategies.
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
let (data, _) = try await session.GET("/userdata", type: UserData.self, decoder: decoder)For bodies that arrive over time — server-sent events, newline-delimited JSON — stream returns the response head as soon as it lands and the body as lines. serverSentEvents parses those lines into events per the EventSource spec.
let (events, response) = try await session.serverSentEvents("/v1/messages", json: ["stream": true, "model": "…"])
for try await event in events {
print(event.event ?? "message", event.data)
}baseURL, the request modifiers, and extra headers apply as they do for every other request. A status above maxSuccessStatusCode reads the body and throws the same DZErrorDomain error the non-streaming calls throw, with the body under DZErrorData.
The DZJSONResponseParser implements the DZResponseParser protocol which handles parsing JSON responses. You can implement your own response parsers (example: XML, YAML, etc.) by conforming your parser to DZResponseParser.
You must then assign that response parser to the DZURLSession before making network requests.
let session = DZURLSession()
session.responseParser = DZJSONResponseParser()The DZURLSession class also comes with a requestModifier block. This is useful when you need to modify all or most requests in a similar fashion (e.g., adding authentication headers or device IDs) before they are sent.
session.requestModifier = { request in
var req = request
let timestamp = ISO8601DateFormatter().string(from: .now)
req.addValue(timestamp, forHTTPHeaderField: "Date")
req.addValue("my-device-id", forHTTPHeaderField: "x-deviceid")
// Add a calculated signature for security
let signature = "api-secret-\(timestamp)".sha256()
req.addValue(signature, forHTTPHeaderField: "Authorization")
return req
}I've tried my best to document most methods properly. All documentation is in the DocC format in the source files.
If you believe you require clarification on something, please open an issue, appropriately tagged, and I'll try to either:
- include documentation, if missing.
- improve documentation, if incorrect.
- try to answer the issue in the thread, if already correctly documented.
- HEAD
- OPTIONS
- GET
- POST
- PUT
- PATCH
- DELETE
If you'd like to contribute, please open a Pull Request. If you are encountering bugs, please open an Issue. Don't forget to tag it appropriately, and be nice to others.
If you see an opportunity to improve the tests suite, your additions will be much appreciated.
DZNetworking is licensed under the MIT License. Complete information can be found in the License file.