Add possibility to pass query items to ApiRequestParameters

This commit is contained in:
Ivan Babkin 2019-06-28 15:42:51 +03:00
parent 6f1d4a0dba
commit 3ed9d949a4
10 changed files with 80 additions and 33 deletions

View File

@ -1,5 +1,9 @@
# Changelog
### 0.9.24
- **Add**: `queryItems` parameter for `ApiRequestParameters`.
- **Add**: `asQueryItems` method for `Encodable` that converts model to query items array.
### 0.9.23
- **Add**: Rounding for `Decimal`.
- **Add**: `doubleValue` property for `Decimal`.

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "LeadKit"
s.version = "0.9.23"
s.version = "0.9.24"
s.summary = "iOS framework with a bunch of tools for rapid development"
s.homepage = "https://github.com/TouchInstinct/LeadKit"
s.license = "Apache License, Version 2.0"

View File

@ -25,8 +25,11 @@ import Foundation
/// Enum that represents common errors in LeadKit framework
///
/// - failedToCastValue: attempt to cast was failed
/// - failedToDecode: attempt to decoding was failed
/// - failedToEncodeQueryItems: attempt to encoding to query items was failed
public enum LeadKitError: Error {
case failedToCastValue(expectedType: Any.Type, givenType: Any.Type)
case failedToDecode(reason: String)
case failedToEncodeQueryItems
}

View File

@ -32,6 +32,7 @@ enum RequestUsageError: Error {
case getMethodForbidden
case urlEncodingForbidden
case unableToHandleQueryParams
}
public extension Reactive where Base: SessionManager {
@ -72,41 +73,52 @@ public extension Reactive where Base: SessionManager {
/// - requestParameters: api parameters to pass Alamofire
/// - additionalValidStatusCodes: set of additional valid status codes
/// - Returns: Observable with request
func apiRequest(requestParameters: ApiRequestParameters, additionalValidStatusCodes: Set<Int>)
-> Observable<DataRequest> {
func apiRequest(requestParameters: ApiRequestParameters, additionalValidStatusCodes: Set<Int>) -> Observable<DataRequest> {
return .deferred {
var url = try requestParameters.url.asURL()
let requestObservable: Observable<DataRequest>
if let queryItems = requestParameters.queryItems {
guard var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: true) else {
return .error(RequestUsageError.unableToHandleQueryParams)
}
switch requestParameters.parameters {
case .dictionary(let parameters)?:
requestObservable = request(requestParameters.method,
requestParameters.url,
parameters: parameters,
encoding: requestParameters.encoding,
headers: requestParameters.headers)
case .array(let parameters)?:
guard let encoding = requestParameters.encoding as? JSONEncoding else {
assertionFailure("Invalid encoding type with array parameter")
return .error(RequestUsageError.urlEncodingForbidden)
urlComponents.queryItems = queryItems
url = try urlComponents.asURL()
}
requestObservable = request(requestParameters.method,
requestParameters.url,
parameters: parameters,
encoding: encoding,
headers: requestParameters.headers)
let requestObservable: Observable<DataRequest>
case .none:
requestObservable = request(requestParameters.method,
requestParameters.url,
parameters: nil as Parameters?,
encoding: requestParameters.encoding,
headers: requestParameters.headers)
switch requestParameters.parameters {
case .dictionary(let parameters)?:
requestObservable = self.request(requestParameters.method,
url,
parameters: parameters,
encoding: requestParameters.encoding,
headers: requestParameters.headers)
case .array(let parameters)?:
guard let encoding = requestParameters.encoding as? JSONEncoding else {
assertionFailure("Invalid encoding type with array parameter")
return .error(RequestUsageError.urlEncodingForbidden)
}
requestObservable = self.request(requestParameters.method,
url,
parameters: parameters,
encoding: encoding,
headers: requestParameters.headers)
case .none:
requestObservable = self.request(requestParameters.method,
url,
parameters: nil as Parameters?,
encoding: requestParameters.encoding,
headers: requestParameters.headers)
}
return requestObservable
.validate(statusCodes: self.base.acceptableStatusCodes.union(additionalValidStatusCodes))
}
return requestObservable
.validate(statusCodes: self.base.acceptableStatusCodes.union(additionalValidStatusCodes))
}
/// Method that executes request and serializes response into target object

View File

@ -21,6 +21,7 @@
//
import Foundation
import Alamofire
public extension Encodable {
@ -35,4 +36,20 @@ public extension Encodable {
return json
}
/// Method that converts encodable model to URLQueryItems array
/// - Returns: URLQueryItems array
func asUrlQueryItems() throws -> [URLQueryItem] {
return try toJSON().map {
if let value = $1 as? Encodable,
let jsonData = try? JSONSerialization.data(withJSONObject: value.toJSON(), options: []),
let jsonString = String(data: jsonData, encoding: .utf8) {
return URLQueryItem(name: $0, value: jsonString)
} else if let value = $1 as? CustomStringConvertible {
return URLQueryItem(name: $0, value: "\(value)")
} else {
throw LeadKitError.failedToEncodeQueryItems
}
}
}
}

View File

@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>0.9.23</string>
<string>0.9.24</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>

View File

@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>0.9.23</string>
<string>0.9.24</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>

View File

@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>0.9.23</string>
<string>0.9.24</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>

View File

@ -39,17 +39,20 @@ public struct ApiRequestParameters {
let method: HTTPMethod
let url: URLConvertible
let parameters: RequestParameters?
let queryItems: [URLQueryItem]?
let encoding: ParameterEncoding
let headers: HTTPHeaders?
public init(url: URLConvertible,
method: HTTPMethod = .get,
parameters: Parameters? = nil,
queryItems: [URLQueryItem]? = nil,
encoding: ParameterEncoding = URLEncoding.default,
headers: HTTPHeaders? = nil) {
self.method = method
self.url = url
self.queryItems = queryItems
self.encoding = encoding
self.headers = headers
if let parameters = parameters {
@ -62,11 +65,13 @@ public struct ApiRequestParameters {
public init(url: URLConvertible,
method: HTTPMethod = .get,
parameters: [Any]? = nil,
queryItems: [URLQueryItem]? = nil,
encoding: ParameterEncoding = URLEncoding.default,
headers: HTTPHeaders? = nil) {
self.method = method
self.url = url
self.queryItems = queryItems
self.encoding = encoding
self.headers = headers
if let parameters = parameters {

View File

@ -81,17 +81,20 @@ public extension NetworkServiceConfiguration {
/// - relativeUrl: Url that will be concatenated with base url.
/// - method: HTTP method to use for request.
/// - parameters: Dictionary of parameters to apply to a URLRequest.
/// - queryItems: An array of query items to configure URL with them.
/// - requestEncoding: Encoding type to use. If passed nil, configuration encoding will be used.
/// - requestHeaders: Dictionary of headers to apply to a URLRequest.
/// - Returns: Initialized instance of ApiRequestParameters with given parameters.
func apiRequestParameters(relativeUrl: String,
method: HTTPMethod = .get,
parameters: Parameters? = nil,
queryItems: [URLQueryItem]? = nil,
requestEncoding: ParameterEncoding? = nil,
requestHeaders: HTTPHeaders? = nil) -> ApiRequestParameters {
return ApiRequestParameters(url: baseUrl + relativeUrl,
method: method,
parameters: parameters,
queryItems: queryItems,
encoding: requestEncoding ?? encoding,
headers: requestHeaders)
}
@ -102,17 +105,20 @@ public extension NetworkServiceConfiguration {
/// - relativeUrl: Url that will be concatenated with base url.
/// - method: HTTP method to use for request.
/// - parameters: An array of JSON objects to apply to a URLRequest.
/// - queryItems: An array of query items to configure URL with them.
/// - requestEncoding: Encoding type to use. If passed nil, configuration encoding will be used.
/// - requestHeaders: Dictionary of headers to apply to a URLRequest.
/// - Returns: Initialized instance of ApiRequestParameters with given parameters.
func apiRequestParameters(relativeUrl: String,
method: HTTPMethod = .get,
parameters: [Any]? = nil,
queryItems: [URLQueryItem]? = nil,
requestEncoding: ParameterEncoding? = nil,
requestHeaders: HTTPHeaders? = nil) -> ApiRequestParameters {
return ApiRequestParameters(url: baseUrl + relativeUrl,
method: method,
parameters: parameters,
queryItems: queryItems,
encoding: requestEncoding ?? encoding,
headers: requestHeaders)
}