Skip to content
Permalink
Browse files

Unzips playground file

  • Loading branch information...
timothymiko committed Apr 8, 2019
1 parent c4d625e commit efbde712e1b22acc049563316d35e350d656d45d
Binary file not shown.
@@ -0,0 +1,125 @@
import Foundation
import PlaygroundSupport

enum HTTPMethod: String {
case get = "GET"
case put = "PUT"
case post = "POST"
case delete = "DELETE"
case head = "HEAD"
case options = "OPTIONS"
case trace = "TRACE"
case connect = "CONNECT"
}

struct HTTPHeader {
let field: String
let value: String
}

class APIRequest {
let method: HTTPMethod
let path: String
var queryItems: [URLQueryItem]?
var headers: [HTTPHeader]?
var body: Data?

init(method: HTTPMethod, path: String) {
self.method = method
self.path = path
}

init<Body: Encodable>(method: HTTPMethod, path: String, body: Body) throws {
self.method = method
self.path = path
self.body = try JSONEncoder().encode(body)
}
}

struct APIResponse<Body> {
let statusCode: Int
let body: Body
}

extension APIResponse where Body == Data? {
func decode<BodyType: Decodable>(to type: BodyType.Type) throws -> APIResponse<BodyType> {
guard let data = body else {
throw APIError.decodingFailure
}
let decodedJSON = try JSONDecoder().decode(BodyType.self, from: data)
return APIResponse<BodyType>(statusCode: self.statusCode,
body: decodedJSON)
}
}

enum APIError: Error {
case invalidURL
case requestFailed
case decodingFailure
}

enum APIResult<Body> {
case success(APIResponse<Body>)
case failure(APIError)
}

struct APIClient {

typealias APIClientCompletion = (APIResult<Data?>) -> Void

private let session = URLSession.shared
private let baseURL = URL(string: "https://jsonplaceholder.typicode.com")!

func perform(_ request: APIRequest, _ completion: @escaping APIClientCompletion) {

var urlComponents = URLComponents()
urlComponents.scheme = baseURL.scheme
urlComponents.host = baseURL.host
urlComponents.path = baseURL.path
urlComponents.queryItems = request.queryItems

guard let url = urlComponents.url?.appendingPathComponent(request.path) else {
completion(.failure(.invalidURL)); return
}

var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = request.method.rawValue
urlRequest.httpBody = request.body

request.headers?.forEach { urlRequest.addValue($0.value, forHTTPHeaderField: $0.field) }

let task = session.dataTask(with: urlRequest) { (data, response, error) in
guard let httpResponse = response as? HTTPURLResponse else {
completion(.failure(.requestFailed)); return
}
completion(.success(APIResponse<Data?>(statusCode: httpResponse.statusCode, body: data)))
}
task.resume()
}
}

struct Post: Decodable {
let userId: Int
let id: Int
let title: String
let body: String
}

let request = APIRequest(method: .get, path: "posts")

APIClient().perform(request) { (result) in
switch result {
case .success(let response):
if let response = try? response.decode(to: [Post].self) {
let posts = response.body
print("Received posts: \(posts.first?.title ?? "")")
} else {
print("Failed to decode response")
}
case .failure:
print("Error perform network request")
}
}

PlaygroundPage.current.needsIndefiniteExecution = true

@@ -0,0 +1,85 @@
import Foundation
import PlaygroundSupport

enum HTTPMethod: String {
case get = "GET"
case put = "PUT"
case post = "POST"
case delete = "DELETE"
case head = "HEAD"
case options = "OPTIONS"
case trace = "TRACE"
case connect = "CONNECT"
}

struct HTTPHeader {
let field: String
let value: String
}

class APIRequest {
let method: HTTPMethod
let path: String
var queryItems: [URLQueryItem]?
var headers: [HTTPHeader]?
var body: Data?

init(method: HTTPMethod, path: String) {
self.method = method
self.path = path
}
}

enum APIError: Error {
case invalidURL
case requestFailed
}

struct APIClient {

typealias APIClientCompletion = (HTTPURLResponse?, Data?, APIError?) -> Void

private let session = URLSession.shared
private let baseURL = URL(string: "https://jsonplaceholder.typicode.com")!

func request(_ request: APIRequest, _ completion: @escaping APIClientCompletion) {

var urlComponents = URLComponents()
urlComponents.scheme = baseURL.scheme
urlComponents.host = baseURL.host
urlComponents.path = baseURL.path
urlComponents.queryItems = request.queryItems

guard let url = urlComponents.url?.appendingPathComponent(request.path) else {
completion(nil, nil, .invalidURL); return
}

var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = request.method.rawValue
urlRequest.httpBody = request.body

request.headers?.forEach { urlRequest.addValue($0.value, forHTTPHeaderField: $0.field) }

let task = session.dataTask(with: urlRequest) { (data, response, error) in
guard let httpResponse = response as? HTTPURLResponse else {
completion(nil, nil, .requestFailed); return
}
completion(httpResponse, data, nil)
}
task.resume()
}
}

let request = APIRequest(method: .post, path: "posts")
request.queryItems = [URLQueryItem(name: "hello", value: "world")]
request.headers = [HTTPHeader(field: "Content-Type", value: "application/json")]
request.body = Data() // example post body
APIClient().request(request) { (_, data, _) in
if let data = data, let result = String(data: data, encoding: .utf8) {
print(result)
}
}

PlaygroundPage.current.needsIndefiniteExecution = true

@@ -0,0 +1,40 @@
import Foundation
import PlaygroundSupport

enum APIError: Error {
case invalidURL
case requestFailed
}

struct APIClient {

typealias APIClientCompletion = (HTTPURLResponse?, Data?, APIError?) -> Void

private let session = URLSession.shared
private let baseURL = URL(string: "https://jsonplaceholder.typicode.com")

func request(method: String, path: String, _ completion: @escaping APIClientCompletion) {
guard let url = baseURL?.appendingPathComponent(path) else {
completion(nil, nil, .invalidURL); return
}

var request = URLRequest(url: url)
request.httpMethod = method

let task = session.dataTask(with: request) { (data, response, error) in
guard let httpResponse = response as? HTTPURLResponse else {
completion(nil, nil, .requestFailed); return
}
completion(httpResponse, data, nil)
}
task.resume()
}
}

APIClient().request(method: "get", path: "todos/1") { (_, data, _) in
if let data = data, let result = String(data: data, encoding: .utf8) {
print(result)
}
}

PlaygroundPage.current.needsIndefiniteExecution = true
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='6.0' target-platform='ios' executeOnSourceChanges='false'>
<pages>
<page name='Simple'/>
<page name='Intermediate'/>
<page name='Advanced'/>
</pages>
</playground>

0 comments on commit efbde71

Please sign in to comment.
You can’t perform that action at this time.