Compare commits
17 Commits
Author | SHA1 | Date |
---|---|---|
![]() |
89e8d109f3 | |
![]() |
6f014c3ff6 | |
![]() |
f270e16c6f | |
![]() |
aed7af9dd3 | |
![]() |
65a4a05ac0 | |
![]() |
e228e4beb3 | |
![]() |
792c159774 | |
![]() |
7e99ee5a65 | |
![]() |
7f323ec75c | |
![]() |
87fd31b2ea | |
![]() |
79db02c391 | |
![]() |
c72de279d3 | |
![]() |
22e8b5dfe4 | |
![]() |
1b9d653e57 | |
![]() |
bbaff73a60 | |
![]() |
c2245892ce | |
![]() |
b489bbd69b |
|
@ -1,4 +1,4 @@
|
|||
// swift-tools-version:5.0
|
||||
// swift-tools-version:5.3
|
||||
|
||||
import PackageDescription
|
||||
|
||||
|
@ -8,8 +8,16 @@ let package = Package(
|
|||
.macOS(.v10_11),
|
||||
],
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/kylef/PathKit", from: "1.0.0"),
|
||||
.package(url: "https://github.com/XCEssentials/RepoConfigurator", from: "3.0.0")
|
||||
.package(
|
||||
name: "PathKit",
|
||||
url: "https://github.com/kylef/PathKit",
|
||||
from: "1.0.0"
|
||||
),
|
||||
.package(
|
||||
name: "XCERepoConfigurator",
|
||||
url: "https://github.com/XCEssentials/RepoConfigurator",
|
||||
from: "3.0.0"
|
||||
)
|
||||
],
|
||||
targets: [
|
||||
.target(
|
||||
|
|
|
@ -11,7 +11,7 @@ print("--- BEGIN of '\(Executable.name)' script ---")
|
|||
|
||||
// MARK: Parameters
|
||||
|
||||
Spec.BuildSettings.swiftVersion.value = "5.0"
|
||||
Spec.BuildSettings.swiftVersion.value = "5.3"
|
||||
|
||||
let localRepo = try Spec.LocalRepo.current()
|
||||
|
||||
|
|
|
@ -16,8 +16,7 @@ git:
|
|||
language: objective-c # fine for Swift as well
|
||||
|
||||
osx_image:
|
||||
- xcode10.2
|
||||
- xcode11
|
||||
- xcode12
|
||||
|
||||
before_script:
|
||||
# cd ./.setup && swift run && cd ./.. # RUN this manually!
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// swift-tools-version:5.0
|
||||
// swift-tools-version:5.3
|
||||
|
||||
import PackageDescription
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[](LICENSE)
|
||||
[](https://github.com/XCEssentials/APIClient/tags)
|
||||
[](Package.swift)
|
||||
[](https://swift.org)
|
||||
[](https://swift.org)
|
||||
[](Package.swift)
|
||||
[](https://travis-ci.com/XCEssentials/APIClient)
|
||||
|
||||
|
|
|
@ -39,20 +39,15 @@ struct BasicURLRequestFacilitator: URLRequestFacilitator
|
|||
public
|
||||
let sharedPrefixURL: URL
|
||||
|
||||
public
|
||||
let onEncodeRequest: OnEncodeRequest
|
||||
|
||||
// MARK: - Initializers
|
||||
|
||||
public
|
||||
init(
|
||||
sharedPrefixURL: URL,
|
||||
session: URLSession = .shared,
|
||||
onConfigureRequest: @escaping OnEncodeRequest = URLEncoding.default.encode
|
||||
session: URLSession = .shared
|
||||
)
|
||||
{
|
||||
self.sharedPrefixURL = sharedPrefixURL
|
||||
self.session = session
|
||||
self.onEncodeRequest = onConfigureRequest
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,10 @@ struct RequestEncodingIssue: URLRequestFacilitatorError
|
|||
|
||||
public
|
||||
enum PrepareRequestIssue: URLRequestFacilitatorError
|
||||
{
|
||||
{
|
||||
case conversionIntoDataFailed(Error)
|
||||
case conversionDataIntoJSONObjectFailed(Error)
|
||||
case conversionJSONObjectIntoDictionaryFailed(theObject: Any)
|
||||
case invalidRelativePath(String)
|
||||
case requestEncodingFailed(RequestEncodingIssue)
|
||||
}
|
||||
|
|
|
@ -28,11 +28,6 @@ import Foundation
|
|||
|
||||
//---
|
||||
|
||||
public
|
||||
typealias OnEncodeRequest = (URLRequest, Parameters?) -> Result<URLRequest, RequestEncodingIssue>
|
||||
|
||||
//---
|
||||
|
||||
public
|
||||
enum HTTPHeaderFieldName: String
|
||||
{
|
||||
|
|
|
@ -24,48 +24,37 @@
|
|||
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
|
||||
//---
|
||||
|
||||
public
|
||||
protocol RequestDefinition
|
||||
protocol RequestDefinition: Encodable
|
||||
{
|
||||
static
|
||||
var relativePath: String { get }
|
||||
|
||||
static
|
||||
var method: HTTPMethod? { get }
|
||||
|
||||
static
|
||||
var parameterEncoding: ParameterEncoding { get }
|
||||
|
||||
static
|
||||
var toDataConverter: (Self) throws -> Data { get }
|
||||
|
||||
static
|
||||
var dataToDictionaryConversionOptions: JSONSerialization.ReadingOptions { get }
|
||||
}
|
||||
|
||||
//---
|
||||
|
||||
public
|
||||
extension RequestDefinition {
|
||||
|
||||
/// Parameters for the corresponding URL request.
|
||||
var parameters: Parameters {
|
||||
extension RequestDefinition
|
||||
{
|
||||
static
|
||||
var toDataConverter: (Self) throws -> Data { JSONEncoder().encode }
|
||||
|
||||
Mirror
|
||||
.init(reflecting: self)
|
||||
.children
|
||||
.compactMap{
|
||||
|
||||
(child: (label: String?, value: Any)) -> (key: String, value: Any)? in
|
||||
|
||||
//---
|
||||
|
||||
if
|
||||
let key = child.label
|
||||
{
|
||||
return (key, child.value)
|
||||
}
|
||||
else
|
||||
{
|
||||
return nil
|
||||
}
|
||||
}
|
||||
.reduce(into: [:]) {
|
||||
|
||||
result, nextItem in
|
||||
|
||||
//---
|
||||
|
||||
result[nextItem.key] = nextItem.value
|
||||
}
|
||||
}
|
||||
static
|
||||
var dataToDictionaryConversionOptions: JSONSerialization.ReadingOptions { .init() }
|
||||
}
|
||||
|
|
|
@ -34,18 +34,73 @@ protocol URLRequestFacilitator
|
|||
var session: URLSession { get }
|
||||
|
||||
var sharedPrefixURL: URL { get }
|
||||
|
||||
var onEncodeRequest: OnEncodeRequest { get }
|
||||
}
|
||||
|
||||
// MARK: - Internal methods
|
||||
// MARK: - Commands - Public
|
||||
|
||||
public
|
||||
extension URLRequestFacilitator
|
||||
{
|
||||
func prepareRequest<R: RequestDefinition>(
|
||||
from definition: R
|
||||
) -> Result<URLRequest, PrepareRequestIssue>
|
||||
{
|
||||
let parametersData: Data
|
||||
|
||||
do
|
||||
{
|
||||
parametersData = try R.toDataConverter(definition)
|
||||
}
|
||||
catch
|
||||
{
|
||||
return .failure(.conversionIntoDataFailed(error))
|
||||
}
|
||||
|
||||
//---
|
||||
|
||||
let parametersObject: Any
|
||||
|
||||
do
|
||||
{
|
||||
parametersObject = try JSONSerialization
|
||||
.jsonObject(
|
||||
with: parametersData,
|
||||
options: R.dataToDictionaryConversionOptions
|
||||
)
|
||||
}
|
||||
catch
|
||||
{
|
||||
return .failure(.conversionDataIntoJSONObjectFailed(error))
|
||||
}
|
||||
|
||||
//---
|
||||
|
||||
guard
|
||||
let parameters = parametersObject as? Parameters
|
||||
else
|
||||
{
|
||||
return .failure(.conversionJSONObjectIntoDictionaryFailed(theObject: parametersObject))
|
||||
}
|
||||
|
||||
//---
|
||||
|
||||
return prepareRequest(
|
||||
R.method,
|
||||
relativePath: R.relativePath,
|
||||
parameterEncoding: R.parameterEncoding,
|
||||
parameters: parameters
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Internal methods
|
||||
|
||||
extension URLRequestFacilitator
|
||||
{
|
||||
func prepareRequest(
|
||||
_ method: HTTPMethod? = nil,
|
||||
relativePath: String,
|
||||
parameterEncoding: ParameterEncoding,
|
||||
parameters: Parameters? = nil
|
||||
) -> Result<URLRequest, PrepareRequestIssue>
|
||||
{
|
||||
|
@ -64,7 +119,7 @@ extension URLRequestFacilitator
|
|||
var result = URLRequest(url: targetURL)
|
||||
result.httpMethod = method?.rawValue
|
||||
|
||||
switch onEncodeRequest(result, parameters)
|
||||
switch parameterEncoding.encode(result, with: parameters)
|
||||
{
|
||||
case .success(let output):
|
||||
return .success(output)
|
||||
|
@ -73,15 +128,4 @@ extension URLRequestFacilitator
|
|||
return .failure(.requestEncodingFailed(error))
|
||||
}
|
||||
}
|
||||
|
||||
func prepareRequest(
|
||||
for definition: RequestDefinition
|
||||
) -> Result<URLRequest, PrepareRequestIssue>
|
||||
{
|
||||
prepareRequest(
|
||||
type(of: definition).method,
|
||||
relativePath: type(of: definition).relativePath,
|
||||
parameters: definition.parameters
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,24 @@ class RequestDefinitionTests: XCTestCase
|
|||
static
|
||||
let method: HTTPMethod? = .get
|
||||
|
||||
static
|
||||
let parameterEncoding: ParameterEncoding = URLEncoding.default
|
||||
|
||||
let id: String
|
||||
|
||||
var optionalFlag: Int? = nil
|
||||
}
|
||||
|
||||
var facilitator: URLRequestFacilitator!
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
facilitator = BasicURLRequestFacilitator(sharedPrefixURL: .init(string: "host.com")!)
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
facilitator = nil
|
||||
super.tearDown()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,12 +41,26 @@ class RequestDefinitionTests: XCTestCase
|
|||
|
||||
extension RequestDefinitionTests
|
||||
{
|
||||
func test_buildParameters()
|
||||
func test_buildParameters_withoutOptional()
|
||||
{
|
||||
let sut = UserRequestDefinition(id: "123").parameters
|
||||
let definition = UserRequestDefinition(id: "123")
|
||||
let request = try! facilitator.prepareRequest(from: definition).get()
|
||||
let components = URLComponents(string: request.url!.absoluteString)!
|
||||
let sut = components.queryItems!
|
||||
|
||||
XCTAssertEqual(sut.count, 1)
|
||||
XCTAssertTrue(sut.contains(where: { $0.key == "id" }))
|
||||
XCTAssertTrue(sut.contains(where: { ($0.value as? String) == "123" }))
|
||||
XCTAssertTrue(sut.contains(where: { $0.name == "id" && $0.value == "123" }))
|
||||
}
|
||||
|
||||
func test_buildParameters_withOptional()
|
||||
{
|
||||
let definition = UserRequestDefinition(id: "123", optionalFlag: 22)
|
||||
let request = try! facilitator.prepareRequest(from: definition).get()
|
||||
let components = URLComponents(string: request.url!.absoluteString)!
|
||||
let sut = components.queryItems!
|
||||
|
||||
XCTAssertEqual(sut.count, 2)
|
||||
XCTAssertTrue(sut.contains(where: { $0.name == "id" && $0.value == "123" }))
|
||||
XCTAssertTrue(sut.contains(where: { $0.name == "optionalFlag" && $0.value == "22" }))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ extension URLRequestFacilitatorTests
|
|||
let sut = facilitator.prepareRequest(
|
||||
.get,
|
||||
relativePath: "user",
|
||||
parameterEncoding: URLEncoding.default,
|
||||
parameters: ["id": "123"]
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in New Issue