Using Alamofire 4.9.0.
I am trying to implement handling streaming APIs in JSON lines format. Here's how:
stream = Alamofire.request(url, method: HTTPMethod.get,
headers: TTSessionManager.headers)
.validate()
.stream(closure: { (data) in
// parsing JSON lines ...
})
.response(completionHandler: { (response) in
// error handling ...
})
Now the issue is that the first response takes some time to return. And when it does I get a couple of JSON lines in one big batch. After that stream continues to normally respond with a new JSON line per response coming through the stream.
Has anyone encountered this behaviour? I'm wondering wether there is some additional session or request setup needed in order for this to work normal (line per response) from the start. When inspecting the response.metrics after canceling the request a lot of the fields are null so I can't for sure say wether some of the initial connection steps are the issue:
(Domain Lookup Start) (null)
(Domain Lookup End) (null)
(Connect Start) (null)
(Secure Connection Start) (null)
(Secure Connection End) (null)
(Connect End) (null)
So the problem here was that the response header didn't have Content-Type set to application/json. When this header is not set properly, URLSession data task will buffer first 512 bytes of response.
More info can be found here: https://developer.apple.com/forums/thread/64875
Related
I have an api (nodejs) which saves my application data in MongoDB. But when I send the request, node throws an error which says that score is undefined
UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'score' of undefined
And when Xcode sends the request, the application works for about 30 seconds and then crashes and Xcode logs: "The request timed out."
this is my Swift code:
let parameters = ["score": scoreBoard]
print(parameters)
AF.request("http://localhost:4000/update/score", method: .post, parameters: parameters).responseDecodable(of: [jsonData].self) {response in
let json = JSON(response.data!)[0]["score"]
scoreBoard = json.rawString()!
}
The problem was with Node I didn't use a body parser. When I included a body-parser then it was able to retrieve the data from the body.
We have a POST endpoint in our serverless api which listens to a Magento 2 integration activation callback and processes the payload. The Content-Type of this callback request is application/x-www-form-urlencoded. However, when we try to get the callback, the lambda function finishes execution immediately, skipping the entire function body. What we see in the Cloudwatch logs is only this. Not even console.logs are printed. (the endpoint only prints a string to the console. No async operations are in place. Yet this problem persists)
2020-12-12T12:24:47.012+05:30 START RequestId: 4afba03d-54ef-4b5e-bd44-157b0b7a9f9b Version: $LATEST
2020-12-12T12:24:47.050+05:30 END RequestId: 4afba03d-54ef-4b5e-bd44-157b0b7a9f9b
2020-12-12T12:24:47.050+05:30 REPORT RequestId: 4afba03d-54ef-4b5e-bd44-157b0b7a9f9b Duration: 37.83 ms Billed Duration: 38 ms Memory Size: 128 MB Max Memory Used: 109 MB Init Duration: 893.79 ms
When we try to hit the same endpoint from POSTMAN with Content-Type: application/json, the endpoint works as expected.
Therefore we thought that the problem might be the Content-Type header and read somewhere that adding request mapping templated would solve this problem. Therefore, we even added a mapping template for content type application/x-www-form-urlencoded in the integration request of the lambda method with following content, time to time. But our problem was not solved unfortunately.
"{ "body": "$util.base64Decode($input.body)" }"
{
"formparams" : $input.json('$')
}
{
"body" : $input.json('$')
}
My question is: How we can set the endpoint to print the POST request payload, preventing it from immediate exiting?
We have been searching for a solution to this problem since a week. It would be a great help, if someone can input their helpful, valuable suggestions to solve this problem. Thanks in advance
Since the Content-Type of the Magento 2 Integration activation callback is application/x-www-form-urlencoded, the lambda event for that POST request was something like this.
console.log(event) -> {body: "a=var&b=other_var&c=another_var"}
The endpoint didn't even print anything because I had put console.log(JSON.parse(event. body)). This results in a JSON parse error and the endpoint immediately finishes execution.
When I started parsing the query parameter event body instead of JSON.parse(), the problem was solved.
I am a newbie to iOS and using Alamofire in my app. Everything is working fine. Now I want to implement network errors. I have searched about it and here are my findings:
We can implment request timed out in the following way:
let manager = Alamofire.SessionManager.default
manager.session.configuration.timeoutIntervalForRequest = 10
let urlVerifyEmail = ####
manager.request(urlVerifyEmail, method: .post, parameters: ["user_email" : email], encoding: JSONEncoding.default, headers: nil).responseJSON(completionHandler: { response in
switch response.result {
case .success:
print (“success”)
case .failure(let serverError):
if (serverError._code == NSURLErrorTimedOut)
{
print(”Request timed out”)
}
else
{
print(”Error sending request to server”)
}
}
}
)
I have read there official docs too. However I am not having much clarity.
What does request timed out actually mean? Does it mean that the app is taking too long to send the request? or server is taking too long to send the response back?
What are other types or network errors in Alamofire? What if the connection wasn't successfully made? What if it broke while the request was getting sent? What if it broke while the response was coming back?
If error code for request timed out is -1001 then what are the codes for other network errors? In order to provide the users with the best experience, which is the best approach to cover all of network errors?
Several people get this error for different reasons. None of the answers I've found have solved my problem.
I use Timberjack to log my Alamofire requests.
All my GET requests work fine and I receive data in JSON.
My POSTs on the other hand works around 1 out 10 times every time if the POST includes a JSON body.
The server does not specify any Keep-Alive header.
Deployment target is iOS 9.0
This is my shared Manager with Timberjack:
class HTTPManager: Alamofire.Manager{
static let sharedManager: HTTPManager = {
let configuration = Timberjack.defaultSessionConfiguration()
let manager = HTTPManager(configuration: configuration)
return manager
}()
}
Defining the request:
let parameters: [String: AnyObject] = ["status":status]
request = HTTPManager.sharedManager.request(.POST, "\(baseURL)\(uri)", parameters: parameters, encoding: .JSON).validate()
Sending the request:
request!.responseJSON(queue: queue, options: .AllowFragments, completionHandler: { (response) in
//Handling the response
})
Most of the time the server receives an empty JSON body. But sometimes it does work and the body is received and the server responds with an OK. When it doesn't work I receive the error:
Error: The network connection was lost.
FAILURE: Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost."
UserInfo={NSUnderlyingError=0x12fa47cb0 {Error Domain=kCFErrorDomainCFNetwork Code=-1005 "The network connection was lost."
If someone can explain what's happening here I would be forever grateful :)
EDIT 1
We let the server respond every call with "Connection": "close" which did nothing to help the problem. The app always sends "Connection": "keep-alive" by default and it cannot be changed. Could this be the problem? That the app thinks the connection is open even though it's closed by the server? But even though you wait a few minutes it seems as though the POST call only works at random.
EDIT 2
Even when I wait 30 seconds between GET(s) and/or POST(s). GET always works. POST works at random (rarely). I get the -1005 error on most POSTs. Even though I get the network connection was lost error the server still receive my request but the JSON body is missing.
EDIT 3 - Ugly solution
In my response I check for the error code -1005, when I receive this error I just recreate the request and try again. This results in sending around 2-4 POST requests to the server where one POST works and the rest have empty JSON bodies.
Restart simulator or kill your app by throwing out from tasks.
Or check more solutions to this error code:
NSURLErrorDomain Code -1005 The network connection was lost
I'm building a firefox add-on using the add-on sdk. I need to make a http request to a certain page and I want to handle the connection timeout but couldn't find anything in the api: https://addons.mozilla.org/en-US/developers/docs/sdk/latest/modules/sdk/request.html
What I'm actually looking is a callback in case the client couldn't connect to the server.
Is there a way to achieve this?
The SDK request will always call onComplete, when the request is considered done for the network. This means that onComplete is called in any case, disregarding if the request returned an error or a success.
In order to detect which error you've got, you need to check the Response object's (the object passed to the onComplete function) property "status" (response.status). It holds the status code for the request. To look up status codes, consider the list on the mozilla developer network. If the response status is 0, the request has failed completely and the user is probably offline, or the target couldn't be reached.
A timeout would either be a status code 504 or 0. The implementation would be similar to this:
var Request = require("sdk/request");
Request({
url: "http://foo.bar/request.target",
onComplete: function(response) {
if(response.status==0||response.status==504) {
// do connection timeout handling
}
// probably check for other status codes
else {
// assume the request went well
}
}
}).get();
I personally use a validation function on the request object, which returns me a number which depends whether I've got a correct response, an error from the web server or a connection issue (4xx and 0 status codes).