Skip to content

Commit aad6553

Browse files
committed
Implement documentation
1 parent 102b484 commit aad6553

14 files changed

Lines changed: 285 additions & 19 deletions

File tree

Sources/NetworkLayer/Classes/Core/Authentification/AuthenticatorInterceptor.swift renamed to Sources/NetworkLayer/Classes/Core/Authentification/AuthenticationInterceptor.swift

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ import Atomic
77
import Foundation
88
import NetworkLayerInterfaces
99

10-
/// A custom AuthenticatorInterceptor implementation that works with a specific type
10+
/// A custom AuthenticationInterceptor implementation that works with a specific type
1111
/// of Authenticator conforming to the IAuthenticator protocol.
12-
public final class AuthenticatorInterceptor<Authenticator: IAuthenticator>: IAuthenticatorInterceptor {
12+
public final class AuthenticationInterceptor<Authenticator: IAuthenticator>: IAuthenticationInterceptor {
1313
// MARK: Types
1414

1515
public typealias Credential = Authenticator.Credential
@@ -21,13 +21,23 @@ public final class AuthenticatorInterceptor<Authenticator: IAuthenticator>: IAut
2121

2222
// MARK: Initialization
2323

24+
/// Creates a new instance of `AuthenticationInterceptor`.
25+
///
26+
/// - Parameters:
27+
/// - authenticator: The authenticator.
28+
/// - credential: The credential.
2429
public init(authenticator: Authenticator, credential: Credential? = nil) {
2530
self.authenticator = authenticator
2631
self.credential = credential
2732
}
2833

2934
// MARK: IAuthentificatorInterceptor
3035

36+
/// Adapts the request with credentials.
37+
///
38+
/// - Parameters:
39+
/// - request: The URLRequest to be adapted.
40+
/// - session: The URLSession for which the request is being adapted.
3141
public func adapt(request: inout URLRequest, for session: URLSession) async throws {
3242
guard let credential else {
3343
throw AuthenticatorInterceptorError.missingCredential
@@ -40,6 +50,11 @@ public final class AuthenticatorInterceptor<Authenticator: IAuthenticator>: IAut
4050
}
4151
}
4252

53+
/// Refreshes credential for the request.
54+
///
55+
/// - Parameters:
56+
/// - request: The URLRequest to be refreshed.
57+
/// - session: The URLSession for which the request is being refreshed.
4358
public func refresh(
4459
_ request: URLRequest,
4560
with response: HTTPURLResponse,
@@ -60,6 +75,13 @@ public final class AuthenticatorInterceptor<Authenticator: IAuthenticator>: IAut
6075
try await refresh(credential, for: session)
6176
}
6277

78+
/// Determines whether a request requires a credential refresh.
79+
///
80+
/// - Parameters:
81+
/// - request: The URLRequest to check.
82+
/// - response: The HTTPURLResponse received for the request.
83+
///
84+
/// - Returns: A boolean indicating whether a credential refresh is required.
6385
public func isRequireRefresh(_ request: URLRequest, response: HTTPURLResponse) -> Bool {
6486
authenticator.didRequest(request, with: response)
6587
}

Sources/NetworkLayer/Classes/Core/Services/RequestProcessor/RequestProcessor.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ actor RequestProcessor {
2424
/// The retry policy service.
2525
private let retryPolicyService: IRetryPolicyService
2626
/// The authenticator interceptor.
27-
private let interceptor: IAuthenticatorInterceptor?
27+
private let interceptor: IAuthenticationInterceptor?
2828
/// The delegate.
2929
private weak var delegate: RequestProcessorDelegate?
3030

@@ -43,7 +43,7 @@ actor RequestProcessor {
4343
dataRequestHandler: any IDataRequestHandler,
4444
retryPolicyService: IRetryPolicyService,
4545
delegate: RequestProcessorDelegate?,
46-
interceptor: IAuthenticatorInterceptor?
46+
interceptor: IAuthenticationInterceptor?
4747
) {
4848
self.configuration = configuration
4949
self.requestBuilder = requestBuilder

Sources/NetworkLayer/Classes/DI/NetworkLayerAssembly.swift

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,23 @@ public final class NetworkLayerAssembly: INetworkLayerAssembly {
1717
/// The request processor delegate.
1818
private let delegate: RequestProcessorDelegate?
1919
/// The authenticator interceptor.
20-
private let interceptor: IAuthenticatorInterceptor?
20+
private let interceptor: IAuthenticationInterceptor?
2121
/// The json encoder.
2222
private let jsonEncoder: JSONEncoder
2323

2424
// MARK: Initialization
2525

2626
public init(
27-
configure: Configuration,
28-
retryPolicyStrategy: RetryPolicyStrategy?,
29-
delegate: RequestProcessorDelegate?,
30-
interceptor: IAuthenticatorInterceptor?,
31-
jsonEncoder: JSONEncoder
27+
configure: Configuration = .init(
28+
sessionConfiguration: .default,
29+
sessionDelegate: nil,
30+
sessionDelegateQueue: nil,
31+
jsonDecoder: JSONDecoder()
32+
),
33+
retryPolicyStrategy: RetryPolicyStrategy? = nil,
34+
delegate: RequestProcessorDelegate? = nil,
35+
interceptor: IAuthenticationInterceptor? = nil,
36+
jsonEncoder: JSONEncoder = JSONEncoder()
3237
) {
3338
self.configure = configure
3439
self.retryPolicyStrategy = retryPolicyStrategy
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Authentication
2+
3+
Learn how to implement authentication.
4+
5+
## Overview
6+
7+
The `network-layer` includes an ``AuthenticationInterceptor`` responsible for handling authentication options.
8+
9+
## Access Tokens
10+
11+
``AuthenticationInterceptor`` requires passing an `IAuthenticator` as initialization parameters that contain logic for updating the access token.
12+
13+
A credential object must conform to `IAuthenticationCredential` protocol that indicates whether the credential is valid.
14+
15+
```swift
16+
import NetworkLayerInterfaces
17+
18+
// Defines a credential model
19+
struct Credential: IAuthenticationCredential {
20+
let expires: Date
21+
let requiresRefresh: Bool { expires < Date() }
22+
}
23+
```
24+
25+
Define a `Authenticator` object that confrorms to `IAuthenticator` and implement your own logic for validation and refreshing an access token.
26+
27+
```swift
28+
import NetworkLayerInterfaces
29+
30+
struct Authenticator: IAuthenticator {
31+
32+
/// Applies the `Credential` to the `URLRequest`.
33+
///
34+
/// - Parameters:
35+
/// - credential: The `Credential`.
36+
/// - urlRequest: The `URLRequest`.
37+
func apply(_ credential: Credential, to urlRequest: URLRequest) async throws {
38+
request.addValue("Bearer <token>", forHTTPHeaderField: "Authorization")
39+
}
40+
41+
/// Refreshes the `Credential`.
42+
///
43+
/// - Parameters:
44+
/// - credential: The `Credential` to refresh.
45+
/// - session: The `URLSession` requiring the refresh.
46+
func refresh(_ credential: Credential, for session: URLSession) async throws -> Credential {
47+
// Token refresh logic here
48+
}
49+
50+
/// Determines whether the `URLRequest` failed due to an authentication error based on the `HTTPURLResponse`.
51+
///
52+
/// - Parameters:
53+
/// - urlRequest: The `URLRequest`.
54+
/// - response: The `HTTPURLResponse`.
55+
///
56+
/// - Returns: `true` if the `URLRequest` failed due to an authentication error, `false` otherwise.
57+
func didRequest(_ urlRequest: URLRequest, with response: HTTPURLResponse) -> Bool {
58+
response.statusCode == 401
59+
}
60+
61+
/// Determines whether the `URLRequest` is authenticated with the `Credential`.
62+
///
63+
/// - Parameters:
64+
/// - urlRequest: The `URLRequest`.
65+
/// - credential: The `Credential`.
66+
///
67+
/// - Returns: `true` if the `URLRequest` is authenticated with the `Credential`, `false` otherwise.
68+
func isRequest(_ urlRequest: URLRequest, authenticatedWith credential: Credential) -> Bool {
69+
true
70+
}
71+
}
72+
```
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Getting Started with Network Layer
2+
3+
## Defining a Request
4+
5+
Before sending a request to a web server, it is necessary to define a request model. For this, define a new `struct` object that conforms to `IRequest` protocol.
6+
7+
```swift
8+
import NetworkLayerInterfaces
9+
10+
struct UserRequest: IRequest {
11+
// MARK: Properties
12+
13+
private let id: Int
14+
15+
// MARK: Initialization
16+
17+
init(id: Int) {
18+
self.id = id
19+
}
20+
21+
// MARK: IRequest
22+
23+
/// The base `URL` for the resource.
24+
var domainName: String {
25+
"https://example.com"
26+
}
27+
28+
/// The endpoint path.
29+
var path: String {
30+
"user"
31+
}
32+
33+
/// A dictionary that contains the parameters to be encoded into the request.
34+
var parameters: [String: String]? {
35+
["user_id": id]
36+
}
37+
38+
/// A Boolean value indicating whether authentication is required.
39+
var requiresAuthentication: Bool {
40+
true
41+
}
42+
43+
/// The HTTP method.
44+
var httpMethod: HTTPMethod {
45+
.get
46+
}
47+
}
48+
```
49+
50+
## Defining a Response Model
51+
52+
While the `network-layer` returns a `Response<T>` object that expects a decodable object, it is necessary to define a response model.
53+
54+
```swift
55+
import NetworkLayerInterfaces
56+
57+
struct UserResponse: Decodable {
58+
let id: Int
59+
let userName: String
60+
}
61+
```
62+
63+
## Usage
64+
65+
```swift
66+
import NetworkLayerInterfaces
67+
68+
let request = UserRequest(id: 1)
69+
70+
do {
71+
let user = try await requestProcessor.send(request)
72+
} catch {
73+
// Catch an error here
74+
}
75+
76+
```
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Retry
2+
3+
Learn how to retry failed requests.
4+
5+
## Overview
6+
7+
The `network-layer` is implemented using the `Typhoon` framework to handle the retrying of failed requests. You can read more about `Typhoon` framework [here](https://github.com/space-code/typhoon/).
8+
9+
## Retrying Failed Requests
10+
11+
By default, the `network-layer` attempts to resend a failed request five times. If you wish to customize this behavior, you can pass the desired value to an assembly of the `RequestProcessor`.
12+
13+
```swift
14+
import NetworkLayer
15+
import NetworkLayerInterfaces
16+
17+
let requestProcessor = NetworkLayerAssembly.assemble(retryPolicyStrategy: .constant(retry: 10, duration: .seconds(1)))
18+
```
19+
20+
> Tip: `typhoon` framework provides different strategies for retrying failed request. You can read more [here](https://github.com/space-code/typhoon).
21+
22+
This behavior will be applied to all future requests.
23+
24+
In case you desire to customize a particular request, you can pass the desired strategy to that specific request:
25+
26+
```swift
27+
import NetworkLayerInterfaces
28+
29+
let request = UserRequest(id: 1)
30+
let user: Response<User> = try await requestProcessor.send(request, strategy: .constant(retry: 10, duration: .seconds(1)))
31+
```
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# ``NetworkLayer``
2+
3+
The library for network communication.
4+
5+
## Overview
6+
7+
The `network-layer` provides a simple interface for communication, making it very easy to send a request to a web server.
8+
9+
```swift
10+
import NetworkLayer
11+
12+
let requestProcessor = NetworkLayerAssembly().assemble()
13+
let user: User = try await requestProcessor.send(request)
14+
```
15+
16+
The `network-layer` separates into two modules: `NetworkLayer`, which contains core functionality, and `NetworkLayerInterfaces`, which only contains public protocols for this framework.
17+
18+
The library supports authentication, retrying requests, and more.
19+
20+
## License
21+
22+
network-layer is available under the MIT license. See the LICENSE file for more info.
23+
24+
## Topics
25+
26+
### Essentials
27+
28+
- <doc:GettingStarted>
29+
- <doc:Authentication>
30+
- <doc:Retry>
31+
32+
<!--### Network Layer Creation-->
33+
<!---->
34+
<!--- ``INetworkLayerAssembly``-->
35+
<!---->
36+
<!--### Request and Response Models-->
37+
<!---->
38+
<!--- ``Configuration``-->
39+
<!--- ``HTTPMethod``-->
40+
<!--- ``RequestBody``-->
41+
<!--- ``IRequest``-->
42+
<!--- ``Response``-->
43+
<!---->
44+
<!--### Errors-->
45+
<!---->
46+
<!--- ``NetworkLayerError``-->
47+
<!--- ``AuthenticatorInterceptorError``-->
48+
<!---->
49+
<!--### Authentication-->
50+
<!---->
51+
<!--- ``IAuthenticationCredential``-->
52+
<!--- ``IAuthenticationInterceptor``-->
53+
<!--- ``IAuthenticator``-->
54+
<!---->
55+
<!--### Services-->
56+
<!---->
57+
<!--- ``IDataRequestHandler``-->
58+
<!--- ``IRequestBuilder``-->
59+
<!--- ``IRequestProcessor``-->
60+
<!--- ``RequestProcessorDelegate``-->

Sources/NetworkLayerInterfaces/Classes/Core/Authenticator/AuthenticatorInterceptorError.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import Foundation
77

8-
/// `AuthenticatorInterceptorError` is the error type returned by AuthenticatorInterceptor.
8+
/// `AuthenticatorInterceptorError` is the error type returned by AuthenticationInterceptor.
99
public enum AuthenticatorInterceptorError: Swift.Error {
1010
/// The credential was not found.
1111
case missingCredential

Sources/NetworkLayerInterfaces/Classes/Core/Authenticator/IAuthenticatorInterceptor.swift renamed to Sources/NetworkLayerInterfaces/Classes/Core/Authenticator/IAuthenticationInterceptor.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import Foundation
77

88
/// A type defines the authenticator interceptor interface.
9-
public protocol IAuthenticatorInterceptor {
9+
public protocol IAuthenticationInterceptor {
1010
/// Adapts the request with credentials.
1111
///
1212
/// - Parameters:

Sources/NetworkLayerInterfaces/Classes/DI/INetworkLayerAssembly.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public protocol INetworkLayerAssembly {
2222
configure: Configuration,
2323
retryPolicyStrategy: RetryPolicyStrategy?,
2424
delegate: RequestProcessorDelegate?,
25-
interceptor: IAuthenticatorInterceptor?,
25+
interceptor: IAuthenticationInterceptor?,
2626
jsonEncoder: JSONEncoder
2727
)
2828

0 commit comments

Comments
 (0)