かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

ストリーミングのAPIにPostでアクセスするとき

HttpClientのPostAsyncだとStreamを全部読み終わるまで帰ってこないみたいです。 そんなAPIって何?っていうとTwitterのこれとかがそうみたいです。

そんなときはPostAsyncじゃなくて、もう一段抽象度の低いSendAsyncメソッドを使ってHttpRequestMessageを組み立ててSendAsyncするといいです。SendAsyncメソッドの引数にHttpCompletionOptionを受け取るものがあって、これの引数をHttpCompletionOption.ResponseHeadersReadに指定すると、BodyじゃなくてHeaderだけ読み取ったら制御を返してくれます。

例えばTwitterにアクセスできるHttpClientがclientという変数であるとして、上のドキュメントの通りtrack=twitterというBodyで送るコードは以下のようになります。

var apiUrl = "https://stream.twitter.com/1.1/statuses/filter.json";
var req = new HttpRequestMessage(HttpMethod.Post, apiUrl);
req.Content = new FormUrlEncodedContent(new Dictionary<string, string> 
{ 
    {"track", "twitter"} 
});
// タイムアウト無制限
client.Timeout = Timeout.InfiniteTimeSpan;
var res = await client.SendAsync(req, HttpCompletionOption.ResponseHeadersRead);
Debug.WriteLine(res);
using (var sr = new StreamReader(await res.Content.ReadAsStreamAsync()))
{
    while(!sr.EndOfStream)
    {
        // 何か処理をする
        Debug.WriteLine(await sr.ReadLineAsync());
    }
}