summaryrefslogtreecommitdiff
path: root/Juick/Service.swift
blob: 441451e4c6c2e491597a534e0e47141f76b2c5b9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//
//  Service.swift
//  Juick
//
//  Created by Vitaly Takmazov on 16.09.2020.
//  Copyright © 2020 com.juick. All rights reserved.
//

import Foundation

class Service : NSObject, URLSessionDelegate, URLSessionTaskDelegate {
    let backgroundQueue = OperationQueue()
    
    let baseURL : URL?
    
    lazy var authorizationHeader : String? = {
        if let token = UserDefaults.standard.string(forKey: "token") {
            return "Juick \(token)"
        }
        return nil;
    }()
    
    override init() {
        let baseURLString = Bundle.main.object(forInfoDictionaryKey:"base_url") as! String
        debugPrint("Initializing with \(baseURLString) base URL")
        self.baseURL = URL(string: baseURLString)
        super.init()
    }
    func url(url:URL, params:[String: String]) -> URL {
        let parametersUrl = NSURLComponents(url: url, resolvingAgainstBaseURL: true)
        var items : [URLQueryItem] = []
        for (key, value) in params {
            items.append(URLQueryItem(name: key, value: value))
        }
        parametersUrl?.queryItems = items
        return (parametersUrl?.url!)!
    }
    func fetchData(url:URL, postData:Data?, boundary:String?, header:String?, callback: @escaping (Data?, Error?) -> Void) {
        var request = URLRequest(url: url)
        if (header != nil) {
            request.addValue(header!, forHTTPHeaderField:"Authorization")
        }
        if (boundary != nil) {
            request.httpMethod = "POST";
            request.httpBody = postData;
            let contentType = "multipart/form-data; boundary=\(boundary!)"
            request.setValue(contentType, forHTTPHeaderField:"Content-Type")
        } else if (postData != nil) {
            request.httpMethod = "PUT";
            request.httpBody = postData;
            request.setValue("application/json", forHTTPHeaderField:"Content-Type")
        } else {
            request.httpMethod = "GET";
        }
        
        let task = URLSession.shared.dataTask(with: request, completionHandler: { (data, response, error) in
            if (error != nil) {
                OperationQueue.main.addOperation {
                    callback(nil, error)
                }
            } else {
                let statusCode = (response as? HTTPURLResponse)?.statusCode ?? 457
                if (response == nil || statusCode != 200) {
                    let url = request.url
                    let err = NSError(domain: "JuickErrorDomain", code: statusCode, userInfo: ["url":url!.absoluteString])
                    OperationQueue.main.addOperation {
                        callback(nil, err)
                    }
                } else {
                    OperationQueue.main.addOperation {
                        callback(data, error)
                    }
                }
            }
        })
        self.backgroundQueue.addOperation {
            task.resume()
        }
    }
    private func multipartData(params:[String:String], boundary:String) -> Data {
        var body = Data()
        for (key, value) in params {
            body.append("--\(boundary)\r\n".data(using: .utf8)!)
            body.append("Content-Disposition: form-data; name=\(key)\r\n\r\n".data(using: .utf8)!)
            body.append("\(value)\r\n".data(using: .utf8)!)
        }
        body.append("--\(boundary)--".data(using: .utf8)!)
        return body;
    }
    private func get(path:String, params:[String:String], callback:@escaping (NSDictionary?, Error?) -> Void) {
        if let url = URL(string: path, relativeTo: self.baseURL) {
            let requestUrl = params.isEmpty ? url : self.url(url: url, params: params)
            fetchData(url: requestUrl, postData: nil, boundary: nil, header: self.authorizationHeader) {
                (responseData, err) in
                if (err != nil) {
                    callback(nil, err)
                } else {
                    if let data = responseData, let jsonData = try? JSONSerialization.jsonObject(with: data, options: []) {
                        callback(jsonData as? NSDictionary, nil)
                    } else {
                        callback(nil, NSError(domain: "JuickErrorDomain", code: 500, userInfo: ["message":"JSON error"]))
                    }
                }
            }
        }
    }
    
    func post(path: String, params:[String:String], callback:@escaping (NSDictionary?, Error?) -> Void) {
        if let url = URL(string: path, relativeTo: self.baseURL) {
            let boundary = "Boundary-\(UUID().uuidString)";
            fetchData(url: url, postData:multipartData(params: params, boundary: boundary), boundary: boundary, header: self.authorizationHeader) {
                (responseData, err) in
                if (err != nil) {
                    callback(nil, err)
                } else {
                    if let data = responseData, let jsonData = try? JSONSerialization.jsonObject(with: data, options: []) {
                        callback(jsonData as? NSDictionary, nil)
                    } else {
                        callback(nil, NSError(domain: "JuickErrorDomain", code: 500, userInfo: ["message":"JSON error"]))
                    }
                }
            }
        }
    }

    func fetchImage(url:URL, callback:@escaping(Data?)-> Void) {
        fetchData(url: url, postData: nil, boundary: nil, header: self.authorizationHeader) { (data, err) in
            if (err != nil) {
                callback(nil);
            } else {
                callback(data);
            }
        }
    }
}