Alamofire + bonjour , no network connection - swift

I'm developing a service browser for iOS device and i'm facing some problems.
I've correctly discovered services by using NSNetServiceBrowser and resolved it but if i try to do a .GET request using Alamofire to the hostname of the NSNetService returned by discovery i get a cannot resolve name
i've used this code to do the request
var url : String = "http://\(self.servers[0].hostName):32400/library/sections"
Alamofire.request(.GET, url.lowercaseString,encoding: ParameterEncoding.URL).responsePropertyList { request, response, result in
if let array = response.result.value as? [[String: String]] {
print("bau")
}
}
self.servers[0].hostName returns a string like iMac-di-Tiz.local.
and opening the url in Chrome i get the page correctly.
Does anyone have tried it and made it work?

Related

Is there a way to differentiate between success and error API answers in Swift when there is no request status in response?

I'm creating a login page, and I used to handle API error such as:
{"status":"error","answer":"Password is wrong"}
this way:
if error?["status"] as? String == "error" {
Alert.showBasic(title: error!["status"] as! String, message: error!["answer"] as! String, vc: self)
This worked perfectly. But now I'm working with another API, that responds to my request this way:
{"password":["password is wrong"]}
The confusion what I have, is that I don't get from API answer, a status for my request, like success or error.
Is there a way to handle it?
The error != nil depends and what you feed to your model and how you feed depends on status code
if let httpResponse = response as? HTTPURLResponse{
switch httpResponse.statusCode {
case 200 : //handle Root data model
case 401 : //handle wrong password model
}
}
URLSession error is different . Its when the request is failed and no response . But you got the response but its up to you differentiate whether its good or bad.
Server response should be static if there is a change not noticed to you means something wrong in the backend.

Error 401: Alamofire/Swift 3

This code previously works, and suddenly after several works around it stopped and return an Error 401.
Alamofire.request(WebServices.URLS().TabDataURL, method: .post, parameters: reqParams).validate().responseJSON { response in
let statusCode = (response.response?.statusCode) //Get HTTP status code
guard response.result.isSuccess, let value = response.result.value else {
// FIXME:you need to handle errors.
print("Status, Fetching News List:", statusCode)
return
}
I have check via Postman, the parameters are correct. Infact, I can also login (by passing 2 parameters). But when I want to pull in a JSON data from server, I am getting 401.
my main project doesn't have an error. but instead of returning the JSON data, it gave me an Error 401. my other projects (same code format, same server & parameters) is giving me this error.
Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.} it worked!
Also, I have check with my other projects -- it seemed I cannot connect aswell. So I suspect it could be because of Alamofire, or my Xcode?
Anyone can help me?
Hi i think your server Response is not correct because, as error indicate object should not start with array same issue i come across tell backend developer to send response in dictionary,
{NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}
let headers = [String: String]()// To add header if any
Alamofire.request(path,method: mType, parameters: parameters, encoding: JSONEncoding.default, headers : headers) .responseJSON
{ response in
//----- this code always works for me. & You don't need add header if not required.
if let JSON = response.result.value {
print("JSON: \(JSON)")
if response.response?.statusCode == 200
{
successCompletionHandler(JSON as! NSDictionary)
}
else if response.response?.statusCode == 401
{
failureCompletionHandler(JSON as! NSDictionary)
}
else
{
failureCompletionHandler(JSON as! NSDictionary)
}
}
else
{
print("error message")
failureCompletionHandler([WSAPIConst.ERROR:WSAPIConst.ERROR_MESSAGE])
}
}

How to set post parameters on using Alamofire in swift

I am using Alamofire in swift to send http request/post to server. Below is the code I used in swift.
Alamofire.request(.POST, "http://localhost:8080/hello", headers: [ACCESS_TOKEN:token, "Content-Type":"application/x-www-form-urlencoded" ],
parameters:["friend_id" : friendId, "skill_id" : skillId]).response(completionHandler: {
(request, response, data, error) in
print(request)
print(response)
print(data)
print(error)
})
Below is the code defined in server side:
#POST
#Path("/hello")
#Produces(MediaType.APPLICATION_JSON)
public Response nominateSkill(#Context HttpServletRequest request, #FormParam("friend_id") long friendId, #FormParam("skill_id") int skillId) {
// ...
}
When I run the swift code, I always got below error message in server side:
A servlet request to the URI http://localhost:8080/hello contains form parameters in the request body but the request body has been consumed by the servlet or a servlet filter accessing the request parameters. Only resource methods using #FormParam will work as expected. Resource methods consuming the request body by other means will not work as expected.
I think the problem would be coursed by the swift code which didn't set the parameter correctly. But I don't know how to set them correctly?
I found the solution after some search. I need to add "encoding: .URL" on the request method like below:
Alamofire.request(.POST, "http://localhost:8080/hello", headers: [ACCESS_TOKEN:token, "Content-Type":"application/x-www-form-urlencoded" ],
parameters:["friend_id" : friendId, "skill_id" : skillId],
encoding: .URL).response(completionHandler: {
(request, response, data, error) in
print(request)
print(response)
print(data)
print(error)
})
Your swift code seems fine. Make sure on which side problem is occur. You can try https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop?hl=en to test the api and make sure api doen't have any issues.
You may also try to change data type of friend_id and skill_id to string in server side and run again.

About Alamofire version for use manager

I use this code.
var apiPath : String = "/api/list/"
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
configuration.timeoutIntervalForRequest = 60
let manager = Alamofire.Manager(configuration: configuration)
manager.session.configuration.HTTPAdditionalHeaders = ["_token" : self._token]
manager.request(.GET, self._host + self._url + apiPath, parameters: nil)
.responseSwiftyJSON ({ (request, response, resultJson, error) in
if (resultJson["Success"]) {
//get list success
} else {
println("request : \(request)")
println("response : \(response)")
println("resultJson : \(resultJson)")
println("error : \(error)")
}
})
And I got some problem
Alamofire version 1.2.1 : No Problem
Alamofire version 1.2.2 & 1.2.3 :
request : { URL: https://test.com/api/list/ }
response : nil
resultJson : null
error : Optional(Error Domain=NSURLErrorDomain Code=-999 "cancelled"
UserInfo=0x7feb92c434f0 {NSErrorFailingURLKey=https
://test.com/api/list/, NSLocalizedDescription=cancelled,
NSErrorFailingURLStringKey=http s://test.com/api/list/})
why response was nil and resultJson was null on version 1.2.2 and 1.2.3
Please help me what problem in this code..
I just encountered the same problem as you today after updating Alamofire from 1.2.1 to 1.2.3.
I discovered by adding "manager.session.invalidateAndCancel()" at the end and inside the responseJSON block fixed this issue. But what I cannot get my head around is that how can this line of code INSIDE the responseJSON block affects the responseJSON results.
Anyway I will just run with this fix until the Alamofire team fixes it or someone explains to me why this is happening.
I noticed that your API endpoint indicates to a secure connection:
httpS://test.com/api/list/
Just try it just in case, maybe it repeats your situation.
In my case, this was a typo in the API manager code. Which from the part can be said is connected with App Transport Security Settings.
Just changed the protected protocol from httpS:// to http:// and the error:
NSURLErrorDomain Code = -999 "cancelled"
was gone and it all worked!
+And also if you had a similar problem. Be sure to discuss this with a backend specialist who deals with the server or API configuration for your application. This means that the server does not have valid security certificates. Perhaps you still need a secure connection. Or this specialist can again configure everything back from http:// to httpS://, and I'm not sure (did not check) whether this will work again when in the code you are already using a non-secure http:// connection.

How can I retrieve the status message of a request made with Alamofire?

The server that I am using returns error messages in the HTTP status message. For example, it will return "400 User already exists" rather than "400 Bad Request".
I would like to access the string "User already exists" in the response method called by Alamofire. However, I cannot find any way to access this string.
I found this question on StackOverflow already: Swift Alamofire: How to get the HTTP response status code
Unfortunately, no one gives an answer to the question. :(
Here is where Chrome shows where the error is:
I would suggest trying to print out all the possible data fields that you are given and see what you can find. Please try the following example and see if that sheds any light.
let URL = NSURL(string: "your/url/to/somewhere")!
let parameters = ["foo": "bar"]
Alamofire.request(.POST, URL, parameters: parameters)
.response { request, response, data, error in
println("Request: \(request)")
println("Response: \(response)")
println("Error: \(error)")
if let data = data as? NSData {
println("Data: \(NSString(data: data, encoding: NSUTF8StringEncoding)!)")
}
}
Return response in json format from the server and then i think you'll be able to get the appropriate status.
I've implemented that thing using php codeigniter..from where my response is like
$response['status'] = 'user_already_exists';
$this->response($response, 400);
Now in swift you can go with this
Alamofire.request(.POST,URL, parameters:parameters) .responseJSON
{
(request, response, data, error) in
var json = JSON(data!) //I've used swiftyJSON for reading json response
let status = json["status"].stringValue
println("Status : \(status)")
}
Hope this may help you.