L’API Streaming de Twitter avec le HttpClient .net

La recherche et le streaming

Un des fonctionnalités intéressantes de l’API Twitter est l’utilisation du Streaming. Tout comme la recherche, cette API nous permet de spécifier un mot clé et de récupérer les tweets liés à ce mot clé. Cet article a pour but de vous montrer la différence entre la recherche et le streaming sur l’API Twitter ainsi que l’implémentation de ce streaming en C#.

La différence entre l’API de recherche et l’API de streaming réside en la manière de récupérer les tweets. Avec la première, vous envoyez une requête au serveur Twitter qui vous retourne alors page par page les tweets correspondant à la recherche dans une seule et même réponse. Le fonctionnement est celui d’un échange client-serveur classique :


(crédits image : https://dev.twitter.com )

Principe du streaming

Concernant le streaming, les tweets retournés ne vont pas l’être dans une seule et même réponse. En effet le serveur maintiendra la connexion indéfiniment et dès qu’un nouveau tweet concerné par la recherche faite va être soumis à Twitter, celui ci va nous être retourné dans la foulée. Ce cas d’utilisation est notamment intéressant dans des applications de type “live tweet” :

(crédits image : https://dev.twitter.com )

Implémentation en C#

L’url de requête sera https://stream.twitter.com/1.1/statuses/filter.json en POST. A cela s’ajoute un ou plusieurs paramètres. Pour une utilisation de base, nous ajouterons le paramètre “track” qui aura comme valeur votre recherche (un hashtag ou tout simplement un mot ).

Cette requête ne semble pas compliquée, mais l’extrait de code suivant, qui fonctionne dans le cas d’une simple recherche, va ici échouer. Le souci ne vient pas directement de ce code mais de la librairie OAuth que j’avais réalisée suite à un de mes précédents articles (code source disponible en une seule classe ici : https://skydrive.live.com/?cid=230FED47B214039C&id=230FED47B214039C%212851 )

static async void ComputeStreaming(string search)
{
    OAuthRequester.ComputeHmacSha1 = ComputeHMACSHA1Hash;
    string consumerKey = "yourConsumerKey";
    string consumerSecret = "yourConsumerSecret";
    string oauthToken = "yourOAuthToken";
    string oAuthTokenSecret = "yourTokenSecret";
    string searchUrl = 
"https://stream.twitter.com/1.1/statuses/filter.json"; Dictionary<string, string> contentParams = new Dictionary<string, string>(); contentParams.Add("track", search); var searchRequest = OAuthRequester.SignRequest(HttpMethod.Post,
searchUrl, consumerKey, consumerSecret, contentParams,
oauthToken, oAuthTokenSecret);
using (StreamReader reader = new StreamReader(
await (await searchRequest).Content.ReadAsStreamAsync())) { while (!reader.EndOfStream) { string result = reader.ReadLine(); JObject root = JObject.Parse(result); Console.WriteLine(root["text"].ToString()); } } }

Il n’y pas forcément d’erreur de conception dans ma librairie, l’erreur serait similaire avec l’utilisation de “WebClient” ou “WebHttpRequest”. De la même manière, la requête sera lancée, mais rien ne sera renvoyé et au bout d’une minute, vous recevrez un timeout. Le souci provient de la manière dont HttpClient traite la réponse par défaut, le client a bien commencé à recevoir la réponse, mais il attend d’avoir reçu tous le contenu avant de renvoyer votre objet “HttpResponseMessage”. Or, le principe du streaming est de laisser la connexion ouverte et de recevoir le contenu au fur et à mesure, donc HttpClient ne peut pas gérer le cas de figure de cette manière. Mais, heureusement, il suffit d’une petite modification pour gérer le cas particulier des réponses sous forme de flux et non de sous forme de contenu entier. Il suffit de modifier l’appel de la méthode “client.SendAsync(…)”, dans notre cas, nous utiliserons la surcharge suivante:

HttpResponseMessage response = await client.SendAsync(request,
HttpCompletionOption.ResponseHeadersRead);

La différence réside en l’ajout du paramètre de type “HttpCompletionOption” qui, s’il est omis, prend par défaut la valeur “ResponseContentRead” qui signifie que HttpClient attend de recevoir tout le contenu de la réponse avant de la traiter. La valeur qui nous intéresse ici est “ResponseHeaderRead” qui signifie que la réponse sera traitée dès que les header seront reçus. Le contenu en lui même sera reçu plus tard, lors de l’appel de “ReadAsStreamAsync()”. Avec la modification de la requête, vous pouvez à présent tester le code un peu plus haut qui fonctionnera cette fois-ci (testez avec un sujet populaire du moment pour voir le streaming agir ).

Conclusion

Parfois complexe à utiliser dans certains SDK, l’API streaming de Twitter consiste en une simple requête en POST. La seule petite difficulté est de ne pas attendre de recevoir tous le contenu pour traiter la requête comme le font par défaut les clients HTTP en .net mais de la traiter dès réception des headers. HttpClient permet ce traitement particulier avec la modification du paramètre HttpCompletionOption.
La mise à jour de la classe helper OAuth 1.0 est disponible ici.

Par Mathieu Hollebecq

2 réponses à “L’API Streaming de Twitter avec le HttpClient .net

  1. Bonjour,
    je voulais tester votre classe mais me trouve bloquée sur la constante ComputeHMACSHA1Hash que Visual Studio Express 2013 ne reconnait pas « Le nom n’existe pas dans le contexte actuel ». Je suppose qu’il manque une référence ou un namespace,mais ne trouve pas. Je suis loin d’être une pro et serais comblée si vous pouviez m’aider.
    J’utilise le Framwork 4.5.
    Merci bien.

  2. Mathieu Hollebecq

    En effet, j’ai oublié de noter qu’étant donné que je suis dans un portable class library, je ne peux pas utiliser directement la cryptographie qui a ses propres classes sur les différentes plateformes. Je laisse néanmoins la possibilité de « setter » la propriété « ComputeHMACSHA1 » sur chaque plateforme utilisant ma librairie. Par exemple sur Windows Phone si j’initialise dans un ViewModel, ma méthode ComputeHMACSHA1Hash sera celle ci :

    public MyViewModel()
    {
    OAuthRequester.ComputeHmacSha1 = ComputeHMACSHA1Hash;
    }

    private byte[] ComputeHMACSHA1Hash(byte[] toHash, byte[] key)
    {
    System.Security.Cryptography.HMACSHA1 ciffer = new System.Security.Cryptography.HMACSHA1(key);
    return ciffer.ComputeHash(toHash);
    }

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s