Alamofire returning status Failure Always - api

I am using Alamofire in my App. This is my Alamofire request code
let params: [String:AnyObject] = ["email": self.signin_Email.text!, "password": self.signin_Password.text!]
Alamofire.request(.GET, "http://DomainName/api/App/Sign_Up", parameters: params, encoding:.JSON)
.responseJSON { response in
debugPrint(response)
}
when i put debugPrint(reponse)
what i got is this
[Request]: { URL:
http://Domain/api/App/Sign_Up } [Response]: nil [Data]:
0 bytes [Result]: FAILURE: Error Domain=NSURLErrorDomain Code=-1017
"cannot parse response" UserInfo={NSUnderlyingError=0x7ffe0840e700
{Error Domain=kCFErrorDomainCFNetwork Code=-1017 "(null)"
UserInfo={_kCFStreamErrorCodeKey=-1, _kCFStreamErrorDomainKey=4}},
NSErrorFailingURLStringKey=http://Domain/api/App/Sign_Up,
NSErrorFailingURLKey=http://Domain/api/App/Sign_Up,
_kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-1, NSLocalizedDescription=cannot parse response}
Here i am always getting the response status as Failure. I am not able to figure out what's going on. (using mvc4 as backend).
This is the Api method that accepts the above given request and returns a JSON Data
[System.Web.Http.HttpGet]
public JsonResult Sign_Up(string email,string password)
{
email = email;
password = password;
System.Web.Mvc.JsonResult usertoreturn = new System.Web.Mvc.JsonResult();
SignUpViewModel signupviewmodel = new SignUpViewModel();
usermodeltocheck.SetPassword(password);
usermodeltocheck.MembershipDate = DateTime.Now;
usermodeltocheck.IsMember = true;
usermodeltocheck.PublicKey = Guid.NewGuid().ToString("N");
usermodeltocheck.MembershipStatus = true;
usertoreturn.Data = Helper.UpdateUser(usermodeltocheck);
}
usertoreturn.JsonRequestBehavior = System.Web.Mvc.JsonRequestBehavior.AllowGet;
return usertoreturn;
}
UPDATE #1 I have created a new method named test that accepts a parameter.The method just returns the parameter value .I tried the sample code available in Github and its working. I am able to get proper response if I am avoiding parameters argument in Alamofire request Method. like
Alamofire.request(.GET, "http://DomainName/api/App/Test", encoding: .JSON).responseJSON{
response in
debugPrint(response)
}
here I am getting a SUCCESS response. I have updated my code like this
Alamofire.request(.GET, "http://DomianName/api/App/Test?test=testing", encoding: .JSON).responseJSON{
response in
debugPrint(response)
}
here also I am getting SUCCESS response. The Error occurs when I pass parameter value to the argument parameters parameters: ["test":"testing"].
also I set my parameters like this
let params = ["test":"testing"]
Alamofire.request(.GET, "http://DomianName/api/App/Test", parameters : params ,encoding: .JSON).responseJSON{
response in
debugPrint(response)
}
in this way also i am getting my response to FAILURE

May be its not an answer you are looking for but for me removing a parameter from Alamofire request method did the trick. Here is the change:
let params : [String:AnyObject] = ["email":self.signin_Email.text!,"password":self.signin_Password.text!]
let request = Alamofire.request(.GET, "http://DomianName/api/App/Sign_Up", parameters: params).responseJSON{
response in
switch response.result{
case .Success(let data) :
let json = JSON(data)
print(json)
case .Failure(let error):
print("Error : \(error)" )
}
}
I have removed encoding:.JSON from my Alamofire request method parameter list and that's it...

Try to print out all the data in response using the following:
let URLString = "http://DomainName/api/App/Sign_Up"
Alamofire.request(.GET, URLString, parameters: params, encoding:.JSON)
.responseJSON { response in
debugPrint(response)
}
Once you print it out, if you could update your question, we could help further. I'll update my answer accordingly afterwards. 👍🏼
Update #1
Okay, so the NSURLErrorDomain Code=-1017 points out that your server is most likely misbehaving. Are you able to successfully use cURL, Postman, Paw or some other HTTP client to hit the service? Once you get one of those working, you should use debugPrint on the `request object to compare.
let URLString = "http://DomainName/api/App/Sign_Up"
let request = Alamofire.request(.GET, URLString, parameters: params, encoding:.JSON)
.responseJSON { response in
debugPrint(response)
}
debugPrint(request)
This will show you the cURL command for the request.

I know this is kind of old but I stumbled upon this looking for something else. From what I have seen, I tend to get errors in this situation any time params are passed as JSON encoded with a .GET instead of a .POST
Changing the server to take a post for the URI makes everything flow correctly, and I guess in theory that is correct behavior, since if you aren't passing the values in the URL, you are technically posting the JSON to the endpoint.

Related

WinHttpRequest: Send method

I'm trying to pass parameters in the request body, the documentation says :
The request to be sent was defined in a prior call to the Open method. The calling application can provide data to be sent to the server through the Body parameter. If the HTTP verb of the object's Open is "GET", this method sends the request without Body, even if it is provided by the calling application.
So, I need to use POST with body. But when I use use POST with body I have error "Bad Request: message text is empty" and when I use GET with body result is ok. Why?
My code:
WinHttp = NEW COMObject("WinHttp.WinHttpRequest.5.1");
WinHttp.Open("GET", "http://api.telegram.org/botbotname/sendMessage", 0);
WinHttp.setRequestHeader("Content-type", "application/json");
JSONWr = New JSONWriter();
JSONWr.ValidateStructure = False;
JSONParams = New JSONWriterSettings( , Chars.Tab);
JSONWr.SetString(JSONParams);
JSONWr.WriteStartObject();
JSONWr.WritePropertyName("chat_id");
JSONWr.WriteValue(UserId);
JSONWr.WritePropertyName("text");
JSONWr.WriteValue(Text);
JSONWr.WriteEndObject();
JSONString = JSONWr.Close();
WinHttp.Send(JSONString);
work, but how? And why the same with POST doesn`t work?

How to get status code of HttpCall with Ktor and kotlinx serialization

I am trying to figure out how to check the http status code of a http request with Ktor
I have a simple GET request like this with a HttpResponseObject that holds the data the server returns and any errors server side that I control
val response:HttpResponseObject<MyObject> = client.get<HttpResponseObject<MyObject>>(url)
Now what I need to also be able to check are is if there are unhandled exceptions or Authentication exceptions that get thrown by the server. In these cases nothing would be returned by the server and a status code of 500 or 401 error would be returned.
I see the documentation has you can get the full http response with something like this
val response:HttpResponse client.get(url)
but then how do lose my serialized data coming back and I couldnt find any examples on how to serialize it from the HttpResponse object.
Does anyone have any suggestions? is there a way to get the http status code from my first example?
You can try getting the status code by using the following code:
val response = client.get<HttpResponse>(url) after that, to get the bytes from the response and serialize it you can try using val bytes: ByteArray = response.readBytes()
You can find full documentation here :
https://ktor.io/clients/http-client/quick-start/responses.html
What I ended up doing was using the HttpResponseValidator in the HttpClientConfig to catch the status codes then throw exceptions
HttpResponseValidator{
validateResponse { response: HttpResponse ->
val statusCode = response.status.value
when (statusCode) {
in 300..399 -> throw RedirectResponseException(response)
in 400..499 -> throw ClientRequestException(response)
in 500..599 -> throw ServerResponseException(response)
}
if (statusCode >= 600) {
throw ResponseException(response)
}
}
}
By doing so I was then able to pass the error through my custom object back up to the UI
private suspend fun getCurrentWeatherForUrl(url:String, callback: (HttpResponseObject<MyObject>?) -> Unit){
var response:HttpResponseObject<MyObject>? = null
response = try{
client.get<HttpResponseObject<MyObject>>(url){
header("Authorization", "Bearer $authKey")
}
}catch (e:Exception){
HttpResponseObject(null, e.toString())
}
callback(response)
}
Also you can use HttpResponse.receive() to get a serialized object AND the response data
val response:HttpResponse = client.get(url)
val myObject:MyObject = response.receive<MyObject>()
HttpResponse is deprecated, you need to use HttpStatement and then get the status after calling execute() on it.

How to set body of HttpServletResponse using ktor client

I have spring boot controller
#PostMapping(path = ["/download"])
fun getFile(#RequestBody myObjectRq: myObjectRq, httpServletResponse: HttpServletResponse): CompletableFuture<HttpServletResponse> {
return GlobalScope.async {
val response = webService.getFile(myObjectRq)
response?.let {
httpServletResponse.setHeader("Content-Type", response.headers.get("Content-Type"))
httpServletResponse.setHeader("Content-Disposition", response.headers.get("Content-Disposition"))
httpServletResponse.writer.write(String(response.content.toByteArray()))
httpServletResponse.writer.flush()
httpServletResponse.status = response.status.value
}
httpServletResponse
}.asCompletableFuture()
}
in which I use service which in turn uses ktor client to send post request to external server which should respond sending csv file. csv file content depends on values I send in myObjectRq.
Service:
suspend fun getFile(myObjectRq: myObjectRq): HttpResponse {
val response = ktorClient.post<HttpResponse> {
accept(ContentType.Application.OctetStream)
url(externalWebServerUrl)
body = myObjectRq
contentType(ContentType.Application.Json)
}
log.info(String(response.content.toByteArray()))
response
}
Headers in response are properly set, also log.info(String(response.content.toByteArray())) in the method prints out the content of received file, but I can't set it as a body of HttpServletResponse. I keep getting org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation.
Also I get Inappropriate blocking method call for httpServletResponse.writer which kind of breaks async qualities of ktor client.
What do I do wrong? How should I solve it?
So, I think SpringBoot is confused with your return type. It is trying to find a way to serialize your return CompletableFuture<HttpServletResponse> into the body of the HTTP response but failing. I believe you can achieve the same result by changing your implementation as follows:
#PostMapping(path = ["/download"])
fun getFile(#RequestBody myObjectRq: myObjectRq, httpServletResponse: HttpServletResponse): CompletableFuture<Void> {
return GlobalScope.async {
val response = webService.getFile(myObjectRq)
response?.let {
httpServletResponse.setHeader("Content-Type", response.headers.get("Content-Type"))
httpServletResponse.setHeader("Content-Disposition", response.headers.get("Content-Disposition"))
httpServletResponse.writer.write(String(response.content.toByteArray()))
httpServletResponse.writer.flush()
httpServletResponse.status = response.status.value
}
null
}.asCompletableFuture()
}
I actually managed to solve this using CompletableFuture<ResponseEntity<ByteArray>> as return type and setting body of the response this way:
ResponseEntity.ok().body(response.content.toByteArray())
This also removed Inappropriate blocking method call warnings.

Alamofire Swift 2.0 <unknown>:0: error: tuple pattern cannot match values of the non-tuple type 'Response<String, NSError>'

I am using Manger class for request. When I compile it shows
<unknown>:0: error: tuple pattern cannot match values of the non-tuple type 'Response<String, NSError>' Error`.
Its working fine in old Swift Xcode 6.*. But in Xcode 7.* its not working.
let aManager = Manager.sharedInstance
aManager.request(.GET, URLStrings.BASE_URL + URLStrings.CATEGORIES)
.responseString { _, _, result in
print("Response String: \(result.value)")
}
.responseJSON { _, _, result in
print("Response JSON: \(result.value)")
}
On clicking responseString it shows ?
Kindly Help me.
I supposed that you are using the 3.0+ Alamofire.
I encounter this problem recently, here is my solution:
for you code replace _, _, result to response and query the response data by response.data or response.result.value
For more information about the new response structure, you can check the official document here: enter link description here
Hope these helps.
You're on the Alamofire 3.0.0-beta.1 pre-release. You should switch back to Alamofire 2.0.2 (the latest release) until we have all the documentation and migration guides up-to-date.
I change my code in to this form. Now What I have to do is Convert data to JSon Object my self. But its working now for me.
let aManager = Manager.sharedInstance
aManager.request(.GET, URLStrings.BASE_URL + URLStrings.CATEGORIES )
.response {
(request, response, data, error) in
if let response = response {
print("GET REQUEST: \(request?.description)")
print("GET REQUEST: \(response.statusCode)")
if response.statusCode == 200 || response.statusCode == 201 {
}
}
else {
}
}
I check the official document here: Response Serializers
In the document, find Response Serializers, read the example code, I post it in here:
Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])
.responseJSON { response in
debugPrint(response) // prints detailed description of all response properties
print(response.request) // original URL request
print(response.response) // URL response
print(response.data) // server data
print(response.result) // result of response serialization
if let JSON = response.result.value {
print("JSON: \(JSON)")
}
}
Hope it can helps you~

Multiple encoding types for Alamofire Request

I need to make a POST request with an HTTP Body with a JSON object, but I also need to use url query parameters in the same request.
POST: http://www.example.com/api/create?param1=value&param2=value
HTTP Body: { foo : [ bar, foo], bar: foo}
Is this supported by Alamofire? How would I go about doing this?
This is definitely a valid use case. I've ran into similar issues with trying to append access tokens as query parameters to a POST request. Here's a function that should make things a bit easier for the time being that is similar to your approach.
func multiEncodedURLRequest(
method: Alamofire.Method,
URLString: URLStringConvertible,
URLParameters: [String: AnyObject],
bodyParameters: [String: AnyObject]) -> NSURLRequest
{
let tempURLRequest = NSURLRequest(URL: NSURL(string: URLString.URLString)!)
let URLRequest = ParameterEncoding.URL.encode(tempURLRequest, parameters: URLParameters)
let bodyRequest = ParameterEncoding.JSON.encode(tempURLRequest, parameters: bodyParameters)
let compositeRequest = URLRequest.0.mutableCopy() as NSMutableURLRequest
compositeRequest.HTTPMethod = method.rawValue
compositeRequest.HTTPBody = bodyRequest.0.HTTPBody
return compositeRequest
}
With that said, could you make sure to put in a feature request issue on the Github? This is certainly something we need to figure out how to make easier in Alamofire since it's such a common use case. If you could put in a really good description of your use case, then I'm sure it will get attention. I will certainly help press to get support added.
At this point, I've decided to solve this by manually encoding an NSURLRequest with the URL parameters, retrieving the URL from that request, and using that to create the final request. I've created a function to return the query parameter encoded request:
private func queryParameterEncodedRequestURL(urlString: String,
values: [String]) -> NSURL {
let URL = NSURL(string: urlString)
var request = NSURLRequest(URL: URL)
let parameters = [
"param1": values[0]!,
"param2": values[1]!
]
let encoding = Alamofire.ParameterEncoding.URL
(request, _) = encoding.encode(request, parameters: parameters)
return (request.URL, nil)
}
This works fine, but I would definitely like to see Alamofire support multiple encoding types more easily. This feels like a workaround to me.