Archives de Catégorie: Developpement

Introduction aux shapefile

Une utilisation cartographique

En voulant m’intéresser à titre personnel aux données cartographiques, j’ai téléchargé sur le site de l’IGN la base de données Route 500, disponible sous licence ouverte. Cette base de données contient les données de 500 000 km de routes en France métropolitaine.

L’archive (161 Mo compressés, 857 décompressés) contient plusieurs descriptifs et des métadonnées, je ne les ai pas consultés entièrement mais je salue l’initiative de joindre des descriptifs. Qui n’a jamais téléchargé  une archive au nom obscur  et oublié distraitement son utilité plusieurs mois plus tard ? Clignement d'œil

Je ne savais pas du tout à quoi m’attendre comme format de fichier en téléchargeant cette base, uniquement l’indication “format Shapefile”.  En fouillant différents dossiers, dont je présumais que l’arborescence n’avais pas beaucoup d’importance, j’ai repéré non pas différents fichiers mais plusieurs ensembles de fichiers. En effet, chaque “fichier” semblait en fait constitué de plusieurs fichiers aux noms identiques mais  aux extensions différentes (cpg, dbf, prj, shp et shx). Aucune de ces extensions ne m’était connue, et en tant que curieux bien trop hâtif, je me suis bien entendu précipité pour essayer de lire ces fichiers au plus vite avec un éditeur de texte, bien entendu sans avoir lu la moindre documentation au préalable. Seulement, avec un éditeur de texte, seuls les fichiers prj et cpg étaient lisibles, les différents cpg contenant toujours “1252” et les différents prj contenant à chaque fois un ensemble de constantes semblables à des sortes de référentiels géographiques. Quant aux autres fichiers, les plus volumineux, ils étaient illisibles (partiellement pour les dbf et totalement pour les shx et shp). Je n’ai donc pas pu éviter de lire dans un premier temps un bref descriptif encyclopédique puis une documentation complète.

Le format

Contenu général

Habitué à parser du json, du xml, des csv ou d’autres formats simples, le format shapefile m’a beaucoup surpris au départ ! Tout d’abord, comme énoncé plus haut, il n’est non pas composé d’un fichier, ni de deux, mais de trois fichiers (minimum)! Ensuite, il est quasiment impossible (mis à part pour le fichier dbf où on devine des chaines de caractères) de lire les fichiers principaux avec un éditeur de texte. En effet, le format datant des années 90, plusieurs centaines de mégaoctets de données représentaient une empreinte de stockage important, il était alors surement impensable de stocker des données sous forme de texte brut. En prenant simplement l’exemple d’un nombre entier, celui-ci sera stocké dans exactement 4 octets en format binaire au lieu de jusqu’à 10 octets en encodage de texte brut. Ainsi, il est totalement impossible de parser le fichier sans documentation. Néanmoins celle ci n’est pas très compliquée à comprendre.

Le fichier le plus important, celui contenant les formes en elles-mêmes, le shp, est constitué de deux parties. La première partie est un en-tête de taille fixe contenant différentes métadonnées comme un type de géométrie, un nombre d’objet présent et une taille par objet. Il suffit donc ensuite de lire le fichier par blocs de taille indiquée, pour trouver le nombre préconisé d’objet au format opportun.

L’endianisme

Le premier point du format qui m’a beaucoup surpris (et mit un petit moment en difficulté) est l’endianisme. Pour ceux qui ne connaissent pas ce terme ni sa traduction anglaise (endianess), cela correspond au sens de lecture de nombres quand ceux-ci ont sur plusieurs octets. Vu qu’un exemple vaut mille discours, imaginez un nombre entier codé sur 4 octets : 0x1A2B3C4D, qui, si on le découpe en octets, se présentera pour un développeur ainsi :

Poids de l’octet 3 2 1 0
Octet 1A 2B 3C 4D

Le premier octet ainsi rencontré est l’octet de poids-fort, ce sens est appelé “Big-endian”. Celui ci à l’avantage de se lire “naturellement” pour un humain mais a l’inconvénient de devoir être lu en commençant par la fin pour une machine. Pour palier à ce problème à l’ère des premiers processeurs, certains systèmes d’exploitation ont alors implémenté le “Little-endian”, c’est à dire la lecture des octets en commençant par celui de poids faible et terminant par ceux de poids forts. Le même nombre en little-endian sera noté ainsi : 4D3C2B1A.

Poids de l’octet 0 1 2 3
Octet 4D 3C 2B 1A

Le problème qu’a le format shapefile avec l’endianisme n’est pas qu’il en utilise un différent de celui de ma machine (Windows sur x86 étant en little-endian), mais qu’il utilise les deux ! En effet, les octets de 0 à 27 du début du fichier sont composés de 7 entiers notés en big-endian puis sont suivis de deux entiers et 8 décimaux notés en…little endian ! De même pour chaque enregistrement du fichier, l’en-tête sera en big-endian alors que les enregistrements eux-mêmes sont composés d’entiers ou de décimaux en little-endian ! Il m’a donc fallu adapter les méthodes de lectures de nombres pour spécifier l’endianisme….

La projection

Il m’est venu ensuite un problème de projection vis à vis des coordonnées. Ce problème n’est pas directement lié au format shape, mais plutôt son utilisation par l’IGN et l’administration française. En effet, nous avons l’habitude d’utiliser des coordonnées dans le système WGS83 (pour World Geodetic System 1983) sous forme de degrés géographiques, ou plus communément appelées “coordonnées GPS”. Ici, les fichiers fournis présentent des données dans la projection cartographiques Lambert 93. Pour faire simple et rapide : je n’ai tout simplement pas réussi à faire la conversion, malgré de la documentation, pourtant en français, je n’arrive pas à implémenter le calcul…

Mis à part cela, une fois les en-têtes de fichiers et d’enregistrement décodés, il suffit d’implémenter la lecture des différents types de données présents, une dizaine en tout mais toujours un seul type dans un même fichier. Ce format n’est ni nouveau, ni complexe et son utilisation est répandue, maitriser son utilisation ne présente pas un gros avantage technologique. Néanmoins, implémenter tous le format peut être assez long pour une seule personne donc autant partager ce code. J’en ai donc profité pour créer un repository (en C#) sur GitHub ! N’hésitez pas à aller  voir mon code, me faire des retours, voire participer (surtout si vous-mêmes ou une de vos connaissance sait convertir des coordonnées Lambert 93 en WGS83…).

Pour la documentation des fichiers shape : ici (et un complément ici pour les fichiers dBASE). Et, encore une fois, si par chance l’un de vous saurait m’aider à implémenter ce calcul,qu’il se fasse connaitre Clignement d'œil

Par Mathieu Hollebecq

Enregistrer

Publicités

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

OAuth 1.0 en bref

Cette article fait partie d’une série dédiée au protocole OAuth

1 – OAuth 1.0 en bref
2 – Exemple de Twitter avec C# et HttpClient

Aujourd’hui utilisé par bon nombre de services populaires, comme Twitter, Tumblr ou encore Facebook, pour exposer leur API publique, OAuth est un protocole d’autorisation qui en est aujourd’hui à sa version 2.0. Il réside certaines différences assez notables entre la version 1.0 et la plus récente, la 2.0. Néanmoins, ce protocole est encore utilisé dans sa version 1.0 par des services très populaires, comme Twitter, c’est donc pour cela que cet article traitera de la version 1.0.

Cet article se veut volontairement détaché de tout langage de programmation pour cibler n’importe quel développeur curieux. Néanmoins il sera suivi d’un article d’exemple d’implémentation de l’OAuth 1.0 en C# pour effectuer une requête à l’API Twitter

Pourquoi OAuth ?

Avant d’expliquer pourquoi OAuth, mettons d’abord en évidence les différents acteurs impliqués dans ce protocole:

  • Le propriétaire des ressources, autrement dit : l’utilisateur final. Il souhaite accéder à un service sur un serveur hébergeant des données qui lui sont propres.
  • Le serveur : le service en lui même hébergeant les ressources de l’utilisateur et mettant en place une API utilisable par des applications tierces.
  • Le client : application ou site web tiers non affilié au serveur fournissant le service. Ce client doit être explicitement autorisé par le propriétaire des ressources d’accéder aux ressources appartenant au client sur le serveur.

Pour donner un exemple de ces trois entités, imaginez un utilisateur final ayant installé une application sur son Smartphone permettant de faire des achats en ligne. Une fois ses achats effectués, l’utilisateur est invité par l’application à mettre à jour son statut Facebook pour montrer à ses amis qu’il a utilisé cette application pour acheter certaines choses. Ainsi, l’application “facilite” le travail de l’utilisateur en pré-remplissant le texte du statut et en y ajoutant une photo correspondante, il suffit alors à l’utilisateur de valider directement depuis l’application pour voir son statut Facebook mis à jour. Dans cet exemple, le propriétaire de ressources est l’utilisateur de l’application, l’application est le client et Facebook est le serveur. Ainsi l’utilisateur possède des informations personnelles (propriétaire de ressources) sur Facebook (serveur) et délègue la rédaction de son statut à l’application smartphone (le client).

OAuth a vu le jour face au potentiel risque de sécurité qui pouvait se poser lorsque le propriétaire de ressources ne pouvait s’authentifier à une API d’un serveur par le biais d’un client tiers que par son couple identifiant/mot de passe. Ainsi pour maintenir l’authentification, le client doit garder une trace du mot de passe de l’utilisateur en clair ! De même l’utilisateur ne peut ni donner un accès partiel à un client (par exemple de la lecture seule) ni révoquer l’accès à un client (à moins de modifier son mot de passe, mais cela révoquerai TOUT les accès des clients tiers).

Comme alternative à ça, OAuth propose l’utilisation d’un jeton (access token) propre à l’utilisateur et au client pouvant être valide uniquement dans un certain laps de temps et pour seulement une partie définie des services du serveur. Ainsi, l’utilisateur n’expose à aucun moment son mot de passe au client, il peut donner un accès restreint à ses ressources et peut révoquer ses accès comme bon lui semble sans avoir à changer son mot de passe et sans modifier les accès d’autres clients tiers au service.

OAuth en bref

Processus

Le processus simplifié d’obtention du jeton d’accès est le suivant : le serveur fournit au client sa propre clé unique d’authentification (consumer key) avec sa clé privée (consumer secret). Cette clé du client sera inclue dans une url de redirection envoyée au propriétaire de ressource dirigée vers la page d’authentification du serveur. Ainsi l’utilisateur s’identifie directement au serveur sans fournir son identifiant et son mot de passe au client, et le serveur (grâce à la consumer key contenue dans la requête) pourra identifier le client pour afficher clairement à l’utilisateur quels droits et à qui il est sur le point d’octroyer. Une fois l’authentification sur le serveur faite, un jeton d’accès (access token) sera généré et renvoyé au client (identifié par sa clé ).

Pour faire une comparaison simple de ce que représente un access token, imaginez un parc d’attraction, un trousseau de clé ouvre ce parc et toutes ses attractions, mais pour donner au public l’accès au parc, le gérant ne va pas, en toute logique, faire des copies du trousseau de clés pour les donner aux visiteurs car de cette manière il leur donne accès à TOUT le parc, même les zones interdites et cet accès sera impossible à révoquer, sauf en changeant les serrures, mais changer les serrures interdira alors l’accès à tous les visiteurs ayant eu les clés et pas juste à celui à qui l’on veut interdire l’accès. Au lieu de donner un trousseau, on va simplement donner à chacun un ticket nominatif et chaque ticket aura un type (par exemple “enfant” pour juste les attractions enfantines, un ticket “premium” donnant accès aux spectacles du soir, etc…) et vérifier ce ticket à l’entrée de chaque attraction, ainsi seules les attractions autorisées par le type du ticket seront accessibles et si un visiteur ne respecte pas le règlement intérieur on peut révoquer son ticket sans gêner l’accès des autres visiteurs. De même, le ticket ne sera valable que durant un nombre précis de jours, et non à vie.

Etape par étape:

1 – Le client, identifié par sa clé unique, fait une demande de oauth token au serveur en signant la requête avec sa clé privée.
2 – L’utilisateur est redirigé vers une url sur laquelle il est invité à s’authentifier. Le oauth token doit être fourni soit en paramètre dans l’url soit fourni directement par l’utilisateur.
3 – L’utilisateur s’authentifie et accepte de fournir au client l’accès à ses données via l’API.
4 – Un access token et un access token secret propres à l’utilisateur et au client sont envoyés au client. Plusieurs manières peuvent opérer:
4.a : Si le client est capable de recevoir une requête du serveur, celui ci lui envoi directement la paire de token
4.b : Si le client n’est pas capable de recevoir de requête du serveur (application mobile ou application bureau), un code “PIN” est fourni à l’utilisateur et ce dernier le fourni au client. Le client doit alors refaire une requête au serveur en incluant son oauth token et le PIN de l’utilisateur pour recevoir en réponse le couple d’access token.
5 – A présent le client peut accéder aux données de l’utilisateur en utilisant sa consumer key et l’access token de l’utilisateur tout en signant la requête par le couple consumer secret et access token secret.

(Schéma d’authentification OAuth, cliquez pour voir l’image originale)

Construire et signer les requêtes

Paramètres OAuth

Une requête OAuth consiste en une requête HTTP classique mis à part que celle ci doit être signée par une clé privée. Pour signer la requête, il convient d’abord de distinguer deux types de paramètres qui devront être donnés à la requête: les paramètres OAuth et les autres paramètres liés au service demandé.

Les paramètres oauth sont au nombre de sept:
oauth_nonce : une chaine de caractère aléatoire
oauth_timestamp : nombre de secondes écoulées depuis le 1er janvier 1970
oauth_version : version du protocole, 1.0 dans notre cas
oauth_signature_method : méthode utilisée pour signer la requête, oauth supporte “PLAINTEXT”, “HMAC-SHA1” et “RSA_SHA1”. Néanmoins, les serveurs sont libres de ne pas supporter toutes ces méthodes. Pour la suite nous parlerons de la méthode “ »HMAC-SHA1”
oauth_consumer_key : la consumer key du client
oauth_token : l’access token (uniquement lorsque l’on a effectivement ce token, si on ne l’a pas, on omet ce paramètre)
oauth_signature : la signature de la requête

Le nonce et le timestamp peuvent servir au serveur s’il souhaite limiter le nombre de requêtes avec un même couple timestamp/nonce.

Signer la requête

(NOTE : n’étant pas sur de la traduction française du terme anglophone “percent encode”, j’utiliserais simplement le terme “encoder” pour faire référence à cet encodage. Il consiste à encoder, pour tout les caractères qui ne sont pas alphanumériques ou bien dans l’ensemble “-._~”, par le caractère pourcent ( % ) suivi de la représentation hexadécimale majuscule du caractère, par exemple “:” donne “%3A” )

Signer la requête consiste en la génération d’un signature base string puis de son hachage avec HMAC-SHA1 (hachage SHA1 mais en utilisant une clé de hachage ). La signature base string est composé de (dans l’ordre EXACT au caractère et à l’encodage près ! ) :

  • La méthode HTTP en majuscule (GET, POST, DELETE,….)
  • Un caractère ‘&’
  • L’url de base (sans les paramètres GET) encodée
  • Un caractère ‘&’
  • L’ensemble des paramètres placés de la manière suivante :
    • Les paramètres doivent être placés par ordre alphabétique de leur nom
    • Chaque paramètre est séparé par un ‘&’
    • Le nom et la valeur de chaque paramètre sont placés ainsi : le nom encodé, le caractère ‘=’ et la valeur encodée (s’il n’y a pas de valeur, nous ne plaçons rien entre le ‘=’ et le ‘&’ séparant du paramètre suivant)

Une fois la signature base string obtenue, nous la hachons avec la ou les clés privées concaténées de la manière suivante:
-La clé consumer secret
-Un caractère ‘&’
-Si l’utilisation de l’access token secret s’applique, nous la concaténons, sinon nous nous arrêtons là pour la formation de la clé de hachage.
 

Obtenir l’Authorization Header

L’authorization header sera une information placée dans le header “Authorization” de la requête. Il contiendra les paramètres oauth utilisés précédemment en y ajoutant la signature. C’est à partir de cet authorization header que le serveur récupèrera les informations lui permettant ou non d’autoriser la requête, cet header sera formé de la manière suivante:

  • le mot  “OAuth” suivi d’un espace
  • chaque paramètre oauth placés de la manière suivante
    • Chaque paramètre est séparé par un espace
    • Le nom et la valeur de chaque paramètre sont placés ainsi : le nom, le caractère ‘=’, le caractère ‘ »’ (double quote), la valeur encodée et un autre caractère ‘ »’ (double quote)

Puis il ne manque plus qu’à renseigner le header “Authorization” avec la valeur obtenue précédemment.

Vérifications

Une fois la requête construite et signée, il ne vous manque plus qu’à lui ajouter les autres paramètres (tous ceux qui ne commencent pas par “oauth_”); pour la méthode HTTP GET en mettant les paramètres dans l’url, pour les autres méthodes dans le header “Content”.

Lors du développement, à des fins de tests et de vérifications, je vous conseille d’utiliser la console de test oauth de Linkedin. Si vous lui fournissez les paramètres qu’elle demande, elle vous fournira la signature base string, la signature ainsi que l’authorization header que vous devriez obtenir. Etant donné que cette console de test ne produit aucune vrai requête à l’url que vous lui fournissez, rien ne vous empêche de ne pas lui fournir vos vrais clé mais plutôt des fausses clés que vous utilisez pour tester simplement la construction de la signature et des header.

Pour une documentation beaucoup plus exhaustive, vous pouvez consulter la norme RFC 5849 (en anglais).

Par Mathieu Hollebecq