2 // OAuthSwiftClient.swift
5 // Created by Dongri Jin on 6/21/14.
6 // Copyright (c) 2014 Dongri Jin. All rights reserved.
11 public var OAuthSwiftDataEncoding: String.Encoding = .utf8
13 @objc public protocol OAuthSwiftRequestHandle {
17 open class OAuthSwiftClient: NSObject {
19 fileprivate(set) open var credential: OAuthSwiftCredential
20 open var paramsLocation: OAuthSwiftHTTPRequest.ParamsLocation = .authorizationHeader
21 /// Contains default URL session configuration
22 open var sessionFactory = URLSessionFactory()
24 static let separator: String = "\r\n"
25 static var separatorData: Data = {
26 return OAuthSwiftClient.separator.data(using: OAuthSwiftDataEncoding)!
30 public init(credential: OAuthSwiftCredential) {
31 self.credential = credential
34 public convenience init(consumerKey: String, consumerSecret: String, version: OAuthSwiftCredential.Version = .oauth1) {
35 let credential = OAuthSwiftCredential(consumerKey: consumerKey, consumerSecret: consumerSecret)
36 credential.version = version
37 self.init(credential: credential)
40 public convenience init(consumerKey: String, consumerSecret: String, oauthToken: String, oauthTokenSecret: String, version: OAuthSwiftCredential.Version) {
41 self.init(consumerKey: consumerKey, consumerSecret: consumerSecret, version: version)
42 self.credential.oauthToken = oauthToken
43 self.credential.oauthTokenSecret = oauthTokenSecret
46 // MARK: client methods
48 open func get(_ urlString: String, parameters: OAuthSwift.Parameters = [:], headers: OAuthSwift.Headers? = nil, success: OAuthSwiftHTTPRequest.SuccessHandler?, failure: OAuthSwiftHTTPRequest.FailureHandler?) -> OAuthSwiftRequestHandle? {
49 return self.request(urlString, method: .GET, parameters: parameters, headers: headers, success: success, failure: failure)
53 open func post(_ urlString: String, parameters: OAuthSwift.Parameters = [:], headers: OAuthSwift.Headers? = nil, body: Data? = nil, success: OAuthSwiftHTTPRequest.SuccessHandler?, failure: OAuthSwiftHTTPRequest.FailureHandler?) -> OAuthSwiftRequestHandle? {
54 return self.request(urlString, method: .POST, parameters: parameters, headers: headers, body: body, success: success, failure: failure)
58 open func put(_ urlString: String, parameters: OAuthSwift.Parameters = [:], headers: OAuthSwift.Headers? = nil, body: Data? = nil, success: OAuthSwiftHTTPRequest.SuccessHandler?, failure: OAuthSwiftHTTPRequest.FailureHandler?) -> OAuthSwiftRequestHandle? {
59 return self.request(urlString, method: .PUT, parameters: parameters, headers: headers, body: body, success: success, failure: failure)
63 open func delete(_ urlString: String, parameters: OAuthSwift.Parameters = [:], headers: OAuthSwift.Headers? = nil, success: OAuthSwiftHTTPRequest.SuccessHandler?, failure: OAuthSwiftHTTPRequest.FailureHandler?) -> OAuthSwiftRequestHandle? {
64 return self.request(urlString, method: .DELETE, parameters: parameters, headers: headers, success: success, failure: failure)
68 open func patch(_ urlString: String, parameters: OAuthSwift.Parameters = [:], headers: OAuthSwift.Headers? = nil, success: OAuthSwiftHTTPRequest.SuccessHandler?, failure: OAuthSwiftHTTPRequest.FailureHandler?) -> OAuthSwiftRequestHandle? {
69 return self.request(urlString, method: .PATCH, parameters: parameters, headers: headers, success: success, failure: failure)
73 open func request(_ urlString: String, method: OAuthSwiftHTTPRequest.Method, parameters: OAuthSwift.Parameters = [:], headers: OAuthSwift.Headers? = nil, body: Data? = nil, checkTokenExpiration: Bool = true, success: OAuthSwiftHTTPRequest.SuccessHandler?, failure: OAuthSwiftHTTPRequest.FailureHandler?) -> OAuthSwiftRequestHandle? {
75 if checkTokenExpiration && self.credential.isTokenExpired() {
76 failure?(OAuthSwiftError.tokenExpired(error: nil))
80 guard URL(string: urlString) != nil else {
81 failure?(OAuthSwiftError.encodingError(urlString: urlString))
85 if let request = makeRequest(urlString, method: method, parameters: parameters, headers: headers, body: body) {
86 request.start(success: success, failure: failure)
92 open func makeRequest(_ request: URLRequest) -> OAuthSwiftHTTPRequest {
93 let request = OAuthSwiftHTTPRequest(request: request, paramsLocation: self.paramsLocation, sessionFactory: self.sessionFactory)
94 request.config.updateRequest(credential: self.credential)
98 open func makeRequest(_ urlString: String, method: OAuthSwiftHTTPRequest.Method, parameters: OAuthSwift.Parameters = [:], headers: OAuthSwift.Headers? = nil, body: Data? = nil) -> OAuthSwiftHTTPRequest? {
99 guard let url = URL(string: urlString) else {
103 let request = OAuthSwiftHTTPRequest(url: url, method: method, parameters: parameters, paramsLocation: self.paramsLocation, httpBody: body, headers: headers ?? [:], sessionFactory: self.sessionFactory)
104 request.config.updateRequest(credential: self.credential)
109 public func postImage(_ urlString: String, parameters: OAuthSwift.Parameters, image: Data, success: OAuthSwiftHTTPRequest.SuccessHandler?, failure: OAuthSwiftHTTPRequest.FailureHandler?) -> OAuthSwiftRequestHandle? {
110 return self.multiPartRequest(url: urlString, method: .POST, parameters: parameters, image: image, success: success, failure: failure)
113 open func makeMultiPartRequest(_ urlString: String, method: OAuthSwiftHTTPRequest.Method, parameters: OAuthSwift.Parameters = [:], multiparts: [OAuthSwiftMultipartData] = [], headers: OAuthSwift.Headers? = nil) -> OAuthSwiftHTTPRequest? {
114 let boundary = "AS-boundary-\(arc4random())-\(arc4random())"
115 let type = "multipart/form-data; boundary=\(boundary)"
116 let body = self.multiDataFromObject(parameters, multiparts: multiparts, boundary: boundary)
118 var finalHeaders = [kHTTPHeaderContentType: type]
119 finalHeaders += headers ?? [:]
121 return makeRequest(urlString, method: method, parameters: parameters, headers: finalHeaders, body: body)
124 func multiPartRequest(url: String, method: OAuthSwiftHTTPRequest.Method, parameters: OAuthSwift.Parameters, image: Data, success: OAuthSwiftHTTPRequest.SuccessHandler?, failure: OAuthSwiftHTTPRequest.FailureHandler?) -> OAuthSwiftRequestHandle? {
125 let multiparts = [ OAuthSwiftMultipartData(name: "media", data: image, fileName: "file", mimeType: "image/jpeg") ]
127 if let request = makeMultiPartRequest(url, method: method, parameters: parameters, multiparts: multiparts) {
128 request.start(success: success, failure: failure)
135 open func multiPartBody(from inputParameters: OAuthSwift.Parameters, boundary: String) -> Data {
136 var parameters = OAuthSwift.Parameters()
137 var multiparts = [OAuthSwiftMultipartData]()
139 for (key, value) in inputParameters {
140 if let data = value as? Data, key == "media" {
141 let sectionType = "image/jpeg"
142 let sectionFilename = "file"
143 multiparts.append(OAuthSwiftMultipartData(name: key, data: data, fileName: sectionFilename, mimeType: sectionType))
145 parameters[key] = value
149 return multiDataFromObject(parameters, multiparts: multiparts, boundary: boundary)
153 open func postMultiPartRequest(_ url: String, method: OAuthSwiftHTTPRequest.Method, parameters: OAuthSwift.Parameters, headers: OAuthSwift.Headers? = nil, multiparts: [OAuthSwiftMultipartData] = [], checkTokenExpiration: Bool = true, success: OAuthSwiftHTTPRequest.SuccessHandler?, failure: OAuthSwiftHTTPRequest.FailureHandler?) -> OAuthSwiftRequestHandle? {
155 if checkTokenExpiration && self.credential.isTokenExpired() {
156 failure?(OAuthSwiftError.tokenExpired(error: nil))
160 if let request = makeMultiPartRequest(url, method: method, parameters: parameters, multiparts: multiparts, headers: headers) {
161 request.start(success: success, failure: failure)
167 func multiDataFromObject(_ object: OAuthSwift.Parameters, multiparts: [OAuthSwiftMultipartData], boundary: String) -> Data {
170 let prefixString = "--\(boundary)\r\n"
171 let prefixData = prefixString.data(using: OAuthSwiftDataEncoding)!
173 for (key, value) in object {
174 guard let valueData = "\(value)".data(using: OAuthSwiftDataEncoding) else {
177 data.append(prefixData)
178 let multipartData = OAuthSwiftMultipartData(name: key, data: valueData, fileName: nil, mimeType: nil)
179 data.append(multipartData, encoding: OAuthSwiftDataEncoding, separatorData: OAuthSwiftClient.separatorData)
182 for multipart in multiparts {
183 data.append(prefixData)
184 data.append(multipart, encoding: OAuthSwiftDataEncoding, separatorData: OAuthSwiftClient.separatorData)
187 let endingString = "--\(boundary)--\r\n"
188 let endingData = endingString.data(using: OAuthSwiftDataEncoding)!
189 data.append(endingData)