-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for request interceptors (#119)
* add prototype for request interceptors * remove runway prints * Change Interceptor -> InterceptorList and RequestInterceptor -> Interceptor Remove request level interceptors de-duplicate finalize request data calls * remove request level interceptors add a bunch of documentation, examples, etc for interceptors * code clean up
- Loading branch information
1 parent
920c0e9
commit fb67817
Showing
10 changed files
with
253 additions
and
18 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
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
File renamed without changes.
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
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,21 @@ | ||
// | ||
// AdaptedRequest.swift | ||
// Netable | ||
// | ||
// Created by Brendan Lensink on 2023-06-09. | ||
// Copyright © 2023 Steamclock Software. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
/// Container for the result of `Interceptor.adapt`. | ||
public enum AdaptedRequest: Sendable { | ||
/// The original URLRequest was modified and the new result should be used instead. | ||
case changed(URLRequest) | ||
|
||
/// The original request should be switched out for a local file resource. | ||
case mocked(URL) | ||
|
||
/// The original request was not modified in any way. | ||
case notChanged | ||
} |
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,23 @@ | ||
// | ||
// Interceptor.swift | ||
// Netable | ||
// | ||
// Created by Brendan Lensink on 2023-06-09. | ||
// Copyright © 2023 Steamclock Software. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
/** | ||
* Interceptors are applied to each request in the given `Netable` instance prior to performing the request. | ||
*/ | ||
public protocol Interceptor: Sendable { | ||
/** | ||
* Adapts the provided URLRequest, returning a modified copy changed in one of three potentional ways: | ||
* - No changes are made, the request proceeds as normal. | ||
* - The request has been modified in some way before sending. How it has been modified is left to the user to determine. | ||
* - The request has been switched with a mocked resource JSON. | ||
* | ||
*/ | ||
func adapt(_ request: URLRequest, instance: Netable) async throws -> AdaptedRequest | ||
} |
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,66 @@ | ||
// | ||
// Interceptor.swift | ||
// Netable | ||
// | ||
// Created by Brendan Lensink on 2023-06-06. | ||
// Copyright © 2023 Steamclock Software. All rights reserved. | ||
// | ||
|
||
|
||
import Foundation | ||
|
||
/// Container struct for interceptors. | ||
public struct InterceptorList: Sendable { | ||
let interceptors: [Interceptor] | ||
|
||
/** | ||
* Create a new interceptor list with a set of interceptors. | ||
* | ||
* - parameter interceptors: The interceptors that will be applied to each request. | ||
*/ | ||
public init(_ interceptors: [Interceptor]) { | ||
self.interceptors = interceptors | ||
} | ||
|
||
/** | ||
* Create a new interceptor list with a single interceptor. | ||
* | ||
* - parameter interceptor: The interceptor that will be applied to each request. | ||
*/ | ||
public init(_ interceptor: Interceptor) { | ||
self.interceptors = [interceptor] | ||
} | ||
|
||
/** | ||
* Apply all intereceptors to the given request. | ||
* Interceptors are applied in the order they were passed into the `InterceptorList` constructor, | ||
* except unless a mocked result is found, it will return immedediately. | ||
* | ||
* - parameter request: The request to apply interceptors to. | ||
* - parameter instance: A reference to the Netable instance that is applying these interceptors. | ||
*/ | ||
public func applyInterceptors(request: URLRequest, instance: Netable) async throws -> AdaptedRequest { | ||
var adaptedURLRequest: URLRequest? | ||
|
||
for interceptor in interceptors { | ||
let result = try await interceptor.adapt(adaptedURLRequest ?? request, instance: instance) | ||
switch result { | ||
case .changed(let newResult): | ||
adaptedURLRequest = newResult | ||
case .mocked(let mockedUrl): | ||
if !mockedUrl.isFileURL { | ||
throw NetableError.interceptorError("Only file URLs are supported for mocking URLs") | ||
} | ||
|
||
return AdaptedRequest.mocked(mockedUrl) | ||
case .notChanged: continue | ||
} | ||
} | ||
|
||
if let adapted = adaptedURLRequest { | ||
return AdaptedRequest.changed(adapted) | ||
} | ||
|
||
return .notChanged | ||
} | ||
} |
Oops, something went wrong.