かずきのBlog@hatena

日本マイクロソフトに勤めています。このブログは個人ブログなので、ここに書いている内容は個人的な意見で会社の公式見解ではない点にご注意ください。好きなものは XAML と C# 。苦手なものは型の無い言語です。

ストリーミングの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());
    }
}