-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
20 changed files
with
645 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
The MIT License (MIT) | ||
|
||
Copyright (c) 2024 SwiftyNetworking | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
# Overview | ||
|
||
**SwiftyNetworking** is a powerful and easy-to-use networking client written in Swift. | ||
It simplifies making network requests and handling responses, allowing you to focus on building your application rather than dealing with the complexities of networking. | ||
- **Simple**: Designed with simplicity and ease of use in mind, SwiftyNetworking eliminates the need for extensive configuration, making it ready to use right out of the box. | ||
- **Asynchronous**: Built with modern Swift concurrency, supporting `async/await`. | ||
- **Flexible**: Customize requests with different methods, headers, and cache policies. | ||
- **Inspectable**: SwiftyNetworking collect some network metrics that can be used for in-depth debugging. | ||
|
||
--- | ||
# Integration | ||
Integrating SwiftyNetworking into your Swift project is straightforward. Follow these steps to get started: | ||
|
||
1. **Install SwiftyNetworking**: | ||
- If you're using Swift Package Manager (SPM): | ||
- Open your Xcode project. | ||
- Navigate to "File" > "Swift Packages" > "Add Package Dependency...". | ||
- Enter the SwiftyNetworking repository URL: `https://github.com/antonio-war/SwiftyNetworking`. | ||
- Follow the prompts to select the version and add SwiftyNetworking to your project. | ||
- If you're using CocoaPods or Carthage, we're sorry, but they are not currently supported. | ||
2. **Import SwiftyNetworking**: | ||
- In the files where you want to use SwiftyNetworking features, import its module at the top of the file: | ||
```swift | ||
import SwiftyNetworking | ||
``` | ||
3. **Start Using SwiftyNetworking**: | ||
- Once SwiftyNetworking is imported, you can start using its methods to execute a networking request. | ||
- Refer to the usage section for guidance regarding structs, classes and methods. | ||
4. **Run Your Project**: | ||
- Build and run your project to ensure that SwiftyNetworking has been integrated successfully. | ||
- Test out the functionality you've implemented using SwiftyNetworking to ensure everything works as expected. | ||
That's it! You've successfully integrated SwiftyNetworking into your project and can now leverage its powerful features. | ||
|
||
--- | ||
# Usage | ||
The main steps for using SwiftyNetworking into your project are outlined below, guiding you through the process. | ||
|
||
### Request definition | ||
First, define a `SwiftyNetworkingRequest` which is a simple wrapper around `URLRequest` which allows you to easily set up everything you need to make an API call. | ||
Such as the classics method, headers and query parameters, but also some parameters closely linked to the iOS ecosystem such as cache policy or timeout management. | ||
|
||
```swift | ||
let request = SwiftyNetworkingRequest( | ||
endpoint: "https://jsonplaceholder.typicode.com", | ||
path: "comments", | ||
method: .get, | ||
parameters: ["postId": 1], | ||
cachePolicy: .reloadIgnoringCacheData | ||
) | ||
``` | ||
|
||
### Client creation | ||
Create a `SwiftyNetworkingClient` instance using the default or a custom URLSessionConfiguration. | ||
A single instance should be enough to manage the entire networking layer of the app, so hypothetically the client could be placed inside a dependency container. | ||
|
||
```swift | ||
let networkingClient = SwiftyNetworkingClient() | ||
``` | ||
|
||
### Request execution | ||
Execute the request using the defined async method. | ||
|
||
```swift | ||
let response = try await networkingClient.send(request: request) | ||
``` | ||
|
||
### Response handling | ||
If successful, the method will return a `SwiftyNetworkingResponse` which is a simple wrapper around `HTTPURLResponse` and allows you to easily access some elements like body, headers and few metrics. SwiftyNetworking always returns the source of the response and its duration allowing you to understand if it comes from the network or from the cache. | ||
|
||
```swift | ||
if response.status == 200 && let body = response.body { | ||
return String(data: body, encoding: .utf8) | ||
} | ||
``` | ||
|
||
--- | ||
# Support | ||
Your generous donations help sustain and improve this project. Here's why supporting us is important: | ||
1. **Development and Maintenance**: Donations enable us to dedicate more time and resources to developing new features, fixing bugs, and maintaining the project's overall health. Your support directly contributes to the project's ongoing improvement and sustainability. | ||
2. **Community Support**: Your contributions show your support for the project and help foster a thriving community around it. Your generosity motivates us to keep pushing the project forward and encourages others to join the cause. | ||
3. **Open Source Sustainability**: By supporting open-source projects like ours, you're contributing to the sustainability of the entire open-source ecosystem. Your donations help ensure that valuable projects remain accessible to everyone. | ||
|
||
Every donation, no matter how small, makes a big difference. Thank you for considering supporting us!<br><br> | ||
<a href="https://www.buymeacoffee.com/antoniowar" target="_blank"><img src="https://github.com/appcraftstudio/buymeacoffee/raw/master/Images/snapshot-bmc-button.png" alt="Buy Me A Coffee" height="40"></a> | ||
|
||
--- | ||
# License | ||
SwiftyNetworking is published under the MIT license. |
34 changes: 34 additions & 0 deletions
34
Sources/SwiftyNetworking/Clients/SwiftyNetworkingClient.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// | ||
// SwiftyNetworkingClient.swift | ||
// | ||
// | ||
// Created by Antonio Guerra on 01/08/24. | ||
// | ||
|
||
import Foundation | ||
|
||
public actor SwiftyNetworkingClient { | ||
private let delegate: SwiftyNetworkingDelegate = SwiftyNetworkingDelegate() | ||
private let configuration: URLSessionConfiguration | ||
private let session: URLSession | ||
|
||
public init(configuration: URLSessionConfiguration = URLSessionConfiguration.default) { | ||
self.configuration = configuration | ||
self.session = URLSession(configuration: configuration, delegate: delegate) | ||
} | ||
|
||
public func send(request: SwiftyNetworkingRequest) async throws -> SwiftyNetworkingResponse { | ||
let underlyingRequest = try request.underlyingRequest | ||
let (body, underlyingResponse) = try await session.data(for: underlyingRequest) | ||
let metrics = delegate.metrics(for: underlyingRequest) | ||
guard let underlyingResponse = underlyingResponse as? HTTPURLResponse else { | ||
throw URLError(.cannotParseResponse) | ||
} | ||
return SwiftyNetworkingResponse( | ||
body: body, | ||
source: metrics.source, | ||
duration: metrics.duration, | ||
underlyingResponse: underlyingResponse | ||
) | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
Sources/SwiftyNetworking/Delegates/SwiftyNetworkingDelegate.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// | ||
// SwiftyNetworkingDelegate.swift | ||
// | ||
// | ||
// Created by Antonio Guerra on 01/08/24. | ||
// | ||
|
||
import Foundation | ||
|
||
class SwiftyNetworkingDelegate: NSObject, URLSessionTaskDelegate { | ||
private var metrics: [Int: URLSessionTaskTransactionMetrics] = [:] | ||
|
||
func metrics(for request: URLRequest) -> SwiftyNetworkingMetrics { | ||
guard let metrics = metrics[request.hashValue] else { | ||
return (.network, 0) | ||
} | ||
let source = SwiftyNetworkingSource(resourceFetchType: metrics.resourceFetchType) | ||
let duration = metrics.responseEndDate?.timeIntervalSince(metrics.requestStartDate ?? Date()) ?? 0.0 | ||
return (source, duration) | ||
} | ||
|
||
func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) { | ||
for metrics in metrics.transactionMetrics { | ||
self.metrics[metrics.request.hashValue] = metrics | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// | ||
// URLSession+.swift | ||
// | ||
// | ||
// Created by Antonio Guerra on 01/08/24. | ||
// | ||
|
||
import Foundation | ||
|
||
extension URLSession { | ||
convenience init(configuration: URLSessionConfiguration, delegate: (any URLSessionDelegate)) { | ||
self.init(configuration: configuration, delegate: delegate, delegateQueue: nil) | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
Sources/SwiftyNetworking/Models/SwiftyNetworkingCachePolicy.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// | ||
// SwiftyNetworkingCachePolicy.swift | ||
// | ||
// | ||
// Created by Antonio Guerra on 02/08/24. | ||
// | ||
|
||
import Foundation | ||
|
||
public enum SwiftyNetworkingCachePolicy: String, Equatable, Hashable, Sendable { | ||
case reloadIgnoringCacheData | ||
case returnCacheDataElseLoad | ||
case returnCacheDataDontLoad | ||
|
||
var underlyingCachePolicy: NSURLRequest.CachePolicy { | ||
switch self { | ||
case .reloadIgnoringCacheData: | ||
return .reloadIgnoringLocalCacheData | ||
case .returnCacheDataElseLoad: | ||
return .returnCacheDataElseLoad | ||
case .returnCacheDataDontLoad: | ||
return .returnCacheDataDontLoad | ||
} | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
Sources/SwiftyNetworking/Models/SwiftyNetworkingMethod.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// | ||
// SwiftyNetworkingMethod.swift | ||
// | ||
// | ||
// Created by Antonio Guerra on 01/08/24. | ||
// | ||
|
||
import Foundation | ||
|
||
public enum SwiftyNetworkingMethod: String, Equatable, Hashable, Sendable { | ||
case connect | ||
case delete | ||
case get | ||
case head | ||
case options | ||
case patch | ||
case post | ||
case put | ||
case trace | ||
} |
84 changes: 84 additions & 0 deletions
84
Sources/SwiftyNetworking/Models/SwiftyNetworkingRequest.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
// | ||
// SwiftyNetworkingRequest.swift | ||
// | ||
// | ||
// Created by Antonio Guerra on 01/08/24. | ||
// | ||
|
||
import Foundation | ||
|
||
public struct SwiftyNetworkingRequest: Identifiable, Hashable, Sendable { | ||
public let id: UUID | ||
public let endpoint: String | ||
public let path: String | ||
public let method: SwiftyNetworkingMethod | ||
public let headers: [String: String] | ||
public let body: Data? | ||
public let parameters: [String: String] | ||
public let cachePolicy: SwiftyNetworkingCachePolicy | ||
public let timeout: TimeInterval | ||
|
||
public init( | ||
id: UUID = UUID(), | ||
endpoint: String, | ||
path: String = "/", | ||
method: SwiftyNetworkingMethod = .get, | ||
headers: [String: String] = [:], | ||
body: Data? = nil, | ||
parameters: [String: Any] = [:], | ||
cachePolicy: SwiftyNetworkingCachePolicy = .returnCacheDataElseLoad, | ||
timeout: TimeInterval = 60 | ||
) { | ||
self.id = id | ||
self.endpoint = endpoint | ||
self.path = path | ||
self.method = method | ||
self.headers = headers | ||
self.body = body | ||
self.parameters = parameters.reduce(into: [String: String]()) { result, parameter in | ||
result[parameter.key] = String(describing: parameter.value) | ||
} | ||
self.cachePolicy = cachePolicy | ||
self.timeout = timeout | ||
} | ||
|
||
var url: URL { | ||
get throws { | ||
guard let endpoint = URL(string: endpoint) else { | ||
throw URLError(.badURL) | ||
} | ||
|
||
guard let scheme = endpoint.scheme, SwiftyNetworkingScheme(rawValue: scheme) != nil else { | ||
throw URLError(.badURL) | ||
} | ||
|
||
guard let url = URL(string: path, relativeTo: endpoint), var components = URLComponents(string: url.absoluteString) else { | ||
throw URLError(.badURL) | ||
} | ||
|
||
guard !parameters.isEmpty else { | ||
return url | ||
} | ||
|
||
components.queryItems = parameters.map { (key, value) in | ||
URLQueryItem(name: key, value: value) | ||
} | ||
|
||
guard let url = components.url else { | ||
throw URLError(.badURL) | ||
} | ||
|
||
return url | ||
} | ||
} | ||
|
||
var underlyingRequest: URLRequest { | ||
get throws { | ||
var request = try URLRequest(url: url, cachePolicy: cachePolicy.underlyingCachePolicy, timeoutInterval: timeout) | ||
request.httpMethod = method.rawValue.uppercased() | ||
request.httpBody = body | ||
request.allHTTPHeaderFields = headers | ||
return request | ||
} | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
Sources/SwiftyNetworking/Models/SwiftyNetworkingResponse.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// | ||
// SwiftyNetworkingResponse.swift | ||
// | ||
// | ||
// Created by Antonio Guerra on 01/08/24. | ||
// | ||
|
||
import Foundation | ||
|
||
public struct SwiftyNetworkingResponse: Identifiable, Hashable, Sendable { | ||
public let id: UUID | ||
public let body: Data | ||
public let status: Int | ||
public let headers: [String: String] | ||
public let source: SwiftyNetworkingSource | ||
public let duration: TimeInterval | ||
|
||
init(id: UUID = UUID(), body: Data, source: SwiftyNetworkingSource, duration: TimeInterval, underlyingResponse: HTTPURLResponse) { | ||
self.id = id | ||
self.body = body | ||
self.status = underlyingResponse.statusCode | ||
self.headers = underlyingResponse.allHeaderFields.reduce(into: [String: String]()) { result, header in | ||
if let name = header.key as? String, let value = header.value as? String { | ||
result[name] = value | ||
} | ||
} | ||
self.source = source | ||
self.duration = duration | ||
self.underlyingResponse = underlyingResponse | ||
} | ||
|
||
var underlyingResponse: HTTPURLResponse | ||
} |
13 changes: 13 additions & 0 deletions
13
Sources/SwiftyNetworking/Models/SwiftyNetworkingScheme.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// | ||
// SwiftyNetworkingScheme.swift | ||
// | ||
// | ||
// Created by Antonio Guerra on 01/08/24. | ||
// | ||
|
||
import Foundation | ||
|
||
public enum SwiftyNetworkingScheme: String, Equatable, Hashable, Sendable { | ||
case http | ||
case https | ||
} |
22 changes: 22 additions & 0 deletions
22
Sources/SwiftyNetworking/Models/SwiftyNetworkingSource.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// | ||
// SwiftyNetworkingSource.swift | ||
// | ||
// | ||
// Created by Antonio Guerra on 02/08/24. | ||
// | ||
|
||
import Foundation | ||
|
||
public enum SwiftyNetworkingSource: String, Equatable, Hashable, Sendable { | ||
case network | ||
case cache | ||
|
||
init(resourceFetchType: URLSessionTaskMetrics.ResourceFetchType) { | ||
switch resourceFetchType { | ||
case .localCache: | ||
self = .cache | ||
default: | ||
self = .network | ||
} | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.