"how to use urlsessionstreamtask with urlsession for chunked-encoding transfer" Code Answer
4
received lots of info courtesy of quinn "the eskimo" at apple.
alas, you have the wrong end of the stick here. urlsessionstreamtask is for wrangling a naked tcp (or tls over tcp) connection, without the http framing on top. you can think of it as a high-level equivalent to the bsd sockets api.
the chunked transfer encoding is part of http, and is thus supported by all of the other urlsession task types (data task, upload task, download task). you don’t need to do anything special to enable this. the chunked transfer encoding is a mandatory part of the http 1.1 standard, and is thus is always enabled.
you do, however, have an option as to how you receive the returned data. if you use the urlsession convenience apis (datatask(with:completionhandler:) and so on), urlsession will buffer all the incoming data and then pass it to your completion handler in one large data value. that’s convenient in many situations but it doesn’t work well with a streamed resource. in that case you need to use the urlsession delegate-based apis (datatask(with:) and so on), which will call the urlsession(_:datatask:didreceive:) session delegate method with chunks of data as they arrive.
as for the specific endpoint i was testing, the following was uncovered:
it seems that the server only enables its streaming response (the chunked transfer encoding) if the client sends it a streaming request. that’s kinda weird, and definitely not required by the http spec.
fortunately, it is possible to force urlsession to send a streaming request:
create your task with uploadtask(withstreamedrequest:)
implement the urlsession(_:task:neednewbodystream:) delegate method to return an input stream that, when read, returns the request body
profit!
i’ve attached some test code that shows this in action. in this case it uses a bound pair of streams, passing the input stream to the request (per step 2 above) and holding on to the output stream.
if you want to actually send data as part of the request body you can do so by writing to the output stream.
received lots of info courtesy of quinn "the eskimo" at apple.
alas, you have the wrong end of the stick here. urlsessionstreamtask is for wrangling a naked tcp (or tls over tcp) connection, without the http framing on top. you can think of it as a high-level equivalent to the bsd sockets api.
the chunked transfer encoding is part of http, and is thus supported by all of the other urlsession task types (data task, upload task, download task). you don’t need to do anything special to enable this. the chunked transfer encoding is a mandatory part of the http 1.1 standard, and is thus is always enabled.
you do, however, have an option as to how you receive the returned data. if you use the urlsession convenience apis (
datatask(with:completionhandler:)
and so on), urlsession will buffer all the incoming data and then pass it to your completion handler in one largedata
value. that’s convenient in many situations but it doesn’t work well with a streamed resource. in that case you need to use the urlsession delegate-based apis (datatask(with:)
and so on), which will call theurlsession(_:datatask:didreceive:)
session delegate method with chunks of data as they arrive.as for the specific endpoint i was testing, the following was uncovered: it seems that the server only enables its streaming response (the chunked transfer encoding) if the client sends it a streaming request. that’s kinda weird, and definitely not required by the http spec.
fortunately, it is possible to force urlsession to send a streaming request:
create your task with
uploadtask(withstreamedrequest:)
implement the
urlsession(_:task:neednewbodystream:)
delegate method to return an input stream that, when read, returns the request bodyprofit!
i’ve attached some test code that shows this in action. in this case it uses a bound pair of streams, passing the input stream to the request (per step 2 above) and holding on to the output stream.
if you want to actually send data as part of the request body you can do so by writing to the output stream.
and you can call the networking code from anywhere such as:
hope this helps.