Equivalent Swift NSURLSession or Alamofire Curl post - swift

I have this curl post that works fine, but for the life of me I can't get it to work with either NSURLSession or Alamofire. The curl that returns fine is:
curl https://api.truevault.com/v1/vaults/XXXXXX-XXXX-XXXX-XXXX-XXXXXXXX/blobs \
-X POST \
-u yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyy: \
--form "file=#foo.pdf" \
-H "Content-Type:multipart/form-data"
No matter what variation of curl or NSURLSession I do I get a 401 error, but it completes successful with curl! Please help! Thanks!
CURRENT ALAMOFIRE ATTEMPT
let headers = ["Authorization": Config.trueVaultKey, "Content-Type": "multipart/form-data"]
Alamofire.upload(
Alamofire.Method.POST,
url!,
headers: headers,
multipartFormData: { multipartFormData in
multipartFormData.appendBodyPart(
data: dat!,
name: "file",
fileName: "license.png",
mimeType: "image/png"
)
},
encodingCompletion: { encodingResult in
switch encodingResult {
case .Success(let upload, _, _):
upload.responseString { response in
//JSON = response.result.value! as String
debugPrint(response)
print("\n\n\nREQUEST HEADER: \(response.request!.allHTTPHeaderFields!)")
print("\n\n\nREQUEST BODY: \(response.request!.HTTPBody)")
print("\n\n\nREQUEST BODY STREAM: \(response.request!.HTTPBodyStream)")
}
case .Failure(let encodingError):
print(encodingError)
}
})

try to build your URL like this :
let userAuth = "username:password" // credential
let url = "https://\(userAuth)#api.truevault.com/v1/vaults/XXXXXX-XXXX-XXXX-XXXX-XXXXXXXX/blobs" // notice the at(#) sign
do not set the headers, they will be set automatically.

Related

How to make this curl request using Almofire?

This is my curl url
curl -X POST https://fax.twilio.com/v1/Faxes \
--data-urlencode "From=+15017122661" \
--data-urlencode "To=+15558675310" \
--data-urlencode "MediaUrl=https://www.twilio.com/docs/documents/25/justthefaxmaam.pdf" \
-u ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:your_auth_token
How can i implement this in Almofire?
I am trying like this way.
AF.request(URL(string: "https://fax.twilio.com/v1/Faxes")!, method: .post, parameters: params, encoding: JSONEncoding.default, headers: headers).authenticate(username: "", password: "").responseJSON { response in
print(response)
}
how can i implement data-urlencode "From=+15017122661" in almofire?
Try this code with Alamofire:
if let url = URL(string: "https://fax.twilio.com/v1/Faxes") {
let parameters = [
"From": "+15017122661",
"To": "+15558675310",
"MediaUrl": "https://www.twilio.com/docs/documents/25/justthefaxmaam.pdf"
]
AF.request(url, method: .post, parameters: parameters, encoder: URLEncodedFormParameterEncoder.default, headers: nil, interceptor: nil)
.authenticate(username: "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", password: "your_auth_token")
.responseJSON { response in
switch response.result {
case .success(let json):
print(json)
case .failure(let error):
print(error)
}
}
}
I've tested with my creds - it should be work, but I haven't real devices for in/out fax

Upload image with Alamofire , Swift 3

For upload image to server I am using Alamofire 4.4 and Swift 3.
Swager information:
curl -X POST "url/id/upload" -H "accept: application/json" -H "Authorization: Bearer token" -H "Content-Type: multipart/form-data" -F "file=#craneB.png;type=image/png"
My Swift code:
let headers = [
"Authorization": "Bearer \(GlobalToken.appToken)",
"Content-Type": "multipart/form-data" ]
let url = BaseUrl+"1f510b93-5177-4880-447d-08d6fe7a9498"+"/upload"
let data = UIImageJPEGRepresentation(selectedImage, 0.9)
Alamofire.upload(multipartFormData: { (multipartFormData) in
if let data = data{
multipartFormData.append(data, withName: "name", fileName: "filename", mimeType: "image/png")
}
}, usingThreshold: UInt64.init(), to: url, method: .post, headers: headers) { (result) in
switch result{
case .success(let upload, _, _):
// upload.validate(statusCode: 200..<299)
upload.responseJSON{ response in
print("Succesfully uploaded")
switch response.result {
case .success(let JSON):
case .failure(_):
}
if let err = response.error{
print(err)
return
}
}
upload.uploadProgress(closure: { (progress) in
})
case .failure(let error):
print("Error in upload: \(error.localizedDescription)")
}
}
Respons:
Upload Progress: 1.0
Succesfully uploaded .
But I have error :
POST BaseUrl/1f510b93-5177-4880-447d-08d6fe7a9498/upload (500) {
Message = "Internal Server Error. - System.NullReferenceException: Object reference not set to an instance of an object. \n at
MaterialService.UploadAsync(Guid Id, IFormFile file)
I guid Id send in URL, file with multipartFormData. Upload on Sawager is work. TY

How to perform a post with Alamofire (swift) to get a security token as return value

I want to request a token via cURL using Swift Alamofire. However, I could not figure out so far how to pass on the right parameters in the right order to make it work.
The description given by Amadeus is the following:
let headers = [
"Content-Type": "application/x-www-form-urlencoded"
]
let params = [
"grant_type": "client_credentials"
]
Alamofire.request("https://test.api.amadeus.com/v1/security/oauth2/token", method: .post, parameters: params, encoding: JSONEncoding.default, headers: headers).authenticate(user: "API", password: "API").responseJSON { response in debugPrint(response)
let result = response.result.value
print(result)
}
The expected result is to get JSON file in return including the token to make API requests. any help is highly appreciated. Thanks
Let's make use of usefull debug tools of Alamofire since you have a cURL sample.
Let's break your current code:
let headers = ["Content-Type": "application/x-www-form-urlencoded"]
let params = ["grant_type": "client_credentials"]
let request = Alamofire.request("https://test.api.amadeus.com/v1/security/oauth2/token",
method: .post,
parameters: params,
encoding: JSONEncoding.default,
headers: headers).authenticate(user: "API", password: "API")
print(request.debugDescription)
request.responseJSON { response in
debugPrint(response)
let result = response.result.value
print(result)
}
Output:
$>curl -v \
-X POST \
-u API:API \
-H "Accept-Language: fr-US;q=1.0, en;q=0.9, fr-FR;q=0.8" \
-H "Accept-Encoding: gzip;q=1.0, compress;q=0.5" \
-H "User-Agent: iOSTest/1.0 (nt.iOSTest; build:1; iOS 12.2.0) Alamofire/4.8.1" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "{\"grant_type\":\"client_credentials\"}" \
"https://test.api.amadeus.com/v1/security/oauth2/token"
Let's go piece by piece:
We should forget about Accept-Encoding, User-Agent & Accept-Language headers. I'll skip them later.
We see that the -d (data into httpBody) is wrong.
Let's change that: encoding: JSONEncoding.default to encoding: URLEncoding(destination: .httpBody). Plus it makes sense since in the content type we said it was url encoded.
We get then:
$>-d "grant_type=client_credentials"
Seems better.
We see the -u API:API \ which correspond to .authenticate(user: "API", password: "API"). We might want to remove it if the server doesn't manage authentification like that and put it into the params instead.
So now, let's change the params:
let params = ["grant_type": "client_credentials",
"client_id" : "APIKey",
"client_secret" : "APISecret"]
We get:
$>-d "client_id=APIKey&client_secret=APISecret&grant_type=client_credentials" \
It should work then.
The order is not the same, but server shouldn't care about it. It should be a key/access not an index/access.
So final:
let headers = ["Content-Type": "application/x-www-form-urlencoded"]
let params = ["grant_type": "client_credentials",
"client_id" : "APIKey",
"client_secret" : "APISecret"]
let request = Alamofire.request("https://test.api.amadeus.com/v1/security/oauth2/token",
method: .post,
parameters: params,
encoding: URLEncoding(destination: .httpBody),
headers: headers)
print(request.debugDescription)
request.responseJSON { response in
debugPrint(response)
let result = response.result.value
print(result)
}
Output (with skipped headers):
$ curl -v \
-X POST \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=APIKey&client_secret=APISecret&grant_type=client_credentials" \
"https://test.api.amadeus.com/v1/security/oauth2/token"
The docs say that the parameters should include grant_type:client_credentials&client_id={client_id}&client_secret={client_secret}. Your parameters are missing the client ID and client secret. Make sure to include those by doing something like this:
let params = [
"grant_type": "client_credentials&client_id=CLIENTIDHERE&client_secret=CLIENTSECRETHERE"
]
The string that has to be passed as body is:
let params = [
"grant_type=client_credentials&client_id=CLIENTIDHERE&client_secret=CLIENTSECRETHERE"
]
I don't know much about Swift but I guess you could do:
let params = [
"grant_type": "client_credentials"
"client_id" : "Your API Key"
"client_secret" : "Your API Secret"
]

Authenticate with WhenIWork API using AlmamoFire (Swift)

UPDATED Question:
I got in touch with the WhenIWork Team and discovered that they need the username and password to be passed in the body but with our a form. So I have solved. If you look at the answer below, it works.
Thanks everyone!
I am trying to get the access token from WhenIWork using Swift and Alamofire on Xcode, the json returned Success but says "Application Not Found Error"
I've been looking for documentation from WhenIWork Doc but without success on error code. (They don't have any error in the 1xxx range)
Ideas? I am new to Swift (and coding in general) so any help would be appreciated.
Thanks!
Below is the Terminal answer:
SUCCESS: {
code = 1110;
error = "Application not found";
}
[Request]: POST https://api.wheniwork.com/2/login/
[Response]: <NSHTTPURLResponse: 0x6080000325e0> { URL: https://api.wheniwork.com/2/login/ } { status code: 401, headers {
"Access-Control-Allow-Headers" = "Authorization, Origin, X-Requested-With, W-Date-Format, Content-Type, Accept, W-Token, W-UserId, W-Key, branch";
"Access-Control-Allow-Methods" = "GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS";
"Access-Control-Allow-Origin" = "*";
"Cache-Control" = "no-cache";
Connection = "keep-alive";
"Content-Type" = "application/json";
Date = "Thu, 17 Aug 2017 17:11:08 GMT";
Server = nginx;
"Transfer-Encoding" = Identity;
"X-Database" = ro;
"X-State" = "RequestId: 0f853dd4-836f-11e7-90f4-0242e14cb0c5, LoginId: 0, AccountId: 0";
"X-Timer-Database" = "0.0052359104156494";
"X-Timer-Total" = "0.012078046798706";
} }
Code:
func logInWhenIWork() {
let parameters: Parameters = [
"username": "cxxxx#xxxx.ca",
"password": "xxxxxxx",
"W-Key": "xxxxxxxxxxxxxsxx"
]
Alamofire.request("https://api.wheniwork.com/2/login", method: .post, parameters: parameters, encoding: JSONEncoding.default).responseJSON { response in
print(response)
debugPrint(response)
if let json = response.result.value {
print("JSON: \(json)")
} else {
print(response)
}
}
I don't use Alamofire much but I tried the following:
let parameters = ["username":"user#example.com",
"password": "*******"]
let headers = ["W-Key": "iworksoharditsnotfunny"]
var req = Alamofire.request("https://api.wheniwork.com/2/login",
parameters: parameters,
encoding: JSONEncoding.default,
headers: headers)
The request ends up looking like this:
curl -v \
-H "Content-Type: application/json" \
-H "Accept-Language: en-US;q=1.0" \
-H "User-Agent: Unknown/Unknown (Unknown; build:Unknown; OS X 10.12.6) Alamofire/1.0" \
-H "W-Key: iworksoharditsnotfunny" \
-H "Accept-Encoding: gzip;q=1.0, compress;q=0.5" \
-d "{\"username\":\"user#example.com\",\"password\":\"*******\"}" \
"https://api.wheniwork.com/2/login"
Which seems to pretty much match the example given in the WhenIWork API documentation. I don't have an account so I can't test it directly.
For those of you who wanted the answer. I finally figured it out. Here it is
func logInWhenIWork() {
let url = URL(string: "https://api.wheniwork.com/2/login")!
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "POST"
urlRequest.allHTTPHeaderFields = ["W-Key": "xxxxxxxxxxx","Content-Type":"application/json"]
let parameters = ["username": "ss#xxx.ca", "password": "sssdsds"]
do {
urlRequest.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: [])
} catch {
// No-op
}
urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
Alamofire.request(urlRequest).responseJSON { response in
switch response.result {
case .success(let value):
let json = JSON(value)
// print("JSON: (json)")
let token = json["token"].stringValue
let newUserID = json["users"][0]["id"].int
print(newUserID)
self.wUserID = String(describing: newUserID)
// print(token)
self.wToken = token
if self.wToken != "" {
print("Successfully logged in")
} else {
print("Log In Failed")
}
case .failure(let error):
print(error)
}
}
}

CURL command in Alamofire with swift

I have the following working curl command which I need to run in Swift using Alamofire.
curl -k -i -d '{ "user": {"displayName":"My Test" ,"email":"test#xxtest.com","pwd":"test","roles":["stu"]}}' -H "Content-Type: application/json;charset=UTF-8" -u web:web -X POST 'https://test.herokuapp.com/xtest/auth/register'
I tried out the following method with Swift by using Alamofire. I have the impression that I do -u web:web wrong, but I have no means to confirm that.
The console gives me the following error which I don't understand:
print response object
nil
print error
Optional(Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.})
Can someone point out what is wrong in here? Thx.
This is the function which translates the CURL command into Swift
func registerNewStudent(displayName: String, email: String, password: String, completionHandler: (AnyObject?, NSError?) -> ()) {
//Basic HTTP auth
let user = "web"
let password = "web"
let credentialData = "\(user):\(password)".dataUsingEncoding(NSUTF8StringEncoding)!
let base64Credentials = credentialData.base64EncodedStringWithOptions([])
let headers = ["Authorization": "Basic \(base64Credentials)"]
//example for a nested array query
let parameters = [
"user": [
"displayName": displayName,
"email": email,
"pwd": password,
"roles":["stu"]
]
]
Alamofire.request(
.POST,
registerURL,
headers: headers,
parameters: parameters
)
.responseJSON { response in
switch response.result {
case .Success(let value):
completionHandler(value, nil)
case .Failure(let error):
completionHandler(nil, error)
}
}
}
I call this function in the following way:
func okButtonTapped(sender: UIButton) {
let displayNameText = displayNameInput.text
let emailText = emailInput.text
let passwordText = passwordInput.text
restApi.registerNewStudent(displayNameText!,emailInput: emailText!, passwordInput: passwordText!) {responseObject, error in
// use responseObject and error here
print("print response object")
print(responseObject)
print("print error")
print(error)
}
Response from the CURL call:
{"result":{"email":"trrrrrest#xxtest.com","display_name":"My Test","pwd":"test","fb_id":null,"roles":["stu"]
I could resolve it from here: http://www.ceus-now.com/curl-d-to-alamofire/
Adding the following line after the JSON response did the trick (not before).
.authenticate(user: "web", password: "web")
so the method looks like:
Alamofire.request(
.POST,
registerURL,
parameters: parameters
)
.responseJSON { response in
switch response.result {
case .Success(let value):
completionHandler(value, nil)
case .Failure(let error):
completionHandler(nil, error)
}
}
.authenticate(user: "web", password: "web")
}