|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692 |
- <!doctype html><!-- This is a valid HTML5 document. -->
- <!-- Screen readers, SEO, extensions and so on. -->
- <html lang=fr>
- <!-- Has to be within the first 1024 bytes, hence before the <title>
- See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
- <meta charset=utf-8>
- <!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
- <!-- The viewport meta is quite crowded and we are responsible for that.
- See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
- <meta name=viewport content="width=device-width,minimum-scale=1,initial-scale=1,shrink-to-fit=no">
- <!-- Required to make a valid HTML5 document. -->
- <title>Sortir le Web des silos (archive) — David Larlet</title>
- <!-- Generated from https://realfavicongenerator.net/ such a mess. -->
- <link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons/apple-touch-icon.png">
- <link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons/favicon-32x32.png">
- <link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons/favicon-16x16.png">
- <link rel="manifest" href="/manifest.json">
- <link rel="mask-icon" href="/static/david/icons/safari-pinned-tab.svg" color="#5bbad5">
- <link rel="shortcut icon" href="/static/david/icons/favicon.ico">
- <meta name="apple-mobile-web-app-title" content="David Larlet">
- <meta name="application-name" content="David Larlet">
- <meta name="msapplication-TileColor" content="#da532c">
- <meta name="msapplication-config" content="/static/david/icons/browserconfig.xml">
- <meta name="theme-color" content="#f0f0ea">
- <!-- That good ol' feed, subscribe :p. -->
- <link rel=alternate type="application/atom+xml" title=Feed href="/david/log/">
-
- <meta name="robots" content="noindex, nofollow">
- <meta content="origin-when-cross-origin" name="referrer">
- <!-- Canonical URL for SEO purposes -->
- <link rel="canonical" href="https://clochix.net/marges/170417-silos">
-
- <style>
- /* http://meyerweb.com/eric/tools/css/reset/ */
- html, body, div, span,
- h1, h2, h3, h4, h5, h6, p, blockquote, pre,
- a, abbr, address, big, cite, code,
- del, dfn, em, img, ins,
- small, strike, strong, tt, var,
- dl, dt, dd, ol, ul, li,
- fieldset, form, label, legend,
- table, caption, tbody, tfoot, thead, tr, th, td,
- article, aside, canvas, details, embed,
- figure, figcaption, footer, header, hgroup,
- menu, nav, output, ruby, section, summary,
- time, mark, audio, video {
- margin: 0;
- padding: 0;
- border: 0;
- font-size: 100%;
- font: inherit;
- vertical-align: baseline;
- }
- /* HTML5 display-role reset for older browsers */
- article, aside, details, figcaption, figure,
- footer, header, hgroup, menu, nav, section { display: block; }
- body { line-height: 1; }
- blockquote, q { quotes: none; }
- blockquote:before, blockquote:after,
- q:before, q:after {
- content: '';
- content: none;
- }
- table {
- border-collapse: collapse;
- border-spacing: 0;
- }
-
- /* http://practicaltypography.com/equity.html */
- /* https://calendar.perfplanet.com/2016/no-font-face-bulletproof-syntax/ */
- /* https://www.filamentgroup.com/lab/js-web-fonts.html */
- @font-face {
- font-family: 'EquityTextB';
- src: url('/static/david/css/fonts/Equity-Text-B-Regular-webfont.woff2') format('woff2'),
- url('/static/david/css/fonts/Equity-Text-B-Regular-webfont.woff') format('woff');
- font-weight: 300;
- font-style: normal;
- font-display: swap;
- }
- @font-face {
- font-family: 'EquityTextB';
- src: url('/static/david/css/fonts/Equity-Text-B-Italic-webfont.woff2') format('woff2'),
- url('/static/david/css/fonts/Equity-Text-B-Italic-webfont.woff') format('woff');
- font-weight: 300;
- font-style: italic;
- font-display: swap;
- }
- @font-face {
- font-family: 'EquityTextB';
- src: url('/static/david/css/fonts/Equity-Text-B-Bold-webfont.woff2') format('woff2'),
- url('/static/david/css/fonts/Equity-Text-B-Bold-webfont.woff') format('woff');
- font-weight: 700;
- font-style: normal;
- font-display: swap;
- }
-
- @font-face {
- font-family: 'ConcourseT3';
- src: url('/static/david/css/fonts/concourse_t3_regular-webfont-20190806.woff2') format('woff2'),
- url('/static/david/css/fonts/concourse_t3_regular-webfont-20190806.woff') format('woff');
- font-weight: 300;
- font-style: normal;
- font-display: swap;
- }
-
-
- /* http://practice.typekit.com/lesson/caring-about-opentype-features/ */
- body {
- /* http://www.cssfontstack.com/ Palatino 99% Win 86% Mac */
- font-family: "EquityTextB", Palatino, serif;
- background-color: #f0f0ea;
- color: #07486c;
- font-kerning: normal;
- -moz-osx-font-smoothing: grayscale;
- -webkit-font-smoothing: subpixel-antialiased;
- text-rendering: optimizeLegibility;
- font-variant-ligatures: common-ligatures contextual;
- font-feature-settings: "kern", "liga", "clig", "calt";
- }
- pre, code, kbd, samp, var, tt {
- font-family: 'TriplicateT4c', monospace;
- }
- em {
- font-style: italic;
- color: #323a45;
- }
- strong {
- font-weight: bold;
- color: black;
- }
- nav {
- background-color: #323a45;
- color: #f0f0ea;
- display: flex;
- justify-content: space-around;
- padding: 1rem .5rem;
- }
- nav:last-child {
- border-bottom: 1vh solid #2d7474;
- }
- nav a {
- color: #f0f0ea;
- }
- nav abbr {
- border-bottom: 1px dotted white;
- }
-
- h1 {
- border-top: 1vh solid #2d7474;
- border-bottom: .2vh dotted #2d7474;
- background-color: #e3e1e1;
- color: #323a45;
- text-align: center;
- padding: 5rem 0 4rem 0;
- width: 100%;
- font-family: 'ConcourseT3';
- display: flex;
- flex-direction: column;
- }
- h1.single {
- padding-bottom: 10rem;
- }
- h1 span {
- position: absolute;
- top: 1vh;
- left: 20%;
- line-height: 0;
- }
- h1 span a {
- line-height: 1.7;
- padding: 1rem 1.2rem .6rem 1.2rem;
- border-radius: 0 0 6% 6%;
- background: #2d7474;
- font-size: 1.3rem;
- color: white;
- text-decoration: none;
- }
- h2 {
- margin: 4rem 0 1rem;
- border-top: .2vh solid #2d7474;
- padding-top: 1vh;
- }
- h3 {
- text-align: center;
- margin: 3rem 0 .75em;
- }
- hr {
- height: .4rem;
- width: .4rem;
- border-radius: .4rem;
- background: #07486c;
- margin: 2.5rem auto;
- }
- time {
- display: bloc;
- margin-left: 0 !important;
- }
- ul, ol {
- margin: 2rem;
- }
- ul {
- list-style-type: square;
- }
- a {
- text-decoration-skip-ink: auto;
- text-decoration-thickness: 0.05em;
- text-underline-offset: 0.09em;
- }
- article {
- max-width: 50rem;
- display: flex;
- flex-direction: column;
- margin: 2rem auto;
- }
- article.single {
- border-top: .2vh dotted #2d7474;
- margin: -6rem auto 1rem auto;
- background: #f0f0ea;
- padding: 2rem;
- }
- article p:last-child {
- margin-bottom: 1rem;
- }
- p {
- padding: 0 .5rem;
- margin-left: 3rem;
- }
- p + p,
- figure + p {
- margin-top: 2rem;
- }
-
- blockquote {
- background-color: #e3e1e1;
- border-left: .5vw solid #2d7474;
- display: flex;
- flex-direction: column;
- align-items: center;
- padding: 1rem;
- margin: 1.5rem;
- }
- blockquote cite {
- font-style: italic;
- }
- blockquote p {
- margin-left: 0;
- }
-
- figure {
- border-top: .2vh solid #2d7474;
- background-color: #e3e1e1;
- text-align: center;
- padding: 1.5rem 0;
- margin: 1rem 0 0;
- font-size: 1.5rem;
- width: 100%;
- }
- figure img {
- max-width: 250px;
- max-height: 250px;
- border: .5vw solid #323a45;
- padding: 1px;
- }
- figcaption {
- padding: 1rem;
- line-height: 1.4;
- }
- aside {
- display: flex;
- flex-direction: column;
- background-color: #e3e1e1;
- padding: 1rem 0;
- border-bottom: .2vh solid #07486c;
- }
- aside p {
- max-width: 50rem;
- margin: 0 auto;
- }
-
- /* https://fvsch.com/code/css-locks/ */
- p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
- font-size: 1rem;
- line-height: calc( 1.5em + 0.2 * 1rem );
- }
- h1 {
- font-size: 1.9rem;
- line-height: calc( 1.2em + 0.2 * 1rem );
- }
- h2 {
- font-size: 1.6rem;
- line-height: calc( 1.3em + 0.2 * 1rem );
- }
- h3 {
- font-size: 1.35rem;
- line-height: calc( 1.4em + 0.2 * 1rem );
- }
- @media (min-width: 20em) {
- /* The (100vw - 20rem) / (50 - 20) part
- resolves to 0-1rem, depending on the
- viewport width (between 20em and 50em). */
- p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
- font-size: calc( 1rem + .6 * (100vw - 20rem) / (50 - 20) );
- line-height: calc( 1.5em + 0.2 * (100vw - 50rem) / (20 - 50) );
- margin-left: 0;
- }
- h1 {
- font-size: calc( 1.9rem + 1.5 * (100vw - 20rem) / (50 - 20) );
- line-height: calc( 1.2em + 0.2 * (100vw - 50rem) / (20 - 50) );
- }
- h2 {
- font-size: calc( 1.5rem + 1.5 * (100vw - 20rem) / (50 - 20) );
- line-height: calc( 1.3em + 0.2 * (100vw - 50rem) / (20 - 50) );
- }
- h3 {
- font-size: calc( 1.35rem + 1.5 * (100vw - 20rem) / (50 - 20) );
- line-height: calc( 1.4em + 0.2 * (100vw - 50rem) / (20 - 50) );
- }
- }
- @media (min-width: 50em) {
- /* The right part of the addition *must* be a
- rem value. In this example we *could* change
- the whole declaration to font-size:2.5rem,
- but if our baseline value was not expressed
- in rem we would have to use calc. */
- p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
- font-size: calc( 1rem + .6 * 1rem );
- line-height: 1.5em;
- }
- p, li, pre, details {
- margin-left: 3rem;
- }
- h1 {
- font-size: calc( 1.9rem + 1.5 * 1rem );
- line-height: 1.2em;
- }
- h2 {
- font-size: calc( 1.5rem + 1.5 * 1rem );
- line-height: 1.3em;
- }
- h3 {
- font-size: calc( 1.35rem + 1.5 * 1rem );
- line-height: 1.4em;
- }
- figure img {
- max-width: 500px;
- max-height: 500px;
- }
- }
-
- figure.unsquared {
- margin-bottom: 1.5rem;
- }
- figure.unsquared img {
- height: inherit;
- }
-
-
-
- @media print {
- body { font-size: 100%; }
- a:after { content: " (" attr(href) ")"; }
- a, a:link, a:visited, a:after {
- text-decoration: underline;
- text-shadow: none !important;
- background-image: none !important;
- background: white;
- color: black;
- }
- abbr[title] { border-bottom: 0; }
- abbr[title]:after { content: " (" attr(title) ")"; }
- img { page-break-inside: avoid; }
- @page { margin: 2cm .5cm; }
- h1, h2, h3 { page-break-after: avoid; }
- p3 { orphans: 3; widows: 3; }
- img {
- max-width: 250px !important;
- max-height: 250px !important;
- }
- nav, aside { display: none; }
- }
-
- ul.with_columns {
- column-count: 1;
- }
- @media (min-width: 20em) {
- ul.with_columns {
- column-count: 2;
- }
- }
- @media (min-width: 50em) {
- ul.with_columns {
- column-count: 3;
- }
- }
- ul.with_two_columns {
- column-count: 1;
- }
- @media (min-width: 20em) {
- ul.with_two_columns {
- column-count: 1;
- }
- }
- @media (min-width: 50em) {
- ul.with_two_columns {
- column-count: 2;
- }
- }
-
- .gallery {
- display: flex;
- flex-wrap: wrap;
- justify-content: space-around;
- }
- .gallery figure img {
- margin-left: 1rem;
- margin-right: 1rem;
- }
- .gallery figure figcaption {
- font-family: 'ConcourseT3'
- }
-
- footer {
- font-family: 'ConcourseT3';
- display: flex;
- flex-direction: column;
- border-top: 3px solid white;
- padding: 4rem 0;
- background-color: #07486c;
- color: white;
- }
- footer > * {
- max-width: 50rem;
- margin: 0 auto;
- }
- footer a {
- color: #f1c40f;
- }
- footer .avatar {
- width: 200px;
- height: 200px;
- border-radius: 50%;
- float: left;
- -webkit-shape-outside: circle();
- shape-outside: circle();
- margin-right: 2rem;
- padding: 2px 5px 5px 2px;
- background: white;
- border-left: 1px solid #f1c40f;
- border-top: 1px solid #f1c40f;
- border-right: 5px solid #f1c40f;
- border-bottom: 5px solid #f1c40f;
- }
- </style>
-
- <h1>
- <span><a id="jumper" href="#jumpto" title="Un peu perdu ?">?</a></span>
- Sortir le Web des silos (archive)
- <time>Pour la pérennité des contenus liés. Non-indexé, retrait sur simple email.</time>
- </h1>
- <section>
- <article>
- <h3><a href="https://clochix.net/marges/170417-silos">Source originale du contenu</a></h3>
- <div class="chapo"><p>Avec le récent succès de Mastodon, je trouve utile de ressortir un billet écrit en 2010 décrivant les technologies utilisées par Status.net, son lointain ancêtre. Cet article avait alors été publié sur mon carnet Web, qui n'est plus accessible (il est hébergé par Gandi en http, alors que j'utilise désormais HSTS pour exiger https sur l'ensemble des sous-domaines de <code>clochix.net</code>. Il faudrait que j'exporte une version statique de ce carnet et l'héberge ici même… dès que j'aurais 5 minutes.)</p>
- </div>
-
- <div vocab="http://schema.org/" about="http://www.clochix.net/post/2010/03/29/Sortir-le-flux-des-silos" typeof="Article" class="cite" itemscope="itemscope" itemtype="http://schema.org/Article" >
-
- <p><header>Citation(s) extraite(s) de « <cite><a itemprop="url" href="http://www.clochix.net/post/2010/03/29/Sortir-le-flux-des-silos">sortir le Web des silos</a></cite> » par <span class="author vcard"><span property="dc:contributor" class="fn" itemprop="creator">Clochix</span></span></header>
- <blockquote property="articleBody" cite="http://www.clochix.net/post/2010/03/29/Sortir-le-flux-des-silos">
- <p>Sortir le Web des silos</p></p>
- </blockquote>
-
- <p></div>
- <p>Alors que de nombreux auteurs de carnets s'étaient assuré du contrôle de leurs données en installant les logiciels nécessaires sur leur propre serveur, l'avènement du micro-blogging et la mode des flux de statuts a ramené tout le monde, geeks y compris, vers des silos : Facebook et Twitter, ou identi.ca pour les intégristes. La <a href="http://status.net/2010/03/04/statusnet-0-9-0-released">sortie de StatusNet 0.9 il y a quelques semaines</a> pourrait bien changer la donne, grâce à son introduction de OStatus, un protocole ouvert et décentralisé permettant d'interagir avec les statuts d'utilisateurs postés sur des serveurs dans le monde entier. Désormais, héberger des pensées, liens et autres bribes sur son propre serveur, tout en continuant la conversation avec les utilisateurs hébergés sur d'autres serveurs, devient possible. OStatus permet de sortir des silos en autorisant une architecture décentralisée qui n'a plus grand chose à envier aux architectures centralisées actuelles.</p>
- <p>Cerise sur le gâteau, mais qui pour moi n'a pas de prix: StatusNet 0.9 a levé la limitation à 140c qui, depuis que Twitter a arrêté l'envoi des tweets par SMS dans nos contrées, n'a vraiment plus de raison d'être.</p>
- <p>Pour citer Evan Prodromou, <a href="http://status.net/2010/03/07/understanding-ostatus">OStatus est bâti au dessus d'une pile de composants</a>, formats d'échanges et protocoles de communication :</p>
- <ul>
- <li>Atom pour les flux;</li>
- <li>ActivityStreams pour décrire les activités sociales;</li>
- <li>PubSubHubbub (PuSH pour les intimes) pour les notifications en temps réel;</li>
- <li>Salmon pour la conversation;</li>
- <li>WebFinger pour décrire les services disponibles : les flux et les points d'entrée de PuSH et de Salmon;</li>
- </ul>
- <p>Toutes les communications entre les serveurs utilisent HTTP, dans le cadre d'une "architecture orientée service", c'est à dire que l'on communique simplement avec des services en appelant l'URL de leur point d'entrée.</p>
- <p>Tentative de présentation rapide de ces différents composants.</p>
- <h3><a name="Des_formats" href="#Des_formats" class="anchor"># </a>Des formats</h3><h4><a name="Atom" href="#Atom" class="anchor"># </a>Atom</h4><p>Le format de base pour décrire des publications regroupées en collections, les flux. Je vous renvoie à <a href="http://www.clochix.net/post/2009/09/12/Introduction-%C3%A0-Atom-et-AtomPub">mon article</a> d'il y a quelques mois. Atom est extensible, c'est donc le format de base idéal sur lequel bâtir des flux que l'on enrichira d'autres informations.</p>
- <h4><a name="Activity_Streams" href="#Activity_Streams" class="anchor"># </a>Activity Streams</h4><p><a href="http://activitystrea.ms/">Activity Streams</a> est une proposition de norme visant à définir un format pour décrire des activités. Une activité est une action réalisée par un auteur sur un objet. Activity Streams se présente comme une extension du format Atom, c'est à dire que les informations sur l'activité peuvent enrichir un flux Atom. Le format est développé et a déjà été adopté par quelques jeunes startups comme Facebook, Google, Microsoft, MySpace, on peut donc espérer qu'il aura un certain avenir.</p>
- <p>Deux spécifications sont en cours de rédaction, l'une <a href="http://activitystrea.ms/spec/1.0/atom-activity-01.html">décrivant le format lui-même</a>, l'autre <a href="http://activitystrea.ms/schema/1.0/activity-schema-01.html">proposant des IRI</a> pour des types d'actions (marquer comme favori, apprécier, entrer en contact, rejoindre, publier, partager, étiqueter...) et de cibles (article, commentaire, endroit, etc) classiques.</p>
- <p>Pour l'instant, ce protocole est essentiellement utilisé dans StatusNet pour les communications entre serveurs. Par exemple, si l'utilisateur toto du serveur toto.org décide de suivre titi du serveur titi.net, à la fin du processus, après les différents contrôles, le serveur toto.org enverra au point d'entrée du serveur titi.net une notification contenant un enregistrement d'activité:</p>
- <pre><code><?xml version="1.0" encoding="UTF-8"?>
- <feed xmlns="http://www.w3.org/2005/Atom" xmlns:activity="http://activitystrea.ms/spec/1.0/">
- <author>
- <name>toto</name>
- <uri>http://toto.org/toto</uri>
- </author>
- <entry>
- <id>follow:totoid:titiid:timestamp</id>
- <title>toto is following titi</title>
- <content type="html">toto is following titi</content>
- <activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb>
- <activity:object>
- <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type>
- <id>http://titi.net/titi</id>
- <activity:object>
- </entry>
- </feed>
- </code></pre><h4><a name="Threading,_geo-localisation..." href="#Threading,_geo-localisation..." class="anchor"># </a>Threading, géo-localisation...</h4><p>StatusNet implémente également d'autres extensions du format Atom:</p>
- <ul>
- <li>Atom Threading pour lier des contenus entre eux <a href="http://www.ietf.org/rfc/rfc4685.txt">au sein de fils</a>, en permettant de définir, pour chaque entrée, deux séries de liens : les IRI des entrées auxquelles elle répond, et les IRI de ses réponses;</li>
- <li><a href="http://www.georss.org">GeoRSS</a> permet elle d'ajouter des données géométriques et géographiques à un flux. Elle est utilisée ici pour donner les coordonnées, latitude et longitude, des différents objets (localisation habituelle de l'auteur, localisation spécifique de chaque entrée: <georss:point>45.5088375 -73.587809</georss:point>;</li>
- <li><a href="http://martin.atkins.me.uk/specs/atommedia">Atom Média</a> pour décrire des contenus multimédias;</li>
- </ul>
- <h3><a name="Des_protocoles" href="#Des_protocoles" class="anchor"># </a>Des protocoles</h3><h4><a name="PubSubHubSub" href="#PubSubHubSub" class="anchor"># </a>PubSubHubSub</h4><p>Le <a href="http://pubsubhubbub.googlecode.com/svn/trunk/pubsubhubbub-core-0.3.html">protocole PubSubHubbub</a>, ou PuSH utilise un concentrateur, ou hub pour permettre de notifier en temps réel d'évènements. Il implémente les concepts de PubSub et de WebHooks dont <a href="http://www.clochix.net/post/2009/10/04/Bidouiller-avec-les-Web-Hooks">j'avais déjà parlé</a> et que j'utilisais dans le <a href="http://www.clochix.net/post/2009/08/30/Nouveau-fan-des-Sixties">projet Sixties</a> (bibliothèque PHP pour jouer avec les fonctions PubSub d'un serveur XMPP).</p>
- <p>Le mécanisme est le suivant:</p>
- <ul>
- <li>un service désirant publier des contenus crée des points d'entrée dans un concentrateur. Ce sont des URL permettant de s'abonner aux mises à jour des contenus;</li>
- <li>il rend publique la liste de ces points d'entrée. Par exemple via la balise <link rel="hub" ...> dans un flux Atom;</li>
- <li>les utilisateurs qui souhaitent être notifiés de la publication de nouveaux contenus dans le flux ont deux solutions : soit recharger le flux à intervalles réguliers (polling, comme le gamin sur la banquette arrière répétant inlassablement « à quelle heure on arrive ? »), soit s'abonner au Hub. Pour cela, il leur suffit d'envoyer une requête de souscription à l'adresse de son point d'entrée. Cette requête contient une URL de rappel;</li>
- <li>lorsqu'un évènement survient sur le serveur d'origine, il en informe le Hub. Celui-ci interroge alors éventuellement le serveur pour récupérer plus d'informations sur l'évènement, puis notifie l'ensemble des abonnés en postant le contenu aux URL de rappel associées à chaque abonnement.</li>
- </ul>
- <p>L'ensemble des communications est réalisée en HTTP et utilise le format Atom.</p>
- <p>StatusNet embarque son propre Hub, il n'est donc pas nécessaire de passer par des services tiers. Ainsi, pour être prévenu immédiatement de la publication d'un nouveau statut, il suffit d'envoyer une requête à l'adresse du hub contenu une URL à appeler. Pour être notifié de mes mises à jours sur identi.ca, un simple GET ressemblant à cela suffit : <a href="http://identi.ca/main/push/hub?hub.callback=http://www.toto.net/callback_url/&hub.topic=http://identi.ca/main/push/hub&hub.mode=subscribe">http://identi.ca/main/push/hub?hub.callback=http://www.toto.net/callback_url/&hub.topic=http://identi.ca/main/push/hub&hub.mode=subscribe</a> (pour sécuriser la transaction, le protocole définit un mécanisme de challenge, d'échange de clés, etc, je n'entre pas dans les détails).</p>
- <h4><a name="Salmon" href="#Salmon" class="anchor"># </a>Salmon</h4><p>Salmon vise à notifier un contenu que du contenu en rapport a été publié. Pour utiliser le protocole, un flux doit fournir l'URL d'un point d'entrée à appeler lorsqu'une réponse est publiée. On peut préciser deux URL, l'une pour les réponses (par exemple les commentaires), l'autre pour les références. Un flux pourra contenir ce type de liens:</p>
- <pre><code><feed xmlns='http://www.w3.org/2005/Atom'>
- (...)
- <link rel="http://salmon-protocol.org/ns/salmon-replies" href="http://example.org/all-replies-endpoint"/>
- <Link rel="http://salmon-protocol.org/ns/salmon-mention" href="https://example.com/mention-handler" />
- (...)
- </feed>
- </code></pre><p>Lorsqu'un serveur publie une réponse à un contenu publié sur un autre serveur (commentaire sur un article ou réponse à un statut par exemple), le serveur crée une entrée Atom au format Atom Threading et la publie à l'URL fournie dans le flux d'origine, via une requête HTTP POST. Le serveur d'origine peut alors s'il le désire publier la réponse et notifier tous les abonnés via PuSH. La <a href="http://salmon-protocol.googlecode.com/svn/trunk/draft-panzer-salmon-00.html">spécification de Salmon</a> prévoit un mécanisme de signature pour lutter contre le spam et différentes autres protections. Le protocole permet ainsi à des commentaires de remonter le flux jusqu'à sa source, d'où la référence au saumon, pour être ensuite partagé avec tous les abonnés au contenu initial.</p>
- <p>Salmon me semble particulièrement intéressant car il répond à au moins deux problématiques:</p>
- <ul>
- <li>la fragmentation des contenus produits par un utilisateurs: un utilisateur peut désormais héberger sur son propre serveur ses réponses à des contenus publiés partout sur le Net. Il en garde le contrôle;</li>
- <li>la fragmentation des discussions : de multiples références à un article dans d'autres articles sont remontées à la source et, pour peu qu'icelle joue le jeu, partagées avec tous les utilisateurs qui la suivent;</li>
- </ul>
- <h4><a name="WebFinger" href="#WebFinger" class="anchor"># </a>WebFinger</h4><p>WebFinger part du constat que l'on est plus habitué, pour désigner une personne, à utiliser une adresse mail qu'une url. Ou du moins une adresse du type user@server. Malheureusement, à la différence des URL, les adresses mail ne permettent pas d'en savoir plus sur leur propriétaire, par exemple son identité, les adresses des services qu'il utilise, etc. Choses que permet une URI donnant accès par exemple à une page Web ou un profil FOAF.</p>
- <p>WebFinger est donc un protocole permettant à partir d'une adresse de type user@server d'obtenir des méta-données sur l'utilisateur qu'elle désigne. Ces méta-données sont exprimées au <a href="http://docs.oasis-open.org/ns/xri/xrd-1.0">format XRD</a>. XRD est un vocabulaire créé par l'OASIS pour décrire toutes les méta-données de n'importe quelle ressource. Il est plus générique que FOAF, spécialisé dans la description des personnes et de leurs liens.</p>
- <p>WebFinger s'appuie sur plusieurs autres protocoles en cours de discussion au sein de l'IETF:</p>
- <ul>
- <li><a href="http://tools.ietf.org/html/draft-nottingham-site-meta">Defining Well-Known URIs</a> propose de regrouper données de service d'un domaine dans un répertoire .well-known situé à la racine de ce domaine. Par exemple les fichiers destinés aux robots d'indexation, le plan du site, l'icône, etc;</li>
- <li><a href="http://tools.ietf.org/html/draft-hammer-hostmeta">host-meta: Web Host Metadata</a> propose que les méta-données d'un domaine soient stockées au format XRD dans un fichier host-meta à l'intérieur de ce dossier;</li>
- <li><a href="http://tools.ietf.org/html/draft-hammer-discovery">LRDD: Link-based Resource Descriptor Discovery</a> utilise un lien link pour référencer des méta-données sur un document. Ce lien peut être dans les entêtes HTTP d'une réponse à une requête, ou une balise LINK dans un document XML quelconque. Dans le cas des fichiers XRD de description d'un domaine, le lien pointera vers un template permettant d'obtenir des informations sur une ressource : par exemple <Link rel="lrdd" template="https://meta.example.org/?q={uri}" type="application/xrd+xml" /></li>
- </ul>
- <p>Le mécanisme utilisé par WebFinger pour obtenir un profil à partir d'une adresse est le suivant:</p>
- <ol>
- <li>transformer l'adresse mail en une XRI, un identifiant universel de ressource1. Cela se fait simplement en la préfixant de acct: pour 'account'';</li>
- <li>récupérer le fichier de description du domaine. Soit pour l'adresse acct:clochix@identi.ca le fichier <a href="https://identi.ca/.well-known/host-meta">https://identi.ca/.well-known/host-meta</a>. On notera au passage que l'adresse mail n'a pas à exister. clochix@identi.ca n'est pas une adresse mail, mais l'identifiant de mon compte sur identi.ca;</li>
- <li>rechercher dans ce fichier le lien de type lrrd possédant un template : <Link rel="lrdd" template="https://identi.ca/main/xrd?uri={uri}" />;</li>
- <li>récupérer la description des données de l'utilisateur via ce template. On obtient un fichier XRD décrivant le profil de l'utilisateur.</li>
- </ol>
- <h5><a name="En_pratique" href="#En_pratique" class="anchor"># </a>En pratique</h5><p>Google fournit ce type d'information pour tous les utilisateurs de Gmail :</p>
- <ul>
- <li>GET <a href="https://gmail.com/.well-known/host-meta">https://gmail.com/.well-known/host-meta</a></li>
- <li><p>on obtient le fichier suivant:</p>
- <p><?xml version='1.0' encoding='UTF-8'?></p>
- <XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'
- xmlns:hm='http://host-meta.net/xrd/1.0'>
- <hm:Host xmlns='http://host-meta.net/xrd/1.0'>gmail.com</hm:Host>
- <Link rel='lrdd' template='http://www.google.com/s2/webfinger/?q={uri}'>
- <Title>Resource Descriptor</Title>
- </Link>
- </XRD>
- </li>
- <li><p>on peut alors consulter le profil de l'adresse toto@gmail.com à l'URL <a href="http://www.google.com/s2/webfinger/?q=acct:toto@gmail.com">http://www.google.com/s2/webfinger/?q=acct:toto@gmail.com</a>. Soit, pour quelqu'un ayant un profil public et activé Buzz, quelque chose comme:</p>
- <p><?xml version='1.0'?></p>
- <XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'>
- <Subject>acct:toto@gmail.com</Subject>
- <Alias><a href="http://www.google.com/profiles/toto">http://www.google.com/profiles/toto</a></Alias>
- <Link rel='http://portablecontacts.net/spec/1.0' href='http://www-opensocial.googleusercontent.com/api/people/'/>
- <Link rel='http://webfinger.net/rel/profile-page' href='http://www.google.com/profiles/toto' type='text/html'/>
- <Link rel='http://microformats.org/profile/hcard' href='http://www.google.com/profiles/toto' type='text/html'/>
- <Link rel='http://gmpg.org/xfn/11' href='http://www.google.com/profiles/toto' type='text/html'/>
- <Link rel='http://specs.openid.net/auth/2.0/provider' href='http://www.google.com/profiles/toto'/>
- <Link rel='describedby' href='http://www.google.com/profiles/toto' type='text/html'/>
- <Link rel='describedby' href='http://s2.googleusercontent.com/webfinger/?q=acct%3Atoto%40gmail.com&fmt=foaf' type='application/rdf+xml'/>
- <Link rel='http://schemas.google.com/g/2010#updates-from' href='http://buzz.googleapis.com/feeds/123456789012345678901/public/posted' type='application/atom+xml'/>
- </XRD></p>
- <p></li>
- </ul>
- <p>Ce qui rappelle au passage que Google est fournisseur OpenID. Le fichier contient également les liens vers le profil Google, dont les informations sont disponibles dans plusieurs formats, y compris FOAF et des micro-formats comme hCard et XFN, et le flux des mises à jour de Buzz.</p>
- <p>Le même fichier est disponible sur toute installation de StatusNet 0.9. Par exemple, la description de mon compte sur identi.ca:</p>
- <pre><code>http://identi.ca/main/xrd?uri=acct:clochix@identi.ca
- <XRD>
- <Subject>acct:clochix@identi.ca</Subject>
- <Alias>http://identi.ca/user/82435</Alias>
- <Link rel="http://webfinger.net/rel/profile-page" type="text/html" href="http://identi.ca/user/82435"/>
- <Link rel="http://schemas.google.com/g/2010#updates-from" type="application/atom+xml" href="http://identi.ca/api/statuses/user_timeline/82435.atom"/>
- <Link rel="http://microformats.org/profile/hcard" type="text/html" href="http://identi.ca/clochix/hcard"/>
- <Link rel="http://gmpg.org/xfn/11" type="text/html" href="http://identi.ca/user/82435"/>
- <Link rel="describedby" type="application/rdf+xml" href="http://identi.ca/clochix/foaf"/>
- <Link rel="http://salmon-protocol.org/ns/salmon-replies" href="http://identi.ca/main/salmon/user/82435"/>
- <Link rel="http://salmon-protocol.org/ns/salmon-mention" href="http://identi.ca/main/salmon/user/82435"/>
- <Link rel="http://ostatus.org/schema/1.0/subscribe" template="http://identi.ca/main/ostatussub?profile={uri}"/>
- </XRD>
- </code></pre><p>On trouve ici les liens vers mon profil, encore une fois disponible à plusieurs formats, ma timeline, les points d'entrées pour Salmon et pour s'abonner à mes mises à jour via OStatus.</p>
- <h3><a name="OStatus" href="#OStatus" class="anchor"># </a>OStatus</h3><p>OStatus s'appuie sur les précédents protocoles pour définir un format d'échange entre des serveurs.</p>
- <h4><a name="Les_statuts" href="#Les_statuts" class="anchor"># </a>Les statuts</h4><p>Chaque statut correspond à une activité au format Activity Streams, donc à une entrée Atom. L'action retenue est la publication (post) d'un objet qui peut être une note, c'est à dire un court billet ne contenant qu'un corps (à la différence d'un article qui contient lui également un titre et un résumé), un statut ou un commentaire. Notes et statuts sont similaires, la différence est sémantique, le contenu d'un statut se rapportant à son auteur quant une note peut traiter de n'importe quel sujet.</p>
- <p>Un statut peut être lié à :</p>
- <ul>
- <li>d'autres contenus auxquels il répond, via Atom Threading s'il constitue une réponse : <thr:in-reply-to ref="http://identi.ca/notice/1" href="http://identi.ca/notice/1"></thr:in-reply-to></li>
- <li>des personnes : <link rel="ostatus:attention" href="http://server/user"/> lorsque je m'adresse à quelqu'un;</li>
- <li>d'autres statuts s'il fait partie d'une conversation: <link rel="ostatus:conversation" href="http://server/conversation/1"/></li>
- </ul>
- <h4><a name="Les_flux" href="#Les_flux" class="anchor"># </a>Les flux</h4><p>L'activité d'un utilisateur est regroupée au sein de flux Atom. Chaque flux doit posséder un point d'entrée PuSH fournissant l'URL où s'abonner à ses mises à jour. Il peut également fournir des point d'entrée Salmon où être notifié des réponses et des mentions.</p>
- <p>Par exemple, voici un extrait du flux d'Evan Prodromou, le créateur de StatusNet :</p>
- <pre><code><?xml version="1.0" encoding="UTF-8"?>
- <feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
- <id>http://evan.status.net/api/statuses/user_timeline/1.atom</id>
- <title>evan timeline</title>
- <author>
- <name>evan</name>
- <uri>http://evan.status.net/user/1</uri>
- </author>
- <link href="http://evan.status.net/" rel="alternate" type="text/html"/>
- <link href="http://evan.status.net/main/push/hub" rel="hub"/>
- <link href="http://evan.status.net/main/salmon/user/1" rel="http://salmon-protocol.org/ns/salmon-replies"/>
- <link href="http://evan.status.net/main/salmon/user/1" rel="http://salmon-protocol.org/ns/salmon-mention"/>
- <link href="http://evan.status.net/api/statuses/user_timeline/1.atom" rel="self" type="application/atom+xml"/>
- (...)
- </code></pre><h4><a name="Les_communications" href="#Les_communications" class="anchor"># </a>Les communications</h4><p>Les communications entre les serveurs utilisent WebFinger pour découvrir les adresses des flux des utilisateurs, PuSH et Salmon pour échanger des messages.</p>
- <p>Lorsqu'un utilisateur publie un nouveau statut, son serveur notifie l'ensemble des abonnés de la mise à jour via PuSH.</p>
- <p>Les serveurs recourent à Salmon pour échanger entre eux des évènements concernant leurs utilisateurs:</p>
- <ul>
- <li>lorsqu'un utilisateur publie un contenu à l'attention d'un autre utilisateur (en utilisant par exemple la syntaxe @toto qui se traduira par un link rel="ostatus:attention" dans le flux), son serveur envoie une notification au serveur du destinataire via le point d'entrée Salmon;</li>
- <li>idem pour les réponses;</li>
- <li>lorsqu'un utilisateur s'abonne ou se désabonne aux mises à jour d'un autre utilisateur, rejoint ou quitte un groupe, ajoute le statut d'un autre utilisateur à ses favoris ou le re-publie, son serveur notifie de même le serveur de l'utilisateur ou du groupe concerné.</li>
- </ul>
- <p>Ouf ! Le repas était copieux, il va falloir un peu de temps pour assembler les pièces du puzzle et digérer tout ça. Mais je suis pour la première fois depuis longtemps optimiste en ce qui concerne les silos de données : bien sûr OStatus n'attaquera pas la suprématie de Facebook et Twitter, mais pour qui souhaite reprendre la main sur ses flux, une solution existe à présent qui me semble crédible, ou en passe de le devenir. Ne reste plus qu'à attendre que Facebook et Twitter implémentent OStatus pour permettre au monde libre de dialoguer avec leurs prisonniers. Vont-ils le faire ?</p></p>
- </article>
- </section>
-
-
- <nav id="jumpto">
- <p>
- <a href="/david/blog/">Accueil du blog</a> |
- <a href="https://clochix.net/marges/170417-silos">Source originale</a> |
- <a href="/david/stream/2019/">Accueil du flux</a>
- </p>
- </nav>
-
- <footer>
- <div>
- <img src="/static/david/david-larlet-avatar.jpg" loading="lazy" class="avatar" width="200" height="200">
- <p>
- Bonjour/Hi!
- Je suis <a href="/david/" title="Profil public">David Larlet</a>, je vis actuellement à Montréal et j’alimente cet espace depuis 15 ans. <br>
- Si tu as apprécié cette lecture, n’hésite pas à poursuivre ton exploration. Par exemple via les <a href="/david/blog/" title="Expériences bienveillantes">réflexions bimestrielles</a>, la <a href="/david/stream/2019/" title="Pensées (dés)articulées">veille hebdomadaire</a> ou en t’abonnant au <a href="/david/log/" title="S’abonner aux publications via RSS">flux RSS</a> (<a href="/david/blog/2019/flux-rss/" title="Tiens c’est quoi un flux RSS ?">so 2005</a>).
- </p>
- <p>
- Je m’intéresse à la place que je peux avoir dans ce monde. En tant qu’humain, en tant que membre d’une famille et en tant qu’associé d’une coopérative. De temps en temps, je fais aussi des <a href="https://github.com/davidbgk" title="Principalement sur Github mais aussi ailleurs">trucs techniques</a>. Et encore plus rarement, <a href="/david/talks/" title="En ce moment je laisse plutôt la place aux autres">j’en parle</a>.
- </p>
-
- <p>
- Voici quelques articles choisis :
- <a href="/david/blog/2019/faire-equipe/" title="Accéder à l’article complet">Faire équipe</a>,
- <a href="/david/blog/2018/bivouac-automnal/" title="Accéder à l’article complet">Bivouac automnal</a>,
- <a href="/david/blog/2018/commodite-effondrement/" title="Accéder à l’article complet">Commodité et effondrement</a>,
- <a href="/david/blog/2017/donnees-communs/" title="Accéder à l’article complet">Des données aux communs</a>,
- <a href="/david/blog/2016/accompagner-enfant/" title="Accéder à l’article complet">Accompagner un enfant</a>,
- <a href="/david/blog/2016/senior-developer/" title="Accéder à l’article complet">Senior developer</a>,
- <a href="/david/blog/2016/illusion-sociale/" title="Accéder à l’article complet">L’illusion sociale</a>,
- <a href="/david/blog/2016/instantane-scopyleft/" title="Accéder à l’article complet">Instantané Scopyleft</a>,
- <a href="/david/blog/2016/enseigner-web/" title="Accéder à l’article complet">Enseigner le Web</a>,
- <a href="/david/blog/2016/simplicite-defaut/" title="Accéder à l’article complet">Simplicité par défaut</a>,
- <a href="/david/blog/2016/minimalisme-esthetique/" title="Accéder à l’article complet">Minimalisme et esthétique</a>,
- <a href="/david/blog/2014/un-web-omni-present/" title="Accéder à l’article complet">Un web omni-présent</a>,
- <a href="/david/blog/2014/manifeste-developpeur/" title="Accéder à l’article complet">Manifeste de développeur</a>,
- <a href="/david/blog/2013/confort-convivialite/" title="Accéder à l’article complet">Confort et convivialité</a>,
- <a href="/david/blog/2013/testament-numerique/" title="Accéder à l’article complet">Testament numérique</a>,
- et <a href="/david/blog/" title="Accéder aux archives">bien d’autres…</a>
- </p>
- <p>
- On peut <a href="mailto:david%40larlet.fr" title="Envoyer un courriel">échanger par courriel</a>. Si éventuellement tu souhaites que l’on travaille ensemble, tu devrais commencer par consulter le <a href="http://larlet.com">profil dédié à mon activité professionnelle</a> et/ou contacter directement <a href="http://scopyleft.fr/">scopyleft</a>, la <abbr title="Société coopérative et participative">SCOP</abbr> dont je fais partie depuis six ans. Je recommande au préalable de lire <a href="/david/blog/2018/cout-site/" title="Attention ce qui va suivre peut vous choquer">combien coûte un site</a> et pourquoi je suis plutôt favorable à une <a href="/david/pro/devis/" title="Discutons-en !">non-demande de devis</a>.
- </p>
- <p>
- Je ne traque pas ta navigation mais mon
- <abbr title="Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33.184162340">hébergeur</abbr>
- conserve des logs d’accès.
- </p>
- </div>
- </footer>
- <script type="text/javascript">
- ;(_ => {
- const jumper = document.getElementById('jumper')
- jumper.addEventListener('click', e => {
- e.preventDefault()
- const anchor = e.target.getAttribute('href')
- const targetEl = document.getElementById(anchor.substring(1))
- targetEl.scrollIntoView({behavior: 'smooth'})
- })
- })()
- </script>
|