blob: 0a651e25c498c57da3106afd483aeb3fd7facb65 [file] [log] [blame]
//
// UsergridRequest.swift
// UsergridSDK
//
// Created by Robert Walsh on 1/12/16.
//
/*
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. The ASF licenses this file to You
* under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License. For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*
*/
import Foundation
/**
The UsergridRequest class incapsulates the properties that all requests made by the SDK have in common.
This class is also functions to create `NSURLRequest` objects based on the properties of the class.
*/
public class UsergridRequest : NSObject {
// MARK: - Instance Properties -
/// The HTTP method.
public let method: UsergridHttpMethod
/// The base URL.
public let baseUrl: String
/// The paths to append to the base URL.
public let paths: [String]?
/// The query to append to the URL.
public let query: UsergridQuery?
/// The auth that will be used.
public let auth: UsergridAuth?
/// The headers to add to the request.
public let headers: [String:String]?
/// The JSON body that will be set on the request. Can be either a valid JSON object or NSData.
public let jsonBody: AnyObject?
/// The query params that will be set on the request.
public let queryParams: [String:String]?
// MARK: - Initialization -
/**
The designated initializer for `UsergridRequest` objects.
- parameter method: The HTTP method.
- parameter baseUrl: The base URL.
- parameter paths: The optional paths to append to the base URL.
- parameter query: The optional query to append to the URL.
- parameter auth: The optional `UsergridAuth` that will be used in the Authorization header.
- parameter headers: The optional headers.
- parameter jsonBody: The optional JSON body. Can be either a valid JSON object or NSData.
- parameter queryParams: The optional query params to be appended to the request url.
- returns: A new instance of `UsergridRequest`.
*/
public init(method:UsergridHttpMethod,
baseUrl:String,
paths:[String]? = nil,
query:UsergridQuery? = nil,
auth:UsergridAuth? = nil,
headers:[String:String]? = nil,
jsonBody:AnyObject? = nil,
queryParams:[String:String]? = nil) {
self.method = method
self.baseUrl = baseUrl
self.paths = paths
self.auth = auth
self.headers = headers
self.query = query
self.queryParams = queryParams
if let body = jsonBody where (body is NSData || NSJSONSerialization.isValidJSONObject(body)) {
self.jsonBody = body
} else {
self.jsonBody = nil
}
}
// MARK: - Instance Methods -
/**
Constructs a `NSURLRequest` object with this objects instance properties.
- returns: An initialized and configured `NSURLRequest` object.
*/
public func buildNSURLRequest() -> NSURLRequest {
let request = NSMutableURLRequest(URL: self.buildURL())
request.HTTPMethod = self.method.stringValue
self.applyHeaders(request)
self.applyBody(request)
self.applyAuth(request)
return request
}
private func buildURL() -> NSURL {
var constructedURLString = self.baseUrl
if let appendingPaths = self.paths {
for pathToAppend in appendingPaths {
if let encodedPath = pathToAppend.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLPathAllowedCharacterSet()) {
constructedURLString = "\(constructedURLString)\(UsergridRequest.FORWARD_SLASH)\(encodedPath)"
}
}
}
if let queryToAppend = self.query {
let appendFromQuery = queryToAppend.build()
if !appendFromQuery.isEmpty {
constructedURLString = "\(constructedURLString)\(UsergridRequest.FORWARD_SLASH)\(appendFromQuery)"
}
}
if let queryParams = self.queryParams {
if let components = NSURLComponents(string: constructedURLString) {
components.queryItems = components.queryItems ?? []
for (key, value) in queryParams {
let q: NSURLQueryItem = NSURLQueryItem(name: key, value: value)
components.queryItems!.append(q)
}
constructedURLString = components.string!
}
}
return NSURL(string:constructedURLString)!
}
private func applyHeaders(request:NSMutableURLRequest) {
if let httpHeaders = self.headers {
for (key,value) in httpHeaders {
request.setValue(value, forHTTPHeaderField: key)
}
}
}
private func applyBody(request:NSMutableURLRequest) {
if let jsonBody = self.jsonBody, httpBody = UsergridRequest.jsonBodyToData(jsonBody) {
request.HTTPBody = httpBody
request.setValue(String(format: "%lu", httpBody.length), forHTTPHeaderField: UsergridRequest.CONTENT_LENGTH)
}
}
private func applyAuth(request:NSMutableURLRequest) {
if let usergridAuth = self.auth {
if usergridAuth.isValid, let accessToken = usergridAuth.accessToken {
request.setValue("\(UsergridRequest.BEARER) \(accessToken)", forHTTPHeaderField: UsergridRequest.AUTHORIZATION)
}
}
}
private static func jsonBodyToData(jsonBody:AnyObject) -> NSData? {
if let jsonBodyAsNSData = jsonBody as? NSData {
return jsonBodyAsNSData
} else {
var jsonBodyAsNSData: NSData? = nil
do { jsonBodyAsNSData = try NSJSONSerialization.dataWithJSONObject(jsonBody, options: NSJSONWritingOptions(rawValue: 0)) }
catch { print(error) }
return jsonBodyAsNSData
}
}
private static let AUTHORIZATION = "Authorization"
private static let ACCESS_TOKEN = "access_token"
private static let APPLICATION_JSON = "application/json; charset=utf-8"
private static let BEARER = "Bearer"
private static let CONTENT_LENGTH = "Content-Length"
private static let CONTENT_TYPE = "Content-Type"
private static let FORWARD_SLASH = "/"
static let JSON_CONTENT_TYPE_HEADER = [UsergridRequest.CONTENT_TYPE:UsergridRequest.APPLICATION_JSON]
}
/**
The `UsergridRequest` sub class which is used for uploading assets.
*/
public class UsergridAssetUploadRequest: UsergridRequest {
// MARK: - Instance Properties -
/// The asset to use for uploading.
public let asset: UsergridAsset
/// A constructed multipart http body for requests to upload.
public var multiPartHTTPBody: NSData {
let httpBodyString = UsergridAssetUploadRequest.MULTIPART_START +
"\(UsergridAssetUploadRequest.CONTENT_DISPOSITION):\(UsergridAssetUploadRequest.FORM_DATA); name=file; filename=\(self.asset.filename)\r\n" +
"\(UsergridRequest.CONTENT_TYPE): \(self.asset.contentType)\r\n\r\n" as NSString
let httpBody = NSMutableData()
httpBody.appendData(httpBodyString.dataUsingEncoding(NSUTF8StringEncoding)!)
httpBody.appendData(self.asset.data)
httpBody.appendData(UsergridAssetUploadRequest.MULTIPART_END.dataUsingEncoding(NSUTF8StringEncoding)!)
return httpBody
}
// MARK: - Initialization -
/**
The designated initializer for `UsergridAssetUploadRequest` objects.
- parameter baseUrl: The base URL.
- parameter paths: The optional paths to append to the base URL.
- parameter auth: The optional `UsergridAuth` that will be used in the Authorization header.
- parameter asset: The asset to upload.
- returns: A new instance of `UsergridRequest`.
*/
public init(baseUrl:String,
paths:[String]? = nil,
auth:UsergridAuth? = nil,
asset:UsergridAsset) {
self.asset = asset
super.init(method: .Put, baseUrl: baseUrl, paths: paths, auth: auth)
}
private override func applyHeaders(request: NSMutableURLRequest) {
super.applyHeaders(request)
request.setValue(UsergridAssetUploadRequest.ASSET_UPLOAD_CONTENT_HEADER, forHTTPHeaderField: UsergridRequest.CONTENT_TYPE)
request.setValue(String(format: "%lu", self.multiPartHTTPBody.length), forHTTPHeaderField: UsergridRequest.CONTENT_LENGTH)
}
private static let ASSET_UPLOAD_BOUNDARY = "usergrid-asset-upload-boundary"
private static let ASSET_UPLOAD_CONTENT_HEADER = "multipart/form-data; boundary=\(UsergridAssetUploadRequest.ASSET_UPLOAD_BOUNDARY)"
private static let CONTENT_DISPOSITION = "Content-Disposition"
private static let MULTIPART_START = "--\(UsergridAssetUploadRequest.ASSET_UPLOAD_BOUNDARY)\r\n"
private static let MULTIPART_END = "\r\n--\(UsergridAssetUploadRequest.ASSET_UPLOAD_BOUNDARY)--\r\n" as NSString
private static let FORM_DATA = "form-data"
}