vendoo_v1.0/Pods/OAuthSwift/OAuthSwift/OAuthSwiftClient.swift

255 lines
12 KiB
Swift

//
// OAuthSwiftClient.swift
// OAuthSwift
//
// Created by Dongri Jin on 6/21/14.
// Copyright (c) 2014 Dongri Jin. All rights reserved.
//
import Foundation
var OAuthSwiftDataEncoding: NSStringEncoding = NSUTF8StringEncoding
public class OAuthSwiftClient: NSObject {
private(set) public var credential: OAuthSwiftCredential
public var paramsLocation: OAuthSwiftHTTPRequest.ParamsLocation = .AuthorizationHeader
static let separator: String = "\r\n"
static var separatorData: NSData = {
return OAuthSwiftClient.separator.dataUsingEncoding(OAuthSwiftDataEncoding)!
}()
// MARK: init
public init(consumerKey: String, consumerSecret: String) {
self.credential = OAuthSwiftCredential(consumer_key: consumerKey, consumer_secret: consumerSecret)
}
public init(consumerKey: String, consumerSecret: String, accessToken: String, accessTokenSecret: String) {
self.credential = OAuthSwiftCredential(oauth_token: accessToken, oauth_token_secret: accessTokenSecret)
self.credential.consumer_key = consumerKey
self.credential.consumer_secret = consumerSecret
}
// MARK: client methods
public func get(urlString: String, parameters: [String: AnyObject] = [:], headers: [String:String]? = nil, success: OAuthSwiftHTTPRequest.SuccessHandler?, failure: OAuthSwiftHTTPRequest.FailureHandler?) {
self.request(urlString, method: .GET, parameters: parameters, headers: headers, success: success, failure: failure)
}
public func post(urlString: String, parameters: [String: AnyObject] = [:], headers: [String:String]? = nil, success: OAuthSwiftHTTPRequest.SuccessHandler?, failure: OAuthSwiftHTTPRequest.FailureHandler?) {
self.request(urlString, method: .POST, parameters: parameters, headers: headers, success: success, failure: failure)
}
public func put(urlString: String, parameters: [String: AnyObject] = [:], headers: [String:String]? = nil, success: OAuthSwiftHTTPRequest.SuccessHandler?, failure: OAuthSwiftHTTPRequest.FailureHandler?) {
self.request(urlString, method: .PUT, parameters: parameters, headers: headers,success: success, failure: failure)
}
public func delete(urlString: String, parameters: [String: AnyObject] = [:], headers: [String:String]? = nil, success: OAuthSwiftHTTPRequest.SuccessHandler?, failure: OAuthSwiftHTTPRequest.FailureHandler?) {
self.request(urlString, method: .DELETE, parameters: parameters, headers: headers,success: success, failure: failure)
}
public func patch(urlString: String, parameters: [String: AnyObject] = [:], headers: [String:String]? = nil, success: OAuthSwiftHTTPRequest.SuccessHandler?, failure: OAuthSwiftHTTPRequest.FailureHandler?) {
self.request(urlString, method: .PATCH, parameters: parameters, headers: headers,success: success, failure: failure)
}
public func request(url: String, method: OAuthSwiftHTTPRequest.Method, parameters: [String: AnyObject] = [:], headers: [String:String]? = nil, checkTokenExpiration: Bool = true, success: OAuthSwiftHTTPRequest.SuccessHandler?, failure: OAuthSwiftHTTPRequest.FailureHandler?) {
if checkTokenExpiration && self.credential.isTokenExpired() {
let errorInfo = [NSLocalizedDescriptionKey: NSLocalizedString("The provided token is expired.", comment:"Token expired, retrieve new token by using the refresh token")]
if let failureHandler = failure {
failureHandler(error: NSError(domain: OAuthSwiftErrorDomain, code: OAuthSwiftErrorCode.TokenExpiredError.rawValue, userInfo: errorInfo))
}
return
}
if let request = makeRequest(url, method: method, parameters: parameters, headers: headers) {
request.successHandler = success
request.failureHandler = failure
request.start()
}
}
public func makeRequest(request: NSURLRequest) -> OAuthSwiftHTTPRequest {
let request = OAuthSwiftHTTPRequest(request: request, paramsLocation: self.paramsLocation)
return makeOAuthSwiftHTTPRequest(request)
}
public func makeRequest(urlString: String, method: OAuthSwiftHTTPRequest.Method, parameters: [String: AnyObject] = [:], headers: [String:String]? = nil) -> OAuthSwiftHTTPRequest? {
guard let url = NSURL(string: urlString) else {
return nil
}
let request = OAuthSwiftHTTPRequest(URL: url, method: method, parameters: parameters, paramsLocation: self.paramsLocation)
if let addHeaders = headers {
request.headers = addHeaders
}
return makeOAuthSwiftHTTPRequest(request)
}
public func makeOAuthSwiftHTTPRequest(request: OAuthSwiftHTTPRequest) -> OAuthSwiftHTTPRequest {
var requestHeaders = [String:String]()
var signatureUrl = request.URL
var signatureParameters = request.parameters
// Check if body must be hashed (oauth1)
let body: NSData? = nil
if request.HTTPMethod.isBody {
if let contentType = request.headers["Content-Type"]?.lowercaseString {
if contentType.rangeOfString("application/json") != nil {
// TODO: oauth_body_hash create body before signing if implementing body hashing
/*do {
let jsonData: NSData = try NSJSONSerialization.dataWithJSONObject(parameters, options: [])
request.HTTPBody = jsonData
requestHeaders["Content-Length"] = "\(jsonData.length)"
body = jsonData
}
catch {
}*/
signatureParameters = [:] // parameters are not used for general signature (could only be used for body hashing
}
// else other type are not supported, see setupRequestForOAuth()
}
}
// Need to account for the fact that some consumers will have additional parameters on the
// querystring, including in the case of fetching a request token. Especially in the case of
// additional parameters on the request, authorize, or access token exchanges, we need to
// normalize the URL and add to the parametes collection.
var queryStringParameters = Dictionary<String, AnyObject>()
let urlComponents = NSURLComponents(URL: request.URL, resolvingAgainstBaseURL: false )
if let queryItems = urlComponents?.queryItems {
for queryItem in queryItems {
let value = queryItem.value?.safeStringByRemovingPercentEncoding ?? ""
queryStringParameters.updateValue(value, forKey: queryItem.name)
}
}
// According to the OAuth1.0a spec, the url used for signing is ONLY scheme, path, and query
if(queryStringParameters.count>0)
{
urlComponents?.query = nil
// This is safe to unwrap because these just came from an NSURL
signatureUrl = urlComponents?.URL ?? request.URL
}
signatureParameters = signatureParameters.join(queryStringParameters)
switch self.paramsLocation {
case .AuthorizationHeader:
//Add oauth parameters in the Authorization header
requestHeaders += self.credential.makeHeaders(signatureUrl, method: request.HTTPMethod, parameters: signatureParameters, body: body)
case .RequestURIQuery:
//Add oauth parameters as request parameters
request.parameters += self.credential.authorizationParametersWithSignatureForMethod(request.HTTPMethod, url: signatureUrl, parameters: signatureParameters, body: body)
}
request.headers = requestHeaders + request.headers
request.dataEncoding = OAuthSwiftDataEncoding
return request
}
public func postImage(urlString: String, parameters: Dictionary<String, AnyObject>, image: NSData, success: OAuthSwiftHTTPRequest.SuccessHandler?, failure: OAuthSwiftHTTPRequest.FailureHandler?) {
self.multiPartRequest(urlString, method: .POST, parameters: parameters, image: image, success: success, failure: failure)
}
func multiPartRequest(url: String, method: OAuthSwiftHTTPRequest.Method, parameters: Dictionary<String, AnyObject>, image: NSData, success: OAuthSwiftHTTPRequest.SuccessHandler?, failure: OAuthSwiftHTTPRequest.FailureHandler?) {
if let request = makeRequest(url, method: method, parameters: parameters) {
var paramImage = [String: AnyObject]()
paramImage["media"] = image
let boundary = "AS-boundary-\(arc4random())-\(arc4random())"
let type = "multipart/form-data; boundary=\(boundary)"
let body = self.multiPartBodyFromParams(paramImage, boundary: boundary)
request.HTTPBody = body
request.headers += ["Content-Type": type] // "Content-Length": body.length.description
request.successHandler = success
request.failureHandler = failure
request.start()
}
}
public func multiPartBodyFromParams(parameters: [String: AnyObject], boundary: String) -> NSData {
let data = NSMutableData()
let prefixString = "--\(boundary)\r\n"
let prefixData = prefixString.dataUsingEncoding(OAuthSwiftDataEncoding)!
for (key, value) in parameters {
var sectionData: NSData
var sectionType: String?
var sectionFilename: String?
if let multiData = value as? NSData where key == "media" {
sectionData = multiData
sectionType = "image/jpeg"
sectionFilename = "file"
} else {
sectionData = "\(value)".dataUsingEncoding(OAuthSwiftDataEncoding)!
}
data.appendData(prefixData)
let multipartData = OAuthSwiftMultipartData(name: key, data: sectionData, fileName: sectionFilename, mimeType: sectionType)
data.appendMultipartData(multipartData, encoding: OAuthSwiftDataEncoding, separatorData: OAuthSwiftClient.separatorData)
}
let endingString = "--\(boundary)--\r\n"
let endingData = endingString.dataUsingEncoding(OAuthSwiftDataEncoding)!
data.appendData(endingData)
return data
}
public func postMultiPartRequest(url: String, method: OAuthSwiftHTTPRequest.Method, parameters: Dictionary<String, AnyObject>, multiparts: Array<OAuthSwiftMultipartData> = [], checkTokenExpiration: Bool = true, success: OAuthSwiftHTTPRequest.SuccessHandler?, failure: OAuthSwiftHTTPRequest.FailureHandler?) {
if let request = makeRequest(url, method: method, parameters: parameters) {
let boundary = "POST-boundary-\(arc4random())-\(arc4random())"
let type = "multipart/form-data; boundary=\(boundary)"
let body = self.multiDataFromObject(parameters, multiparts: multiparts, boundary: boundary)
request.HTTPBody = body
request.headers += ["Content-Type": type] // "Content-Length": body.length.description
request.successHandler = success
request.failureHandler = failure
request.start()
}
}
func multiDataFromObject(object: [String:AnyObject], multiparts: Array<OAuthSwiftMultipartData>, boundary: String) -> NSData? {
let data = NSMutableData()
let prefixString = "--\(boundary)\r\n"
let prefixData = prefixString.dataUsingEncoding(OAuthSwiftDataEncoding)!
for (key, value) in object {
guard let valueData = "\(value)".dataUsingEncoding(OAuthSwiftDataEncoding) else {
continue
}
data.appendData(prefixData)
let multipartData = OAuthSwiftMultipartData(name: key, data: valueData, fileName: nil, mimeType: nil)
data.appendMultipartData(multipartData, encoding: OAuthSwiftDataEncoding, separatorData: OAuthSwiftClient.separatorData)
}
for multipart in multiparts {
data.appendData(prefixData)
data.appendMultipartData(multipart, encoding: OAuthSwiftDataEncoding, separatorData: OAuthSwiftClient.separatorData)
}
let endingString = "--\(boundary)--\r\n"
let endingData = endingString.dataUsingEncoding(OAuthSwiftDataEncoding)!
data.appendData(endingData)
return data
}
}