Reading headers from HttpResponseMessage before the content is 100% full

  • How do I access the response headers before the entire response is sent back?
  • How to read a stream as it arrives?
  • Is HttpClient my best bet for such close monitoring of an HTTP response?

Here is a snippet that can illustrate my question:

using (var response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead)) { var streamTask = response.Content.ReadAsStreamAsync(); //how do I check if headers portion has completed? //Does HttpCompletionOption.ResponseHeadersRead guarantee that? //pseudocode while (!(all headers have been received)) //maybe await a Delay here to let Headers get fully populated access_headers_without_causing_entire_response_to_be_received //how do I access the response, without causing an await until contents downloaded? //pseudocode while (stremTask.Resul.?) //ie while something is still streaming //? what goes here? a chunk-read into a buffer? or line-by-line since it http? ... 


Edit to clarify for me one more grayness:
Any link that I found has a kind of blocking statement that will make it wait until the content appears. Links I usually read accessor methods or properties in streamTask.Result or on Content, and I don’t know enough to exclude which such links are suitable, as StreamTask progresses against what will cause it to wait until the task completes.

+6
source share
2 answers

Based on my own testing, the content will not be transferred until you start reading the content stream and you are correct that the call to Task.Result is a blocking call, but in itself it is a synchronization point. But it does not block the preliminary buffer of all content, it is blocked only until the content begins to arrive from the server.

Thus, an infinite flow will not be blocked for an infinite amount of time. Thus, trying to get the stream asynchronously might be considered redundant, especially if your header processing is relatively short. But if you want, you can always process the headers while the content stream is being processed in another task. Something like this will accomplish this.

 static void Main(string[] args) { var url = "http://somesite.com/bigdownloadfile.zip"; var client = new HttpClient(); var request = new HttpRequestMessage(HttpMethod.Get, url); var getTask = client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); Task contentDownloadTask = null; var continuation = getTask.ContinueWith((t) => { contentDownloadTask = Task.Run(() => { var resultStream = t.Result.Content.ReadAsStreamAsync().Result; resultStream.CopyTo(File.Create("output.dat")); }); Console.WriteLine("Got {0} headers", t.Result.Headers.Count()); Console.WriteLine("Blocking after fetching headers, press any key to continue..."); Console.ReadKey(true); }); continuation.Wait(); contentDownloadTask.Wait(); Console.WriteLine("Finished downloading {0} bytes", new FileInfo("output.dat").Length); Console.WriteLine("Finished, press any key to exit"); Console.ReadKey(true); } 

Note that there is no need to check whether part of the headers is complete, you explicitly indicated that with the HttpCompletionOption.ResponseHeadersRead option. The SendAsync task SendAsync not continue until headers are received.

+4
source

The result, using the await / async keywords, is even more readable:

 var url = "http://somesite.com/bigdownloadfile.zip"; using (var httpClient = new HttpClient()) using (var httpRequest = new HttpRequestMessage(HttpMethod.Get, url )) using(HttpResponseMessage response = await httpClient.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead)) using (Stream stream = await response.Content.ReadAsStreamAsync()) { //Access to the Stream object as it comes, buffer it or do whatever you need } 
+3
source

All Articles