Adding headers to Alamofire request (with ephemeral session) - ios

I'm trying to add headers into AlamoFire requests.
It works well when I use the following code:
let manager = Manager.sharedInstance
manager.session.configuration.HTTPAdditionalHeaders = [
"Authorization": "Bearer \(accessToken!)" ]
However, when I need to user an ephemeral session it does not work with the following code.
let configuration = NSURLSessionConfiguration.ephemeralSessionConfiguration()
let manager = Manager(configuration: configuration)
manager.session.configuration.HTTPAdditionalHeaders = [
"Authorization": "Bearer \(accessToken!)" ]
Am I missing something?
Thanks in advance,

You have to ensure your manager is retained, you could do it by setting it as a stored property. You'll find more informations here: https://github.com/Alamofire/Alamofire/issues/157
let customManager: Manager?
init() {
let configuration = NSURLSessionConfiguration.ephemeralSessionConfiguration()
self.customManager = Manager(configuration: configuration)
self.customManager!.session.configuration.HTTPAdditionalHeaders = [
"Authorization": "Bearer \(accessToken!)" ]
}
func yourFunc() {
let URL = NSURL(string: identityURL)
var mutableURLRequest = NSMutableURLRequest(URL: URL!)
let request = self.customManager!.request(mutableURLRequest)
request.responseJSON {
(request, response, data, error) in
if let response = response {
// Your code
}
}

func HTTPHeader(param : NSDictionary)
{
var username: AnyObject? = param[kAPIUsername]
var password: AnyObject? = param[kAPIPassword]
var str = "\(username!):\(password!)"
let base64Encoded = BaseVC.sharedInstance.encodeStringToBase64(str)
Manager.sharedInstance.session.configuration.HTTPAdditionalHeaders = [
"Authorization": "Basic \(base64Encoded)",
]
}
func encodeStringToBase64(str : String) -> String
{
// UTF 8 str from original
// NSData! type returned (optional)
let utf8str = str.dataUsingEncoding(NSUTF8StringEncoding)
// Base64 encode UTF 8 string
// fromRaw(0) is equivalent to objc 'base64EncodedStringWithOptions:0'
// Notice the unwrapping given the NSData! optional
// NSString! returned (optional)
let base64Encoded = utf8str!.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))
return base64Encoded;
}
func GET()
{
HTTPHeader(param, token: token)
request(.GET, API URL , encoding: .JSON)
.progress { bytesWritten, totalBytesWritten, totalBytesExpectedToWrite in
//progress
}
.responseJSON {
(request, response, json, error) -> Void in
//get response here
}
}
might be help with link: how to use Alamofire with custom headers

Related

How to post the data in encoding structure?

I am using two models GET and POST which are encodable and decodable
using the below code i am able to get the data in GET model, but i am not able to post the data with POST model.
please guide me how to post the data using POST model
let url = URL(string: "<YOUR URL HERE>")
let config = URLSessionConfiguration.default
config.httpAdditionalHeaders = [
"Accept" : "application/json",
"Content-Type" : "application/x-www-form-urlencoded"
]
let session = URLSession(configuration: config)
var request = URLRequest(url: url!)
request.encodeParameters(parameters: ["username": username, "password":
password])
let task = session.dataTask(with: request) { data, response, error in
guard let data = data else { return }
do {
let sentPost = try JSONDecoder().decode(Get.self, from: data)
print(sentPost)
} catch {}
}
task.resume()
model
struct Post: Encodable, Decodable {
let username: String
let password: String
}
extension for URLRequest
extension URLRequest {
private func percentEscapeString(_ string: String) -> String {
var characterSet = CharacterSet.alphanumerics
characterSet.insert(charactersIn: "-._* ")
return string
.addingPercentEncoding(withAllowedCharacters: characterSet)!
.replacingOccurrences(of: " ", with: "+")
.replacingOccurrences(of: " ", with: "+", options: [], range: nil)
}
mutating func encodeParameters(parameters: [String : String]) {
httpMethod = "POST"
let parameterArray = parameters.map { (arg) -> String in
let (key, value) = arg
return "\(key)=\(self.percentEscapeString(value))"
}
httpBody = parameterArray.joined(separator: "&").data(using: String.Encoding.utf8)
}
}
You don't need to create another string and then to data. This will be handled by Codable protocol and your JSONEncoder. You need to encode your post type using JSONEncoder and provide the data to the request.httpBody
Try this:
let url = URL(string: "<YOUR URL HERE>")
let config = URLSessionConfiguration.default
config.httpAdditionalHeaders = [
"Accept" : "application/json",
"Content-Type" : "application/x-www-form-urlencoded"
]
do {
let aPost = Post(username: "username", password: "password")
let encoder = JSONEncoder()
let encodedPost = try encoder.encode(aPost)
let session = URLSession(configuration: config)
var request = URLRequest(url: url!)
request.httpMethod = "POST"
request.httpBody = encodedPost
let task = session.dataTask(with: request) { data, response, error in
do {
let sentPost = try JSONDecoder().decode(Get.self, from: data)
print(sentPost)
} catch {
print(error.localizedDescription)
}
}
task.resume()
} catch {
print(error.localizedDescription)
}

Post request with HTTP header parameters

I Want to use Bittrex api. I've read their api docs. There are explanations like the following.
For this version, we use a standard HMAC-SHA512 signing. Append apikey
and nonce to your request and calculate the HMAC hash and include it
under an apisign header.
$apikey='xxx';
$apisecret='xxx';
$nonce=time();
$uri='https://bittrex.com/api/v1.1/market/getopenorders?apikey='.$apikey.'&nonce='.$nonce;
$sign=hash_hmac('sha512',$uri,$apisecret);
$ch = curl_init($uri);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('apisign:'.$sign));
$execResult = curl_exec($ch);
$obj = json_decode($execResult);
I want to do this with Swift. But I don't want to use Alamofire.
I wrote a code. I think I'm doing everything but I'm getting the following error.
{
message = "APISIGN_NOT_PROVIDED";
result = "<null>";
success = 0;
}
I wrote similar code with Delphi. It works fine. So there is no problem with APIKEY. When I use the same parameters in Delphi, the same SecretHex is generated. So there's no problem with Encryption.
I think, I cannot do the Post Request with headers.
I can not find the fault. Would you please help me.
func getBalances()
{
let apiKeySTR = "01235xxxxxx"
let secretSTR = "41691xxxxxx"
let path = "https://bittrex.com/api/v1.1/account/"
let timeInterval = NSDate().timeIntervalSince1970
let epochtime = String(floor(timeInterval))
let urlFull = path + "getbalances" + "?" + "apikey=" + apiKeySTR + "&" + "nonce=" + epochtime
let secretUInt8 : [UInt8] = Array(urlFull.utf8)
var secretKey : [UInt8]?
do {
try secretKey = HMAC(key: secretSTR, variant: .sha512).authenticate(secretUInt8)
} catch {
print ("Error")
}
let secretHex = secretKey?.toHexString() ?? ""
guard let url = URL(string: urlFull) else { return }
var request = URLRequest(url: url)
request.addValue("apising", forHTTPHeaderField: (secretHex))
request.httpMethod = "POST"
let session = URLSession.shared
session.dataTask(with: request) { (data, response, error) in
if let response = response {
print(response)
}
if let data = data {
do {
let json = try JSONSerialization.jsonObject(with: data, options: [])
print(json)
} catch {
print(error)
}
}
}.resume()
}
First off... you have a typo:
request.addValue("apising", forHTTPHeaderField: (secretHex))
I believe it's apisign, not "apising", right?
And below is a recap on creating REST API requests with a header and body. You can update this method according your needs:
1) Create URLRequest
var request = URLRequest(url: requestURL)
2) Set headers and http method:
request.allHTTPHeaderFields = ["Authentication" : "Bearer XYZ..."]
request.httpMethod = "POST"
3) Set request body:
// parameters is a simple [String:String] dictionary, just as header
let jsonData = try? JSONSerialization.data(withJSONObject: parameters)
request.httpBody = jsonData
Complete example:
public enum RESTMethod:String {
case get = "GET"
case post = "POST"
case put = "PUT"
}
public func sendRequest(_ url: String,
method: RESTMethod,
headers: [String : String],
parameters: [String : Any],
completionHandler: #escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionTask! {
let requestURL: URL
if method == .get {
let parameterString = parameters.stringFromHttpParameters()
requestURL = URL(string:"\(url)?\(parameterString)")!
} else {
requestURL = URL(string: url)!
}
var request = URLRequest(url: requestURL)
request.allHTTPHeaderFields = headers
request.httpMethod = method.rawValue
if method == .post {
let jsonData = try? JSONSerialization.data(withJSONObject: parameters)
request.httpBody = jsonData
}
request.timeoutInterval = 60
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
completionHandler(data,response,error)
}
task.resume()
return task
}
extension Dictionary {
/// Build string representation of HTTP parameter dictionary of keys and objects
func stringFromHttpParameters() -> String {
let parameterArray = self.map { (key, value) -> String in
let percentEscapedKey = (key as! String).addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
let percentEscapedValue = (value as? String ?? "\(value)").addingPercentEncodingForURLQueryValue()!
return "\(percentEscapedKey)=\(percentEscapedValue)"
}
return parameterArray.joined(separator: "&")
}
}
Usage:
sendRequest("http://yourserver",
method: .get, // .post or .put
headers: [],
parameters: [],
completionHandler: { (data, response, error) in
// Handle response here
})

POST body values are not recognized

I am calling a POST API but the post values are not getting recognised.
I am using alamofire for API handling
public func POSTRequest(postData : AnyObject?,APIName : String?,headers: HTTPHeaders?,success:#escaping (JSON) -> Void, failure:#escaping (String,String) -> Void)
{
let url = URL(string: APIName!)!
var urlRequest = URLRequest(url: url)
urlRequest.httpBody = postData as? Data
urlRequest.httpMethod = "POST"
urlRequest.allHTTPHeaderFields = headers
let manager = Alamofire.SessionManager.default
manager.session.configuration.timeoutIntervalForRequest = 30.0
manager.request(urlRequest).responseJSON { ( responseData) -> Void in
if responseData.result.isSuccess {
let statusCode = responseData.response?.statusCode
if(statusCode == 200){
let resJson = JSON(responseData.result.value!)
success(resJson)
}
else {
let resJson = JSON(responseData.result.value!)
let errorMsg = resJson["message"].stringValue
let errorTitle = resJson["title"].stringValue
failure(errorMsg,errorTitle)
}
}
if responseData.result.isFailure {
let error : Error = responseData.result.error!
failure(error.localizedDescription,"")
}
}
}
// MARK: Login
func userLogin(postData: AnyObject, completionHandler:#escaping (JSON) -> Void,failure:#escaping (String,String) -> Void)
{
let apiName = GlobalConstants.rootUrl + GlobalConstants.loginUrl
let httpHeaders: HTTPHeaders = getHeaders()
ApiRequestHandler.shared.POSTRequest(postData: postData, APIName: apiName, headers: httpHeaders, success: { (JSON) in
print("JSON \(JSON)")
completionHandler(JSON)
})
{ (Errormsg,ErrorTitle) in
print("Error \(Errormsg)")
failure(Errormsg,ErrorTitle)
}
}
I am creating the post data here
let postDataDct = NSMutableDictionary()
postDataDct.setValue(self.userNameTextField.text, forKey: "username")
postDataDct.setValue(self.phoneNumberTextField.text, forKey: "mobile")
guard let data = try? JSONSerialization.data(withJSONObject:
postDataDct , options: JSONSerialization.WritingOptions.prettyPrinted)
as NSData else {
return;
}
print(NSString(data: data as Data, encoding:
String.Encoding.utf8.rawValue)! as String)
header creation here
func getHeaders() -> HTTPHeaders {
let headers: HTTPHeaders = ["Content-Type": "application/json" ,"Authorization" : "Basic dGFuaXNocWdfgaFF%waXJvb3Q6dzBEMFlkSnR0"]
return headers
}
I am calling the login method here
ApiManager.shared.userLogin(postData: postDataDct as AnyObject, completionHandler: { (JSON) in
print(JSON)
})
{ (ErrorMsg, ErrorTitle) in
print(ErrorMsg)
}
Please help me to find the issue.
API is giving me error response, saying user name or password is empty.
For Posting Alamofire have its own Parameters Class Try to use that like this with make share using the exact keys as on server.
let parameter: Parameters = [
"Email": txtfld_email.text!,
"Password": txtfld_password.text!
]
Cross check your keys:
let postDataDct = NSMutableDictionary()
postDataDct.setValue(self.userNameTextField.text, forKey: "username")
postDataDct.setValue(self.phoneNumberTextField.text, forKey: "mobile")
You are making the request with username and mobile It seems like the keys will be username and password according to the response you are getting name or password is empty.
let postDataDct = NSMutableDictionary()
postDataDct.setValue(self.userNameTextField.text, forKey: "username")
postDataDct.setValue(self.phoneNumberTextField.text, forKey: "password")
Suggestion:
Don't use NSMutableDictionary in Swift, use its native Swift
counterpart, Dictionary

Post method request Alamofire

I'm using Swift 3 and Alamofire 4.0.
I want to create similar Alamofire POST request as Postman request shown in screenshot:
I've tried with these lines of code:
var parameters: [String: Any] = [
"client_id" : "xxxxxx",
"client_secret" : "xxxxx",
"device_token" : "xxxx",
"fullname" : "xxxxx",
"gender": "xxx"
]
Alamofire.request(url, method: .post, parameters: parameters).responseJSON { response in
print(response)
}
But I got this error:
How to implement POST request with Body as form-data using Alamofire in Swift 3?
Swift 3.0 - Alamofire - Working code for multipart form data upload *
// Parameters
let params: [String : String] =
["UserId" : "\(userID)",
"FirstName" : firstNameTF.text!,
"LastName" : lastNameTF.text!,
"Email" : emailTF.text!
]
// And upload
Alamofire.upload(
multipartFormData: { multipartFormData in
for (key, value) in params
{
multipartFormData.append((value.data(using: .utf8))!, withName: key)
}
},
to: url,
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON { response in
debugPrint(response)
}
upload.uploadProgress(queue: DispatchQueue(label: "uploadQueue"), closure: { (progress) in
})
case .failure(let encodingError):
print(encodingError)
}
}
)
Let me know if you still have issues with it.
after too much try I have succeded so try this
override func viewDidLoad() {
super.viewDidLoad()
let parameters: Parameters = ["client_id": "1","user_token":"xxxxxxxx"]
// Do any additional setup after loading the view, typically from a nib.
let url = "http://xxxxxxxxxxx/index.php/Web_api/get_client_profile"
//let timeParameter = self.getLastTimeStamp()
self.request = Alamofire.request(url, method: .post, parameters:parameters)
if let request = request as? DataRequest {
request.responseString { response in
//PKHUD.sharedHUD.hide()
do{
let dictionary = try JSONSerialization.jsonObject(with: response.data!, options: JSONSerialization.ReadingOptions.allowFragments) as! NSDictionary
print(dictionary)
}catch{
}
}
}
}
var request: Alamofire.Request? {
didSet {
//oldValue?.cancel()
}
}
You can post a request using Alamofire.
let url = ""
let headers = [ "Content-Type" : "application/json"]
let para : Parameters = [ "data" : JSONObject]
Alamofire.request(url, method: .post, parameters: para, encoding: JSONEncoding.default, headers : headers)
.responseJSON { response in
print(response)
print(response.result)
}
Nothing to worry about.
Alamofire request method not changed so much(For Swift 3.0) if in case you know how to do that in Swift 2.0/2.2. If you understand the old method then you can easily understand this one also. Now lets take a closer look on the following boilerplate -
Alamofire.request(apiToHit, method: .post, parameters: parametersObject, encoding: JSONEncoding.default, headers: headerForApi).responseJSON { response in switch response.result{
case .success(_):
if let receivedData: Any = response.result.value{
if let statusCode: Int = response.response?.statusCode {
//Got the status code and data. Do your data pursing task from here.
}
}else{
//Response data is not valid, So do some other calculations here
}
case .failure(_):
//Api request process failed. Check for errors here.
}
Now here in my case -
apiToHit //Your api url string
.post //Method of the request. You can change this method as per you need like .post, .get, .put, .delete etc.
parametersObject // Parameters needed for this particular api. Same in case you are sending the "body" on postman etc. Remember this parameters should be in form of [String: Any]. If you don't need this then you can just pass nil.
JSONEncoding.default //This the encoding process. In my case I am setting this as .default which is expected here. You can change this to .prettyPrinted also if you need.
headerForApi //This is the header which you want to send while you are requesting the api. In my case it is in [String: String] format. If you don't need this then you can just pass nil.
.responseJSON //Expecting the response as in JSON format. You can also change this as you need.
Now, in my request I am using Switch inside the request closure to check the result like response in switch response.result{.
Inside case .success(_): case I am also checking for result data and http status code as well like this
if let receivedData: Any = response.result.value{
if let statusCode: Int = response.response?.statusCode {
}
}
Hope this helped. Thanks.
class func alamofireMethod(methods: Alamofire.HTTPMethod , url : URLConvertible , parameters : [String : Any],need_flag_inside : Bool = false, paramJson : Bool = true ,need_loader : Bool = true,Header: [String: String],handler:#escaping CompletionHandler,errorhandler : #escaping ErrorHandler)
{
if NetworkController.sharedInstance.checkNetworkStatus()
{
var alamofireManager : Alamofire.SessionManager?
var hed = Header
if let tok = UserDefaults.standard.value(forKey: "TOKEN") as? String {
hed = ["Authorization":"Bearer \(tok)"]
}
if need_loader {
// DELEGATE.showLoader()
}
var UrlFinal = ""
do
{
try UrlFinal = baseURL + url.asURL().absoluteString
}
catch{}
let configuration = URLSessionConfiguration.default
configuration.timeoutIntervalForResource = 25
configuration.timeoutIntervalForRequest = 25
configuration.httpAdditionalHeaders = hed
alamofireManager = Alamofire.SessionManager(configuration: configuration)
alamofireManager = Alamofire.SessionManager.default
let json = JSON(parameters)
guard let jsonDict = json.dictionaryObject else {
return
}
var jsonData = Data()
do {
jsonData = try JSONSerialization.data(withJSONObject: jsonDict, options: [])
} catch {
//handle error
print(error)
}
var request = URLRequest(url: URL(string: UrlFinal)!)
request.httpMethod = methods.rawValue
if methods == .post || methods == .put
{
//check here
if paramJson {
hed["Content-Type"] = "application/json"
request.httpBody = jsonData
}else{
let postString = self.getPostString(params: parameters)
request.httpBody = postString.data(using: .utf8)
}
}
request.allHTTPHeaderFields = hed
Alamofire.request(request).responseJSON(queue: nil, options: JSONSerialization.ReadingOptions.allowFragments) { (response) in
print(parameters)
print(UrlFinal)
print(hed)
// DELEGATE.hideLoader()
if response.result.isSuccess
{
print(response)
handler(response.result.value! as AnyObject)
}
else if response.response?.statusCode == 401
{
// DELEGATE.redirectToLogin()
// DELEGATE.showToast(message: "Token Expired")
}
else{
// DELEGATE.showToast(message: default_failure)
errorhandler(response.result.error! as NSError)
print(response.result.error as Any)
}
}
}else{
// DELEGATE.showToast(message: "Please check your internet connection.")
}
}
Alomofire With Post and Put Method In swift

Send SMS with Twilio in Swift

I try to use Twilio as an service provider but they have no examples for Swift that I understand.
My task is to send SMS to a number using Twilio API with Swift.
I have a Twilio.com account - and that one is working. But how do I do this in Swift code in a easy manner.
Twilio does provide a library - but that is meant for C# not for Swift (and using a bridging header seems too complicated!)
Here is the C# example, I need a easy Swift example.
// Download the twilio-csharp library from twilio.com/docs/csharp/install
using System;
using Twilio;
class Example
{
static void Main(string[] args)
{
// Find your Account Sid and Auth Token at twilio.com/user/account
string AccountSid = "AC5ef8732a3c49700934481addd5ce1659";
string AuthToken = "{{ auth_token }}";
var twilio = new TwilioRestClient(AccountSid, AuthToken);
var message = twilio.SendMessage("+14158141829", "+15558675309", "Jenny please?! I love you <3", new string[] {"http://www.example.com/hearts.png"});
Console.WriteLine(message.Sid);
}
}
Twilio evangelist here.
To send a text message from Swift you can just make a request directly to Twilios REST API. That said, I would not recommend doing this from an iOS app (or any other client app) as it requires you to embed your Twilio account credentials in the app, which is dangerous. I would instead recommend sending the SMS from a server side application.
If you do want to send the message from your app, there are a couple of Swift libraries I know of that simplify making HTTP requests:
Alamofire - from Mattt Thompson, creator of AFNetworking - used in the example here: https://www.twilio.com/blog/2016/11/how-to-send-an-sms-from-ios-in-swift.html
SwiftRequest - from Ricky Robinett of Twilio
To make the request using SwiftRequest, it would look like this:
var swiftRequest = SwiftRequest();
var data = [
"To" : "+15555555555",
"From" : "+15555556666",
"Body" : "Hello World"
];
swiftRequest.post("https://api.twilio.com/2010-04-01/Accounts/[YOUR_ACCOUNT_SID]/Messages",
auth: ["username" : "[YOUR_ACCOUNT_SID]", "password" : "YOUR_AUTH_TOKEN"]
data: data,
callback: {err, response, body in
if err == nil {
println("Success: \(response)")
} else {
println("Error: \(err)")
}
});
Hope that helps.
recently I have gone through Twilio docs and few SO post.
you can send SMS with following code snip in Swift 2.0
func sendSMS()
{
let twilioSID = "your Sender ID here"
let twilioSecret = "your token id here"
//Note replace + = %2B , for To and From phone number
let fromNumber = "%2B14806794445"// actual number is +14803606445
let toNumber = "%2B919152346132"// actual number is +919152346132
let message = "Your verification code is 2212 for signup with <app name here> "
// Build the request
let request = NSMutableURLRequest(URL: NSURL(string:"https://\(twilioSID):\(twilioSecret)#api.twilio.com/2010-04-01/Accounts/\(twilioSID)/SMS/Messages")!)
request.HTTPMethod = "POST"
request.HTTPBody = "From=\(fromNumber)&To=\(toNumber)&Body=\(message)".dataUsingEncoding(NSUTF8StringEncoding)
// Build the completion block and send the request
NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: { (data, response, error) in
print("Finished")
if let data = data, responseDetails = NSString(data: data, encoding: NSUTF8StringEncoding) {
// Success
print("Response: \(responseDetails)")
} else {
// Failure
print("Error: \(error)")
}
}).resume()
}
if everything goes fine..You should receive message like this..
Here is the new Swift example for Passwordless authentication. For the complete tutorial, Click Here
let url = "http://localhost:8000"
var swiftRequest = SwiftRequest()
var params:[String:String] = [
"token" : token!.text
]
swiftRequest.post(url + "/user/auth/", data: params, callback: {err, response, body in
if( err == nil && response!.statusCode == 200) {
if((body as NSDictionary)["success"] as Int == 1) {
self.showAlert("User successfully authenticated!");
} else {
self.showAlert("That token isn't valid");
}
} else {
self.showAlert("We're sorry, something went wrong");
}
})
If You are using server side Swift with Perfect.org
See this Blog
http://perfecttwilio.blogspot.in
The answer by "Devin Rader" is perfect. For any other users like me, the following is the full converted code for SwiftRequest for swift 3.0. The original code is by Ricky Robinett.
Please let us know if any errors.
Thankx..
//
// SwiftRequest.swift
// SwiftRequestTest
//
// Created by Ricky Robinett on 6/20/14.
// Copyright (c) 2015 Ricky Robinett. All rights reserved.
//
// ***********************************************************
//
// Modification for Swift 3.0 by Sanjay Sampat on 21.Jun.2017
//
// ***********************************************************
import Foundation
public class SwiftRequest {
var session = URLSession.shared
public init() {
// we should probably be preparing something here...
}
// GET requests
public func get(url: String, auth: [String: String] = [String: String](), params: [String: String] = [String: String](), callback: ((_ err: NSError?, _ response: HTTPURLResponse?, _ body: AnyObject?)->())? = nil) {
let qs = dictToQueryString(data: params)
request(options: ["url" : url, "auth" : auth, "querystring": qs ], callback: callback )
}
// POST requests
public func post(url: String, data: [String: String] = [String: String](), auth: [String: String] = [String: String](), callback: ((_ err: NSError?, _ response: HTTPURLResponse?, _ body: AnyObject?)->())? = nil) {
let qs = dictToQueryString(data: data)
request(options: ["url": url, "method" : "POST", "body" : qs, "auth" : auth] , callback: callback)
}
// Actually make the request
func request(options: [String: Any], callback: ((_ err: NSError?, _ response: HTTPURLResponse?, _ body: AnyObject?)->())?) {
if( options["url"] == nil ) { return }
var urlString = options["url"] as! String
if( options["querystring"] != nil && (options["querystring"] as! String) != "" ) {
let qs = options["querystring"] as! String
urlString = "\(urlString)?\(qs)"
}
let url = NSURL(string:urlString)
let urlRequest = NSMutableURLRequest(url: url! as URL)
if( options["method"] != nil) {
urlRequest.httpMethod = options["method"] as! String
}
if( options["body"] != nil && options["body"] as! String != "" ) {
var postData = (options["body"] as! String).data(using: String.Encoding.ascii, allowLossyConversion: true)
urlRequest.httpBody = postData
urlRequest.setValue("\(postData!.count)", forHTTPHeaderField: "Content-length")
}
// is there a more efficient way to do this?
if( options["auth"] != nil && (options["auth"] as! [String: String]).count > 0) {
var auth = options["auth"] as! [String: String]
if( auth["username"] != nil && auth["password"] != nil ) {
let username = auth["username"]
let password = auth["password"]
var authorization = "\(username!):\(password!)"
if let data = authorization.data(using: String.Encoding.utf8) {
//authorization = "Basic " + data.base64EncodedString(options: [])
authorization = "Basic " + data.base64EncodedString()
}
urlRequest.setValue(authorization, forHTTPHeaderField: "Authorization")
}
}
let task = session.dataTask(with: urlRequest as URLRequest, completionHandler: {body, response, err in
let resp = response as! HTTPURLResponse?
if( err == nil) {
if let gotResponse = response {
if(gotResponse.mimeType == "text/html") {
let bodyStr = NSString(data: body!, encoding:String.Encoding.utf8.rawValue)
return callback!(err as NSError?, resp, bodyStr)
} else if(gotResponse.mimeType == "application/xml") {
let bodyStr = NSString(data: body!, encoding:String.Encoding.utf8.rawValue)
return callback!(err as NSError?, resp, bodyStr)
} else if(gotResponse.mimeType == "application/json") {
// ss pending
do {
let jsonAnyObject:AnyObject = try JSONSerialization.jsonObject(with: (body! as NSData) as Data, options: JSONSerialization.ReadingOptions.mutableContainers) as! [String: AnyObject] as AnyObject
return callback!(err as NSError?, resp, jsonAnyObject as AnyObject);
} catch _ {
}
}
}
}
return callback!(err as NSError?, resp, body as AnyObject)
})
task.resume()
}
func request(url: String, callback: ((_ err: NSError?, _ response: HTTPURLResponse?, _ body: AnyObject?)->())? = nil) {
request(options: ["url" : url ], callback: callback )
}
private func dictToQueryString(data: [String: String]) -> String {
var qs = ""
for (key, value) in data {
let encodedKey = encode(value: key)
let encodedValue = encode(value: value)
qs += "\(encodedKey)=\(encodedValue)&"
}
return qs
}
private func encode(value: String) -> String {
let queryCharacters = NSCharacterSet(charactersIn:" =\"#%/<>?#\\^`{}[]|&+").inverted
if let encodedValue:String = value.addingPercentEncoding(withAllowedCharacters: queryCharacters) {
return encodedValue
}
//let encodedValue:String = value.stringByAddingPercentEncodingWithAllowedCharacters(queryCharacters)!
return value
}
}
Sample code to use above class as mentioned by "Devin Rader"
let URL = "https://api.twilio.com/2010-04-01/Accounts/\(myUserIdForBulkSmsMessageSending)/Messages"
var swiftRequest = SwiftRequest();
var data = [
"To" : "+\(replaceNumberToSendSms)",
"From" : "+\(replaceNumberFromSendSms)",
"Body" : message,
"MediaUrl" : theUrlEncodedMessage
];
//print( "=========VV==========" )
//print( "URL: \(URL) " )
//print( "data: \(String(describing: data))" )
//print( "auth: \(myUserIdForBulkSmsMessageSending) \(myUserPasswordForBulkSmsMessageSending)")
//print( "=====================" )
swiftRequest.post(url: URL,
data: data,
auth: ["username" : myUserIdForBulkSmsMessageSending, "password" : myUserPasswordForBulkSmsMessageSending],
callback: {err, response, body in
if err == nil {
print("Success: \(String(describing: response))")
if let currentBody = body {
// SSTODO PENDING TO HANDLE SUCCESS OF TWILLO OR ERRORS HANDLING OF TWILLO.
//print( "=====================" )
//print( " currentBody: \(currentBody) " )
//print( " currentBodyString: \(String(describing: currentBody)) ")
//print( "=========^^==========" )
}
} else {
print("Error: \(String(describing: err))")
}
});
Swift 3 version:
func sendSMS()
{
print("Starting...")
let twilioSID = "ENRET YOUR SID"
let twilioSecret = "YOUR TOKEN"
//Note replace + = %2B , for To and From phone number
let fromNumber = "%29999999"// actual number is +9999999
let toNumber = "%29999999"// actual number is +9999999
let message = "Your verification code is 2212 for signup with"
// Build the request
let request = NSMutableURLRequest(url: URL(string:"https://\(twilioSID):\(twilioSecret)#api.twilio.com/2010-04-01/Accounts/\(twilioSID)/SMS/Messages")!)
request.httpMethod = "POST"
request.httpBody = "From=\(fromNumber)&To=\(toNumber)&Body=\(message)".data(using: .utf8)
// Build the completion block and send the request
URLSession.shared.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) in
print("Finished")
if let data = data, let responseDetails = NSString(data: data, encoding: String.Encoding.utf8.rawValue) {
// Success
print("Response: \(responseDetails)")
} else {
// Failure
print("Error: \(error)")
}
}).resume()
}

Resources