2

I'm working with a slightly unconventional API that is expecting a JSON body with a GET request and I have no control over this. Unfortunately, every time I attempt to make the request, it seems to completely disappear and never make it to the API. I originally wrote the request using a standard URLSession and then switched to try Alamofire in an attempt to fix it but ended with the same result. My request looks like this:

Alamofire.request("http://192.168.1.1:8000/connect/", method: .get, parameters: ["test": "test"], encoding: JSONEncoding.default)
  .responseJSON { response in
            
            let body = response.request?.httpBody
            guard response.result.isSuccess else {
                onCompletion(nil)
                return
            }
            
            onCompletion(response.result.value as! [String : Any]?)
        }

This exact code works for a different request where there is no JSON in the body, but seemingly the moment I add it, it just times out. This has already been discussed on the alamofire github repo (https://github.com/Alamofire/Alamofire/issues/1819) but the final comment with what should be working code isn't really any different to mine, so doesn't provide any help, nor do the other linked issues.

Printing the request with debugPrint gives me this curl command

$ curl -i \
  -H "Content-Type: application/json" \
  -d "{\"test\":\"test\"}" \
  "http://192.168.1.1:8000/connect/"

Which is missing the -X GET flag, but when I add that in, the request works as expected and the server responds, so I know the API itself is working and is happy processing the JSON in the body, so I'm at a loss as to what's going on.

I've installed Timberjack to attempt to trace things, which didn't give me any more info at all, just what I already knew

Request: GET http://192.168.1.1:8000/connect/
Headers: [
  Content-Type : application/json
  Content-Length : 24
]

Although I'm not sure if it's supposed to be showing me the body as well which it isn't?

In both cases (URLSession and Alamofire) the request gives the following output which I don't see at any other time:

2017-01-22 23:31:09.797453 my-app[3755:1349066] [] nw_endpoint_flow_service_writes [2 192.168.1.1:8000 ready socket-flow (satisfied)] Write request has 4294967295 frame count, 0 byte count
2017-01-22 23:32:04.484182 my-app[3755:1349066] [] __tcp_connection_write_eof_block_invoke Write close callback received error: [89] Operation canceled

Anyone have any ideas on what's going on as I'm completely at a loss at this point.

Update

I've done some more digging. If I change the endpoint to https://httpbin.org/get then the request goes through just fine and I get a response. Whilst this kind of suggests the API server is refusing to process the request, it's still working with the cURL command so that can't really be the issue.

I also forgot to mention (although not sure it should make a difference) that the API I'm trying to communicate with is connected via an ad-hoc wifi. Other requests to it work just fine though so I can definitely communicate with it.

Update 2

So I've been able to switch the server to using POST instead of GET and unsurprisingly it now works, however I would still love to know of a solution to the original problem

Community
  • 1
  • 1
PaReeOhNos
  • 4,338
  • 3
  • 30
  • 41
  • Did you try that solution to remove your message : http://stackoverflow.com/questions/39791692/error-tcp-connection-write-eof-block-invoke-write-close-callback-received-err ? Is this a background request ? – Ludovic Jan 23 '17 at 08:02
  • Yeah, it just suppresses the error logs, but doesn't do anything more than that. – PaReeOhNos Jan 23 '17 at 08:08
  • Ok. I had a similar problem, its was my json encoding that was wrong, try using this answer, did the trick for me http://stackoverflow.com/a/39959559/1385773 – Ludovic Jan 23 '17 at 08:14
  • well the encoding itself seems fine. I've inspected what is being request and the JSON appears to be fine, and oddly changing the request URL to `https://httpbin.org/get` seems to work as expected – PaReeOhNos Jan 23 '17 at 08:34
  • Do you have access to your web server logs ? Did you receive a response from this server ? If the web server receive a request it always send back a response even if it's an error (500). Maybe you should use a tool like Postman to debug what's happened ? – Ludovic Jan 23 '17 at 09:07
  • uhh not sure, I'll have a dig around and see if I can find anything. I've contacted the developer that wrote the API and see if I can get the action changed to a POST. Would probably make this whole thing a lot easier :( I've tried to use Postman, but that doesn't seem to support putting a body in a GET request (understandably) – PaReeOhNos Jan 23 '17 at 09:16

1 Answers1

0

URLSession and CFHTTPMessage cannot send a message body for a GET request. They send the content length for the body, but do not send the body itself. This results in a timeout.

In order to resolve this issue I've used libcurl to handle the GET requests which have a message body to my project. I use URLSession everywhere else. When you add a body to a request using libcurl it changes the request to a POST, but that can be changed back to a GET after setting the body and before submitting the request.

Howard Shere
  • 143
  • 1
  • 7