NSURLSession data tasks always buffer the first 512 bytes unless content type is JSON?

Does NSURLSession data tasks buffer the first 512 bytes before it calls URLSession:dataTask:didReceiveResponse:completionHandler: as well as URLSession:dataTask:didReceiveData:? And is the buffering disabled when the Content-Type is application/json?


I was experimenting with NSURLSession and was hoping to make it possible for my app to do something as soon as the HTTP header is received or as the first batch of raw data is received. I wrote a simple server to test, but what I described below can also be tested with services like httpbin.org. I noticed that:


  1. URLSession:dataTask:didReceiveResponse:completionHandler: is only called before URLSession:dataTask:didReceiveData: is called, though the doc says the former "[tells] the delegate that the data task received the initial reply (headers) from the server", and I thought it meant that the delegate method would be called as soon as the header is received even if the response body is not yet seen, but that doesn't seem to be the case.
  2. URLSession:dataTask:didReceiveData: is only called for the first time when the server sends 512 bytes in total (or closes the connection if the total content length is less than that). After the first 512 bytes, the delegate method is called as soon as a new batch of data is received. If Transfer-Encoding is used for chunking, the 512 bytes apply to the decoded bytes, not the raw bytes over the wire.
  3. However, if Content-Type is application/json, URLSession:dataTask:didReceiveData: will be called as soon as one byte is received. This Stack Overflow discussion mentioned this seemingly undocumented behavior.


One can see the buffering in action with a simple HTTP server, or just use httpbin.org, for example with https://httpbin.org/drip?numbytes=1024&duration=8; if you use "curl -N" to fetch that URL, you'll see some characters received soon after the the request started, but if you use a data task to fetch it, it'll be a few seconds until the two delegate methods mentioned above are called, and the first batch of data is always >= 512 bytes long.


The thing about this is that they don't seem to be documented anywhere, and I appreciate if there are some clarifications on the API contract. Thanks!

Post not yet marked as solved Up vote post of lukhnos Down vote post of lukhnos
2.3k views

Replies

I'm interested in this as well.


I feel like as soon as the headers are received from the server that didReceiveResponse should be called, and likewise, as soon as any data is received, `didReceiveData` should be called.

I'm running into this issue as well. At a minimum, this should be documented. I think this is pretty ridiculous behavior, I don't see the benefit in the normal case to have such a restriction. A slow or quiet stream of data regardless of Content-Type should be immediately delivered as soon as data is received. I can understand buffering- but there should be a flush interval and the library should not wait for the whole buffer to fill up.

Seems to be an issue still?!

I'm beyond flabbergasted this is still an issue!

Seems to be an issue still?!

application/octet-stream work too