Swift Alamofire "The request timed out" in one of every two requests - swift

In every one of my two calls to loadHeader with the same URL, I get "The request timed out" error. In first try, the function works and I manage to get and parse the response. In second, I get time out. In third it works and in forth time out again. Is it about my code or about server? I tried waiting before trying again as it might be some security protocol of server but it didn't change anything.
Here is error code:
FAILURE: Error Domain=NSURLErrorDomain Code=-1001 "The request timed out."
And here is my code:
func loadHeader(url: String){
let parameters = ["foo": "bar"]
Alamofire.request(url, method: .get, parameters: parameters, encoding: JSONEncoding.default)
.validate { request, response, data in
// Custom evaluation closure now includes data (allows you to parse data to dig out error messages if necessary)
return .success
}
.responseJSON {
response in
let json=response.data
self.jsonToObjectHeader(json: json!)
}
}
func jsonToObjectHeader(json:Data){
do{
databases = try JSONDecoder().decode(responseHeader.self,from: json)
if databases.ordersHeader.count == 0 {
let alert = UIAlertView(title: "empty",message: "empty",delegate: nil,cancelButtonTitle: "OK")
alert.show()
}
else {
for i in 0...databases.ordersHeader.count-1 {
myArray2.append(databases.ordersHeader[i].productName!)
}
}
DispatchQueue.main.async {
self.myTableView.reloadData()
self.myTableView.tableFooterView = UIView()
}
//print(databases.ordersHeader[0].companyAddress)
}catch let jsonErr {
print(jsonErr)
}
}

I've added
let parameters = ["foo": "bar"]
thinking I've to give parameters as it is in the function. Just updated
Alamofire.request(url, method: .get, parameters: parameters, encoding: JSONEncoding.default)
to
Alamofire.request(url, method: .get, parameters: nil, encoding: JSONEncoding.default)
and it solved the issue. Posting this in case of someone experiences something similar.

Related

How to Access Magento Rest API in iOS swift 4

I am write code to post data from Magento REST API for IOS Application put get me error. I try from login and register view controller in the same code get me the same error
The api Magento REST API . I success to get data from api but error to post data in api
self.internetConnectionChecker { (status) in
if status{
KVNProgress.show();
let userLoginApi = "http://3.85.198.62/4apps/rest/V1/integration/customer/token"
let parameters: Parameters = ["username": username, "password": password]
let header : HTTPHeaders = ["Content-Type": "application/json"]
Alamofire.request(userLoginApi, method: .post, parameters: parameters, headers: header).responseObject { (response: DataResponse<User>) in
KVNProgress.dismiss()
print(response.request?.url)
print(response.request?.allHTTPHeaderFields)
let json = try! JSONSerialization.jsonObject(with: response.data!, options: JSONSerialization.ReadingOptions.mutableContainers)
print(json)
DispatchQueue.main.async {
loginCallback(response.result.value!)}
self.maincontroller.SuccessMessage(title: "تسجيل الدخول", successbody: "")
The Output
{
message = "Decoding error: \nUnable to unserialize value. Error: Syntax error\n#0 /opt/bitnami/apache2/htdocs/4apps/lib/internal/Magento/Framework/Webapi/Rest/Request/Deserializer/Json.php(64): Magento\\Framework\\Serialize\\Serializer\\Json->unserialize('password=Abc%40...')\n#1 /opt/bitnami/apache2/htdocs/4apps/lib/internal/Magento/Framework/Webapi/Rest/Request.php(141): Magento\\Framework\\Webapi\\Rest\\Request\\Deserializer\\Json->deserialize('password=Abc%40...')\n#2 /opt/bitnami/apache2/htdocs/4apps/lib/internal/Magento/Framework/Webapi/Rest/Request.php(199): Magento\\Framework\\Webapi\\Rest\\Request->getBodyParams()\n#3 /opt/bitnami/apache2/htdocs/4apps/app/code/Magento/Webapi/Controller/Rest/InputParamsResolver.php(97): Magento\\Framework\\Webapi\\Rest\\Request->getRequestData()\n#4 /opt/bitnami/apache2/htdocs/4apps/lib/internal/Magento/Framework/Interception/Interceptor.php(58): Magento\\Webapi\\Controller\\Rest\\InputParamsResolver->resolve()\n#5 /opt/bitnami/apache2/htdocs/4apps/lib/internal/Magento/Framework/Interception/Interceptor.php(138): Magento\\Webapi\\Controller\\Rest\\InputParamsResolver\\Interceptor->___callParent('resolve', Array)\n#6 /opt/bitnami/apache2/htdocs/4apps/lib/internal/Magento/Framework/Interception/Interceptor.php(153): Magento\\Webapi\\Controller\\Rest\\InputParamsResolver\\Interceptor->Magento\\Framework\\Interception\\{closure}()\n#7 /opt/bitnami/apache2/htdocs/4apps/generated/code/Magento/Webapi/Controller/Rest/InputParamsResolver/Interceptor.php(26): Magento\\Webapi\\Controller\\Rest\\InputParamsResolver\\Interceptor->___callPlugins('resolve', Array, Array)\n#8 /opt/bitnami/apache2/htdocs/4apps/app/code/Magento/Webapi/Controller/Rest/SynchronousRequestProcessor.php(85): Magento\\Webapi\\Controller\\Rest\\InputParamsResolver\\Interceptor->resolve()\n#9 /opt/bitnami/apache2/htdocs/4apps/app/code/Magento/Webapi/Controller/Rest.php(188): Magento\\Webapi\\Controller\\Rest\\SynchronousRequestProcessor->process(Object(Magento\\Framework\\Webapi\\Rest\\Request\\Proxy))\n#10 /opt/bitnami/apache2/htdocs/4apps/lib/internal/Magento/Framework/Interception/Interceptor.php(58): Magento\\Webapi\\Controller\\Rest->dispatch(Object(Magento\\Framework\\App\\Request\\Http))\n#11 /opt/bitnami/apache2/htdocs/4apps/lib/internal/Magento/Framework/Interception/Interceptor.php(138): Magento\\Webapi\\Controller\\Rest\\Interceptor->___callParent('dispatch', Array)\n#12 /opt/bitnami/apache2/htdocs/4apps/lib/internal/Magento/Framework/Interception/Interceptor.php(153): Magento\\Webapi\\Controller\\Rest\\Interceptor->Magento\\Framework\\Interception\\{closure}(Object(Magento\\Framework\\App\\Request\\Http))\n#13 /opt/bitnami/apache2/htdocs/4apps/generated/code/Magento/Webapi/Controller/Rest/Interceptor.php(26): Magento\\Webapi\\Controller\\Rest\\Interceptor->___callPlugins('dispatch', Array, Array)\n#14 /opt/bitnami/apache2/htdocs/4apps/lib/internal/Magento/Framework/App/Http.php(137): Magento\\Webapi\\Controller\\Rest\\Interceptor->dispatch(Object(Magento\\Framework\\App\\Request\\Http))\n#15 /opt/bitnami/apache2/htdocs/4apps/generated/code/Magento/Framework/App/Http/Interceptor.php(24): Magento\\Framework\\App\\Http->launch()\n#16 /opt/bitnami/apache2/htdocs/4apps/lib/internal/Magento/Framework/App/Bootstrap.php(261): Magento\\Framework\\App\\Http\\Interceptor->launch()\n#17 /opt/bitnami/apache2/htdocs/4apps/index.php(39): Magento\\Framework\\App\\Bootstrap->run(Object(Magento\\Framework\\App\\Http\\Interceptor))\n#18 {main}";
trace = "<null>";
}
The error you see has happened on the Magento side Decoding error: \nUnable to unserialize value... It points to the problem unserializing JSON params. So I've tried to play with encoding on the Alamofire request and URLEncoding.queryString works for me. Here is my code
Alamofire.request(userLoginApi, method: .post, parameters: parameters, encoding: URLEncoding.queryString, headers: header).responseData { (response: DataResponse<Data>) in
let json = try! JSONSerialization.jsonObject(with: response.data!, options: JSONSerialization.ReadingOptions.mutableContainers)
print("json", json)
}

Can't make post request using params as dictionary with Swift 4 & Alamofire

I'm trying to learn to call API with/without library. But the problem here confuses me.
I have params like this:
let parameters: [String:String] =
["key":"MY_KEY" ,
"q":sourceText,
"source": sourceLanguage),
"target": target)]
let headers: HTTPHeaders = [ "Content-type": "application/json"]
I make a post call like this:
Alamofire.request(urlString, method: HTTPMethod.post, parameters: parameters, headers: headers)
.responseJSON{ response in
guard response.result.error == nil else {
print("error calling POST on /todos/1")
print(response.result.error!)
return
}
// make sure we got some JSON since that's what we expect
guard let json = response.result.value as? [String: Any] else {
print("didn't get todo object as JSON from API")
print("Error: \(response.result.error)")
return
}
By this I get an error 403, saying that I do not have a valid API key (I tested the key with postman, and it is okay).
After many efforts, I have to change the code like this
let stringparams = "key=MY_KEY&q=\(sourceText)&source=\(sourceLanguage)&target=\(target)"
request.httpBody = stringparams.data(using: String.Encoding.utf8)
and using this: Alamofire.request(request)
it works!
I'm using Google Cloud Translation api. And the web use a REST api as said here: https://cloud.google.com/translate/docs/reference/translate
So why can't I use params as dictionary, but using the string (like formdata) will work here?
My guess is Alamofire didn't make the right BODY for the request from the parameters because other arguments is okay. But I don't know why.
And I think Google should accept a json params as they mentioned, in stead of using form data? I did try the original method, but it didn't work with JSON.
From what actually works for you it looks like you need to encode the parameters in the same style as a query. Try this:
struct ParameterQueryEncoding: ParameterEncoding {
func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
var request = try urlRequest.asURLRequest()
request.httpBody = parameters?
.map { "\($0)=\($1)" }
.joined(separator: "&")
.data(using: .utf8)
return request
}
}
You should then be able to perform the original call that you had before:
Alamofire.request(urlString,
method: HTTPMethod.post,
parameters: parameters,
encoding: ParameterQueryEncoding(),
headers: headers)
.responseJSON { response in
...
}
Try by using JSON encoding. Make sure you have removed ) from dictionary.
Alamofire.request(URL, method: method, parameters: parameters, encoding: JSONEncoding.default, headers: headers)

JSON POST request with Alamofire 4.6 is not firing

I am trying to send a post request with Alamofire 4.6. I am having an issue where it does not seem like the body of the request is never being reached. The server Is never getting a request and the print statements are never being hit. I am led to believe that the request is never started up.
let jsonData = ["request":
["method": "phoneNumberVerificationStart","id": 1,
"params":
["number": "\(PhoneNumber)"] ]]
let urlString = "*************************************"
let requestURL = URLRequest(url: URL(string: urlString)!)
let finalRequest = Alamofire.request(urlString, method: .post, parameters: jsonData, encoding: JSONEncoding.default, headers: nil)
finalRequest.responseJSON{
request in
print(request)
print("I am IN the request")
}
print("Here after Request")
The "Here after the Request" prints out but the "I am IN the request" never is hit so I am led to believe that the async call is never called. Does anyone have an idea what the issue is?

Catch pattern changes callback signature

I am trying to use JSONDecoder to decode a json response from my server using Alamofire. When I decode the response with a guard, it works without any issues. The side-effect of this approach is that I can't tell what the issue is when the decode actually fails.
guard let result: TResponseData = try? decoder.decode(TResponseData.self, from: response.data!) else {
self.logger.error("Unable to decode the response data into a model representation.")
return
}
So instead I'm wanting to use a do { } catch { } but I can't figure out how exactly I'm supposed to use it within the Alamofire responseJSON callback.
This is what I've currently got:
Alamofire.request(completeUrl, method: .post, parameters: parameters, encoding: encoding, headers: headers)
.validate()
.responseJSON { (response) -> Void in
self.logger.info("POST Response: \(String(describing:response.response?.statusCode))")
switch response.result {
case .success(_):
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .custom(Date.toTMDBDate)
do {
let _ = try decoder.decode(TResponseData.self, from: response.data!)
} catch DecodingError.dataCorrupted(let error) {
self.logger.error(error.underlyingError)
return
}
completion(result)
return
case .failure(let error):
//....
}
What I am given with this code however is a compiler error on the .responseJSON { (response) -> Void in line.
Invalid conversion from throwing function of type '(_) -> Void' to non-throwing function type '(DataResponse) -> Void'.
The guard code works fine, and if I change the try to a try? or force an unwrap, it compiles - I just don't get to have my catch handle the actual error.
If I change the catch block so that it does not include any pattern, then the code compiles.
catch {
return
}
This doesn't give me anything over what my guard was giving me. I really want to capture the error encountered with the decode operation. Am I using the wrong pattern? Why does using the DecodingError.dataCorrupted pattern seemingly change the callback signature?
JSONDecoder can throw errors other than DecodingError.dataCorrupted; you need to be able to handle the case of an arbitrary Error being thrown. So, if you want to handle that error, you'll want an unconditional catch {} block.
You can also:
Use responseData instead of responseJSON as you're doing your own deserialisation with JSONDecoder.
Use the unwrap() method on Alamofire's Result type in order to coalesce the network error with the decoding error, if desired.
This is what that looks like:
Alamofire
.request(
completeUrl, method: .post, parameters: parameters,
encoding: encoding, headers: headers
)
.validate()
.responseData { response in
self.logger.info(
"POST Response: \(response.response?.statusCode as Any)"
)
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .custom(Date.toTMDBDate)
do {
let result = try decoder.decode(
TResponseData.self, from: response.result.unwrap()
)
completion(result)
} catch {
self.logger.error(error)
}
}
Although one thing to note here is that you're not calling completion if the request fails; I would personally change that such that you do, and propagate the error back by having the completion take a Result<TResponseData> parameter.
In that case, you can use Result's flatMap(_:) method rather than unwrap() and a catch {} block:
func doRequest(_ completion: #escaping (Result<TResponseData>) -> Void) {
let completeURL = // ...
let parameters = // ...
let encoding = // ...
let headers = // ...
Alamofire
.request(
completeURL, method: .post, parameters: parameters,
encoding: encoding, headers: headers
)
.validate()
.responseData { response in
self.logger.info(
"POST Response: \(response.response?.statusCode as Any)"
)
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .custom(Date.toTMDBDate)
// if response.result is successful data, try to decode.
// if decoding fails, result is that error.
// if response.result is failure, result is that error.
let result = response.result.flatMap {
try decoder.decode(TResponseData.self, from: $0)
}
.ifFailure {
self.logger.error($0)
}
completion(result)
}
}

Issue with Alamofire Request

I am trying to use Alamofire to make a web request. It had been working absolutely fine, but after doing a recent pod update it has stopped.
My syntax is:
var params = [String : Any]()
if (data != nil) {
params = try! JSONSerialization.jsonObject(with: data!, options: []) as! [String : Any]
}
let _ = Alamofire.request( "http://example.com" , method: Method, parameters: params?, encoding: .queryString, headers: [:]).response{ (request, response, data, error) in
}
the error looks is "Extra argument 'method' in call" and I don't seem to be able to get rid of it. My parameters of the request to Alamofire.request seem ok to me, but clearly I am missing something.
You're not passing anything to the method parameter. I don't know what you're trying to provide in the encoding parameter either but that went through some changes in Alamofire 4.0. For example and for simplicity's sake, this compiles:
let _ = Alamofire.request( "http://example.com" , method: HTTPMethod.get, parameters: nil, encoding: JSONEncoding.default, headers: nil)