I am using a post API method like this
AF.request("http://40.86.255.119/api/Authentication", method:.post, parameters: parameters,encoding: JSONEncoding.default) .responseJSON { (response) in
print(response)
}
It's showing me a response
success({
data = {
security = (
);
token = "eyJhbGc";
};
key = "<null>";
message = "Login Successfully";
succeed = 1;
})
I need to print just a token of data and need to know how can I do this?
Response screenshot by swagger
I try to like this but the issue is how ill show token that is inside the data array. It's showing a message which is outside an array but the token is inside an array.
AF.request("http://40.86.255.119/api/Authentication", method: .post, parameters: parameters, encoding: JSONEncoding.default)
.responseJSON { response in
switch response.result {
case .success(let value):
if let json = value as? [String: Any] {
print(json)
print(json["message"]) //this work
print(json["data"]["token"]) //this didnt work
}
case .failure(let error):
print(error)
}
}
I highly recommend to take advantage of the JSON decoding capabilities of AF.
Create two structs
struct Response : Decodable { let data : TokenData }
struct TokenData : Decodable { let token : String }
And replace .responseJSON with .responseDecodable and an appropriate type annotation of response.
In any case you should handle the potential error
AF.request("http://40.86.255.119/api/Authentication", method:.post, parameters: parameters) .responseDecodable { (response : DataResponse<Response,AFError>) in
switch response.result {
case .success(let result): print(result.data.token)
case .failure(let error): print(error)
}
}
Related
i am trying to send an image to an api using alamofire heres what i got:
var uploadedProfileImage: UIImage = UIImage()
let body: Parameters = [
"profilePic": uploadedProfileImage,
"name": "John Doe"
]
Alamofire.request(BASE_URL",method: .post,parameters: body,encoding: JSONEncoding.default).responseData { response in
debugPrint("All Response Info: \(response)")
if let data = response.result.value, let utf8Text = String(data: data, encoding: .utf8) {
print("Data: \(utf8Text)")
}
}
so this is the code i am using uploadProfileImage has an image that the user picked from the library and my api receives a json body parameter in which it has profilePic which is off type file when i run this its giving me an error saying 'Invalid type in JSON write (UIImage)'.theres is also a terminating with uncaught exception of type NSException error. what am i doing wrong and how to fix it?
You can't upload image with
"profilePic": uploadedProfileImage
as it's used for types that are encode-able such as strings , you need
upload image to server using Alamofire
func uploadImageAndData(_ url:String,parameters1:Parameters,headers1:HTTPHeaders,images:[UIImage]){
Alamofire.upload(multipartFormData: { multipartFormData in
// import image to request
var i=0
for imageData in images {
// multipartFormData.append(self.resizeImage(image: imageData, targetSize: CGSize(width: 400, height:
multipartFormData.append(imageData.pngData()!, withName: "image", fileName: "image"+".jpeg", mimeType: "image/jpeg")
i += 1
}
for (key, value) in parameters1 {
multipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
}
} ,to: url,method:.post,
headers:[:],
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.uploadProgress(closure: { (Progress) in
print("Upload Progress: \(Progress.fractionCompleted)")
//SwiftSpinner.show(progress: Progress.fractionCompleted*100, title: "تحميل")
})
upload.responseJSON { response in
switch response.response?.statusCode {
case 200 :
break
case 400 :
break
case 401 :
break
case 302 :
break
case 500 :
break
default: break
}
}
return
case .failure(let encodingError):
}
})
}
var head = [String:Any]()
head["Accept"]="application/json"
head["Authorization"] = "Bearer \(tokenIfExists)"
the ServiceKey I got for the api is mixed with complex characters, like D%2FFgugDIl1le9xiY7be1ge%2B0Q%3D%3D
and when I put the key in the params of alamofire and use the .get keyword, my key transforms and when the url is actually created, it becomes a totally different key.
is there any way to solve this problem?
This is the code I am using
Alamofire.request(BusURL, method: .get, parameters: ["cityCode": 25, "routeId":"DJB30300052ND", "ServiceKey": key])
.responseString { response in
print(" - API url: \(String(describing: response.request!))") // original url request
var statusCode = response.response?.statusCode
switch response.result {
case .success:
print("status code is: \(String(describing: statusCode))")
if let string = response.result.value {
print("XML: \(string)")
}
case .failure(let error):
statusCode = error._code // statusCode private
print("status code is: \(String(describing: statusCode))")
print(error)
}
}
Try below:
let params = ["cityCode": "25", "routeId":"DJB30300052ND"]
var urlParams = params.flatMap({ (key, value) -> String in
return "\(key)=\(value)"
}).joined(separator: "&")
let key = "&ServiceKey=D%2FFgugDIl1le9xiY7be1ge%2B0Q%3D%3D"
urlParams.append(key)
let url = "https://google.com?\(urlParams)"
print("url\(url)")
Alamofire.request(url, method: .get).validate().responseString(completionHandler: {response in
switch response.result{
case .success:
let s = response.result.value ?? "Empty Result"
print("response \(s)")
case .failure:
print("Call Failed")
debugPrint(response)
}
})
output: https://google.com?cityCode=25&routeId=DJB30300052ND&ServiceKey=D%2FFgugDIl1le9xiY7be1ge%2B0Q%3D%3D
I am using Async library found here in order to wait for first alamofire request to complete before running my second from the ViewDidLoad. The library seems simple to use but I can never get the first request to wait. My code is as follows:
let group = AsyncGroup()
group.utility
{
self.getToken()
}
group.wait()
self.getDevices()
I would like the getToken function to complete the Alamofire request and its completion handler before moving on to the getDevices request. Both are very simple Alamofire requests.
EDIT:
This is the getToken request. The token variable is not getting updated with the alamofire response before second alamofire request is being called.
func getToken()
{
let httpheader: HTTPHeaders =
[
"Content-Type": "application/json"
]
// Dev
let param = [params here]
Alamofire.request("url", method: .post, parameters: param, encoding: JSONEncoding.default, headers:httpheader).validate()
.responseData { response in
switch response.result {
case .success:
if let data = response.data {
let xml = SWXMLHash.parse(data)
token = (xml["authResponse"] ["authToken"].element?.text)!
}
case .failure:
print ("error")
}
}
}
Your getToken looks more like:
func getToken(whenDone:(String?)->()) {
let httpheader: HTTPHeaders = [
"Content-Type": "application/json"
]
// Dev
let param = [params here]
Alamofire.request("url", method: .post, parameters: param, encoding: JSONEncoding.default, headers:httpheader).validate()
.responseData { response in
switch response.result {
case .success:
if let data = response.data {
let xml = SWXMLHash.parse(data)
token = (xml["authResponse"] ["authToken"].element?.text)!
whenDone(token)
}
case .failure:
print ("error")
whenDone(nil)
}
}
}
and the calling sequence just becomes:
getToken() { token ->
guard let token = token else {
return
}
getDevices()
}
i'n trying to do some request on the MapMyFitness API (Oauth2).
I can get my Authorization Code with the oauth2 identification, but now i need to request to some route.
Here is the request :
Alamofire.request(self.oauthClient.baseURL() + "workout/",
method: .get,
parameters: nil,
headers: authorizationHeader
)
.validate()
.responseData { [weak self] (response) in
switch response.result {
case .success(let data):
do {
let jsonResponse = try JSON(data: data)
success(items);
self?.isLoading = false;
} catch {
self?.isLoading = false;
failed(nil)
}
break;
case .failure(let error):
print(error);
self?.isLoading = false;
failed(error)
break;
}
}
In the header here is the authorization code like this :
"Authorization": "Bearer ***********************************"
Here is the doc about the route API : https://developer.underarmour.com/docs/v71_Workout
Alamofire error:
responseValidationFailed(Alamofire.AFError.ResponseValidationFailureReason.unacceptableStatusCode(403))
Am i missing something ? Thx
Problem founded !
If you are using MapMyFitness API you have to use https://www.mapmyfitness.com/v7.1/ url for the authentification but when you need to request route it's https://api.ua.com/v7.1/.
Moreover, you need to add in your header the "api-key".
["Authorization": "Bearer ***********************************", "api-key": client_id]
and you need to set an user_id in params.
var params = ["user" : self.userID, field_set: "time_series"] as [String : Any]
These informations are not in the documentation.
Here is my final request :
self.authorizationHeader.updateValue(self.clientID, forKey: "api-key")
var params = ["field_set" : "time_series",
"user" : self.userID] as [String : Any]
Alamofire.request(self.url + "/workout/",
method: .get,
parameters: params,
headers: self.authorizationHeader
)
.validate()
.responseData { [weak self] (response) in
switch response.result {
case .success(let data):
do {
let jsonResponse = try JSON(data: data)
success(items);
} catch {
failed(nil)
}
break;
case .failure(let error):
print(error);
failed(error)
break;
}
}
}
How can I get status code from the Alamofire response?
In the latest version I can use validate but I need to check what the status code is.
Code:
Alamofire.request(.GET, "http://example.com/url")
.responseJSON { response in
}
This works (after #MirzaDelic pointed out my mistake):
Alamofire.request(.get, "http://www.google.com")
.responseJSON { response in
if response.response.statusCode == 404 {
// do something
} else {
// do something else
}
}
In Alamofire 4.0 swift3 branch, I needed exactly:
Alamofire.request(request, withMethod: .get, parameters: parameters, encoding: .url, headers: nil)
.validate()
.responseJSON { response in
switch response.result {
case .success:
let statusCode = (response.response?.statusCode)!
print("...HTTP code: \(statusCode)")
}
}
While the above methods will work, there is a more efficient way to do this. response.response.statusCode returns a status code that could very in large amounts. Alamofire includes two functions that are useful for this case, isSuccess and isFailure.
Alamofire.request(.get, "http://example.com/url").responseJSON { response in
let responseErrorCode = response.response!.statusCode
if response.result.isSuccess {
print("Successful HTTP code: \(responseErrorCode)")
// Run code if request is successful
} else if response.result.isFailure {
print("Failure HTTP code: \(responseErrorCode)")
// Run code if request isn't successful
}
}
By using the code above you can easily know whether the HTTP code is good or bad.
With Alamofire 5.6, if you add .validate(statusCode: [200]) to your AF request you can then inspect the AFError of the result.
func request(_ requestConvertible: any URLRequestConvertible) async throws {
switch await AF
.request(requestConvertible, interceptor: interceptor)
.validate(statusCode: [200])
.serializingDecodable(Empty.self, emptyResponseCodes: [200])
.result {
case .failure(let error):
if error.responseCode == 401 {
// Handle 401 statusCode
}
throw error
case .success:
break
}
}
Or for a Decodable type (from a JSON response):
func requestDecodable<Value: Decodable>(_ requestConvertible: any URLRequestConvertible, to type: Value.Type) async throws -> Value {
let request = AF.request(requestConvertible, interceptor: interceptor)
.validate(statusCode: [200])
let response = request.serializingData(emptyResponseCodes: [200])
let result = await response.result
switch result {
case .failure(let error):
if request.response?.statusCode == 401 {
// Handle 401 statusCode
}
throw error
case .success(let data):
return try JSONDecoder().decode(type.self, from: data)
}
}