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
func isValidJSON(_ jsonString: String) -> Bool { | |
if let data = jsonString.data(using: .utf8) { | |
do { | |
_ = try JSONSerialization.jsonObject(with: data, options: []) | |
return true | |
} catch { | |
return false | |
} | |
} | |
return false |
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
// The movies search in action | |
let movies = try await client.fetch(Movies.Search("Godfather", year: 1972)) | |
// The ranking in action | |
let page = try await client.fetch(Rankings.List(.topRated, region: .US)) |
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
var client: HTTPClient = { | |
client = HTTPClient(baseURL: "https://api.themoviedb.org/3") | |
client.queryParams = [ | |
.init(name: "api_key", value: "<API KEY>"), | |
.init(name: "language", value: "IT-it") | |
] | |
return client | |
}() |
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
public extension HTTPClient { | |
func fetch<T: APIResourceConvertible>(_ convertible: T) async throws -> T.Result { | |
let result = try await fetch(convertible.request()) | |
return try result.decode(T.Result.self) | |
} | |
} |
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
extension Rankings { | |
struct List: APIResourceConvertible { | |
public typealias Result = MoviesPage | |
public enum Category: String, CaseIterable { | |
case upcoming, popular | |
case topRated = "top_rated" | |
} |
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
public extension Movies { | |
struct Search: APIResourceConvertible { | |
public typealias Result = MoviesPage | |
var query: String | |
var includeAdult: Bool = false | |
var year: Int? | |
public init(_ query: String, year: Int? = nil) { |
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
public protocol APIResourceConvertible { | |
associatedtype Result: Decodable // the output object of the service | |
func request() -> HTTPRequest // function which generate a request | |
} | |
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
public enum Rankings { } | |
public enum Movies { } |
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
public func fetch() async throws { | |
// prepare the request and execute it | |
let task = try await request.urlSessionTask(inClient: client) | |
let response = try await fetch(request, task: sessionTask: task) | |
// ask to validator the action to perform on this request | |
let action = client.validate(response: response, forRequest: request) | |
switch action { | |
case .failChain(let error): | |
return HTTPResponse(error: error) // fail with error |
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
func validate(response: HTTPResponse, forRequest request: HTTPRequest) -> HTTPResponseValidatorResult { | |
if !(200..<300).contains(response.statusCode) { | |
// invalid response, we want to fail the request with error | |
throw HTTPError.invalidResponse | |
} | |
return .nextValidator // everything is okay, move to next validator | |
} |
NewerOlder