Alamofire - Add a timeout if there is no response - swift

I have a JSON call using Alamofire, it works well except if the query on the server is not responding. If the endpoint times out then Alamofire does give a timeout error but recently the endpoint was working but MSSQL on the server was not responding. In that case, the SVProgress would just spin and wait for the server to return the response and would not timeout.
How can I add a timeout to the below code so that if the server is not responding after x seconds I get an error?
I'm using Swift 5.
SVProgressHUD.show()
let apiEndpoint: String = "https://intelipos.dynalias.net/iocserver/MobileApp.aspx?action=MobileApp"
let headers = HTTPHeaders(["Content-Type" : "application/json","WebSiteAppID":self.webSiteAppID])
var param = [String: Any?]()
param["Command"] = "GetSales"
let keychain = KeychainSwift()
let sessionID = keychain.get("adminSessionID")!.base64Decoded()!
let strParam = jsonToString(json: ["SessionID":sessionID])
param["Data"] = strParam?.base64Encoded()
param["Signature"] = strParam?.base64Encoded()?.sha256Signature()
let request = AF.request(URL(string: apiEndpoint)!, method: .post, parameters: param as Parameters, encoding: JSONEncoding.default, headers: headers)

You just need to set the timeout interval of your url request to your desired value.
request.timeoutInterval = 30

Related

Alamofire session configurations are not reflected in the request

Alamofire Version: 5.1
We are modifying our alamofire session configuration as following:
let apiManager: Session = {
let configuration = URLSessionConfiguration.af.default
configuration.timeoutIntervalForRequest = 20
configuration.requestCachePolicy = .reloadIgnoringCacheData
configuration.urlCache = nil
let manager = Alamofire.Session(
configuration: configuration,
cachedResponseHandler: ResponseCacher(behavior: .doNotCache)
)
return manager
}()
And we are making the request as following
apiManager.request(
url,
method: .post,
parameters: requestBodyParameters,
encoding: JSONEncoding.default,
headers: generateHeaders(enableAuth: authorisation) // to generate headers
)
.validate(statusCode: 200..<300)
.responseJSON { response in
print(response)
}
}
}
But the request configurations is not updated, they remain at default values
[Timeout]
60
[Cache policy]
UseProtocolCachePolicy
You're looking at the URLRequest generated by Alamofire which doesn't include the URLSession-level configuration, and which will never reflect the cache customization. If you want to see the actual URLRequest being performed after it passes through both Alamofire and URLSession, you can access the latest URLSessionTask that the Alamofire Request (in this case a DataRequest) performed by using request.task. However, like I said, this will never reflect the other behaviors you've attached, like a ResponseCacher, since those exist outside of the request pipeline.

Post Method Error : "The request timed out." - Swift

I am sending data to api using the post method. But while working in advance, I have now moved my server to the windows sdd server and started to get the problem I wrote below all the time. While working on Similator, it doesn't work when I try it on my physical phone, I get this problem. What is the problem? A situation related to the firewall? Because I started to get this problem after moving the server. Or another problem?
NSErrorFailingURLStringKey=....php, NSErrorFailingURLKey=....php,
_kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-2102, NSLocalizedDescription=The request timed out.}
#objc func veriGonder() {
let url = NSURL(string: "...php")
var request = URLRequest(url: url! as URL)
request.httpMethod = "POST"
...
dataString = dataString + "&formCLASSNAMESTARIH\(verıTURUSTarih)"
dataString = dataString + "&formCLASSNAMESZAMAN\(verıTURUsZaman)"
...
let dataD = dataString.data(using: .utf8)
do {
let uploadJob = URLSession.shared.uploadTask(with: request, from: dataD)
{
data, response, error in
...
}
Here as the error specifies your request timed out. So to fix this either you need to increase the timeout interval or increase the server response interval from server-side. So, if it's the first option here's the code you need:
request.timeoutInterval = 100 // increase this to your desired value.

Alamofire 4 sends method as POST but server reads it GET

I have a very weird problem here, using Alamofire 4 Swift 4 Xcode 9.1
let manager = Alamofire.SessionManager.default
manager.session.configuration.timeoutIntervalForRequest = 30
manager.session.configuration.requestCachePolicy = .reloadIgnoringLocalAndRemoteCacheData
let request = manager.request(
url,
method: HTTPMethod.post,
parameters: [:])
But server replies with method not allowed because it reads it as GET, however, if I change HTTPMethod.put or .delete or any other method, the server reads it correctly, the problem is with post specifically!
By debugging Alamofire's class 'SessionManager', specially the following method:
open func request(
_ url: URLConvertible,
method: HTTPMethod = .get,
parameters: Parameters? = nil,
encoding: ParameterEncoding = URLEncoding.default,
headers: HTTPHeaders? = nil)
-> DataRequest
The method here is correct, POST, so it's just fine before it goes out the application, what's wrong?
It was adding '/' at the end of the URL that was causing this.

Alamofire timeout url

I am using the Alamofire Swift library
Alamofire.request
(RestApiManager.sharedInstance.baseURL+"login?language="+lang,
method: .post,
parameters: requestDictionary,
encoding: URLEncoding.httpBody,
headers: headers
).responseObject(keyPath: "") { (response: DataResponse<User>) in
let user = response.result.value
print(user?.status)
print(user?.message)
}
So simply, I want to put a timeout of 60 seconds on every call I make.And i like to give a message connection timeout after 60 seconds. I also want to know, if there exists an internet connection or not. If it doesnt exist, I like to avoid calling alamofire.
Here's the Swift 3.0 / Alamofire 4.0 code to get an alamofireManager that has a 60 second timeout.
You need create a global variable for the request manager:
var alamoFireManager = Alamofire.Manager.sharedInstance
And after configure the custom parameters:
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
configuration.timeoutIntervalForRequest = 60 // seconds
configuration.timeoutIntervalForResource = 60
self.alamoFireManager = Alamofire.Manager(configuration: configuration)

NSURLConnection response returns 500 Status Code

I am trying to connect to a local node.js server setup and authenticate the user. I keep getting the 500 status code and can't figure out what I am missing.
I have tried hitting the server with these credentials from a web browser, and it works as expected.
Note: I do understand I have to use the NSURLSession instead of NSURLConnection, but for now, I need to get this to work.
Here is my code,
func signInUserWithDetails(userName:String,userPassword:String,serverURL:NSURL) {
let credDic :[String:String]=["user[name]":userName,
"user[password]":userPassword ]
self.httpMethod="PUT"
self.httpPath="/account"
self.expectedStatusCode=201
self.actualStatusCode=NSNotFound
self.requestUniqueIdentifier = NSUUID().UUIDString
let urlComponents = NSURLComponents(URL: serverURL, resolvingAgainstBaseURL: false)!
urlComponents.path = httpPath
let formedURL = urlComponents.URL!
var requestOrg = NSMutableURLRequest(URL: formedURL)
requestOrg.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
requestOrg.addValue("application/json", forHTTPHeaderField: "Accept")
requestOrg.HTTPMethod=self.httpMethod!
print(requestOrg.allHTTPHeaderFields) // Output 1
do{
let theJSONData = try NSJSONSerialization.dataWithJSONObject(credDic,options: NSJSONWritingOptions.PrettyPrinted)
let theJSONText = NSString(data: theJSONData,encoding: NSASCIIStringEncoding)
requestOrg.HTTPBody = theJSONData;
let tempD=try NSJSONSerialization.JSONObjectWithData(requestOrg.HTTPBody!, options: []) as? [String:String]
print("\(tempD)") //Output 2
}catch let error as NSError {
print(error)
}
connection = NSURLConnection(request: requestOrg, delegate: self, startImmediately: true)!
}
And I am just printing out the response with this,
func connection(didReceiveResponse: NSURLConnection, didReceiveResponse response: NSURLResponse) {
print("----------------------didReceiveResponse")
self.response=response
print("Response Received:"+"\(self.response)")
let urlResponse:NSHTTPURLResponse = response as! NSHTTPURLResponse
let responseCode=urlResponse.statusCode
self.actualStatusCode=responseCode
}
And the result I get is
Optional(["Accept": "application/json", "Content-Type": "application/x-www-form-urlencoded"])
Optional(["user[password]": "R", "user[name]": "R"])
----------------------didReceiveResponse
Response Received:Optional(<NSHTTPURLResponse: 0x7faba269d440> { URL: http://localhost:3000/account } { status code: 500, headers {
Connection = "keep-alive";
"Content-Length" = 1464;
"Content-Type" = "application/json";
Date = "Sat, 26 Dec 2015 08:34:45 GMT";
"X-Powered-By" = Express;
} })
And the didReceiveData throws this error
{"error":{"message":"Cannot read property 'name' of undefined","stack":"TypeError: Cannot read property 'name' of undefined\n at Object.exports.signIn [as handle] ( .......
Status code 500 means, that the server could not process your data and ran into an internal error. This oftentimes is caused by improperly encoded HTTP messages, where the server was unable to catch all possible errors.
When looking at your code, it becomes immediately apparent:
You are not sending a properly application/x-www-form-urlencoded encoded data to the server. This is likely the main cause of your problem. The other cause might be, that it's likely not a PUT but a POST method which is required to sign-in.
But before explaining how you encode your data properly, I would suggest to find out whether your server accepts JSON as content data (application/json). If so, properly encoding the data is much easier: having a JSON object (your variable credDic), simply convert it to JSON as UTF-8 in a NSData container. Then, get the length in bytes, set headers Content-Type and Content-Length accordingly.
I had a similar issue but after tried to include Content-Type using application/json, it was solved.
Example: request.addValue("application/json", forHTTPHeaderField: "Content-Type")
The client application gets an HTTP status code of 500 with the message "Internal Server Error" as a response for API calls. The 500 Internal Server error could be caused by an error during the execution of any policy within Edge or by an error on the target/backend server.
The HTTP status code 500 is a generic error response. It means that the server encountered an unexpected condition that prevented it from fulfilling the request. This error is usually returned by the server when no other error code is suitable