The git repo behind my blog.

publishing-through-the-known-api.html 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="utf-8" />
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  6. <meta name="HandheldFriendly" content="True" />
  7. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  8. <meta name="robots" content="index, follow" />
  9. <link href='https://phyks.me/theme/stylesheet/fonts.css' rel='stylesheet' type='text/css'>
  10. <link rel="stylesheet" type="text/css" href="https://phyks.me/theme/stylesheet/style.min.css">
  11. <link rel="stylesheet" type="text/css" href="https://phyks.me/theme/pygments/monokai.min.css">
  12. <link rel="stylesheet" type="text/css" href="https://phyks.me/theme/font-awesome/css/font-awesome.min.css">
  13. <link href="https://phyks.me/feeds/all.atom.xml" type="application/atom+xml" rel="alternate" title="Phyks' blog Atom">
  14. <link rel="shortcut icon" href="/images/favicon.ico" type="image/x-icon">
  15. <link rel="icon" href="/images/favicon.ico" type="image/x-icon">
  16. <!-- Chrome, Firefox OS and Opera -->
  17. <meta name="theme-color" content="#333">
  18. <!-- Windows Phone -->
  19. <meta name="msapplication-navbutton-color" content="#333">
  20. <!-- iOS Safari -->
  21. <meta name="apple-mobile-web-app-capable" content="yes">
  22. <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
  23. <!-- Microsoft EDGE -->
  24. <meta name="msapplication-TileColor" content="#333">
  25. <meta name="author" content="Phyks" />
  26. <meta name="description" content="As stated in my last article, I’m considering moving my blog to Known. But I’m not a huge fan of WSIWYG editors. I find it handy sometimes, and can enjoy editing in Markdown on Github, but for a long post, I really prefer writing content on my own …" />
  27. <meta name="keywords" content="">
  28. <meta property="og:site_name" content="Phyks' blog"/>
  29. <meta property="og:title" content="Publishing through the Known API"/>
  30. <meta property="og:description" content="As stated in my last article, I’m considering moving my blog to Known. But I’m not a huge fan of WSIWYG editors. I find it handy sometimes, and can enjoy editing in Markdown on Github, but for a long post, I really prefer writing content on my own …"/>
  31. <meta property="og:locale" content="en_US.UTF-8"/>
  32. <meta property="og:url" content="https://phyks.me/2015/01/publishing-through-the-known-api.html"/>
  33. <meta property="og:type" content="article"/>
  34. <meta property="article:published_time" content="2015-01-07 16:20:00+01:00"/>
  35. <meta property="article:modified_time" content=""/>
  36. <meta property="article:author" content="https://phyks.me/author/phyks.html">
  37. <meta property="article:section" content="Dev"/>
  38. <meta property="og:image" content="/images/profile.png">
  39. <title>Phyks' blog &ndash; Publishing through the Known API</title>
  40. </head>
  41. <body>
  42. <aside>
  43. <div>
  44. <a href="https://phyks.me">
  45. <img src="/images/profile.png" alt="Phyks" title="Phyks">
  46. </a>
  47. <h1><a href="https://phyks.me">Phyks</a></h1>
  48. <p>I write about dev, FOSS, DIY and more, in French and English.</p>
  49. <ul class="social">
  50. <li><a class="sc-rss" href="feeds/all.atom.xml" target="_blank"><i class="fa fa-rss"></i></a></li>
  51. <li><a class="sc-envelope-o" href="mailto:phyks+blog@phyks.me" target="_blank"><i class="fa fa-envelope-o"></i></a></li>
  52. <li><a class="sc-github" href="http://github.com/phyks/" target="_blank"><i class="fa fa-github"></i></a></li>
  53. <li><a class="sc-gitlab" href="https://git.phyks.me/phyks" target="_blank"><i class="fa fa-gitlab"></i></a></li>
  54. </ul>
  55. </div>
  56. </aside>
  57. <main>
  58. <nav>
  59. <a href="https://phyks.me">Home</a>
  60. <a href="https://links.phyks.me">Bookmarks</a>
  61. <a href="/pages/hosted-tools.html">Tools</a>
  62. <a href="/archives.html">Archives</a>
  63. <a href="/pages/memo-autohebergement.html">Autohébergement</a>
  64. <a href="https://phyks.me/feeds/all.atom.xml">Atom</a>
  65. </nav>
  66. <article class="single">
  67. <header>
  68. <h1 id="publishing-through-the-known-api">Publishing through the Known <span class="caps">API</span></h1>
  69. <p>
  70. Posted on January 07, 2015 in <a href="https://phyks.me/category/dev.html">Dev</a>
  71. &#8226; 6 min read
  72. </p>
  73. </header>
  74. <div>
  75. <p>As stated in <a href="https://phyks.me/2015/01/thoughts-on-blogging-engine.html">my last article</a>, I&#8217;m considering moving my blog to Known. But I&#8217;m not a huge fan of <span class="caps">WSIWYG</span> editors. I find it handy sometimes, and can enjoy editing in Markdown on Github, but for a long post, I really prefer writing content on my own text editor and sending it online after. Plus I can maintain drafts this way and benefits from spell checking abilities with my&nbsp;dictionary.</p>
  76. <p>My goal is then to find a way to post to Known from my own <span class="caps">PC</span>, using some kind of local app or&nbsp;script.</p>
  77. <p>That&#8217;s really really easy in fact, as every single <span class="caps">URL</span> in Known is also an <span class="caps">API</span>&nbsp;endpoint.</p>
  78. <p>But, first, let&#8217;s talk about a standard way of doing it, that is not Known specific. You can install the <a href="https://github.com/idno/indiepub">IndiePub</a> plugin in Known to enable a <a href="https://indiewebcamp.com/Micropub">MicroPub</a> endpoint in&nbsp;Known.</p>
  79. <p><em>Note</em>: Take care of cloning the repo correctly in <code>IdnoPlugins</code> as the case matters. Indeed, I cloned it as <code>indiepub</code> (lower case) and it took me some time to figure out why it was not working. After having renamed the folder <code>IndiePub</code> everything works&nbsp;fine.</p>
  80. <p>Micropub is a standard way of publishing content to another website, so that, after having received an authorization from you, an app can publish content to your website. Some kind of standard (part of the <a href="https://indiewebcamp.com/">IndieWebCamp</a> stuff) <span class="caps">API</span>, like the one used by apps on silos to post things on your&nbsp;page.</p>
  81. <p>Then, you can use anything that speaks the Micropub to publish on your website. The most famous one may be <a href="http://quill.p3k.io/">Quill</a>, a webapp by <a href="http://aaronparecki.com/">aaronparecki</a>. Most of the available tools are written in <span class="caps">PHP</span>, but you can also find some libs in <a href="https://indiewebcamp.com/Python">Python</a> to handle this kind of stuff (although there does not seem to be any Micropub publishing libraries at the&nbsp;moment).</p>
  82. <p>But known also offers its own <span class="caps">API</span> which may be way easier to use, at least to start with. It can be used in basically the same way, but you don&#8217;t have to worry as much about authentication and endpoints&nbsp;discovery.</p>
  83. <p>So, every <span class="caps">URL</span> endpoint is also an <span class="caps">API</span> endpoint. For instance, on your Known homepage, if you click on &#8220;status update&#8221; to post a new status update, and have a look at the form that appears, you will notice that it posts data to <code>/status/edit</code> (actually, when you click the &#8220;status update&#8221; button, you will notice there is a link on it to <code>/status/edit</code>, in case you do not have <span class="caps">JS</span> enabled). The form is a <code>POST</code> form and you have a <code>body</code> textarea. Let&#8217;s try to have a look at the page at <code>status/edit</code> (with your browser). As you can see, you have the same form that allows you to publish a new status. But you can also directly send a query to this address, to post a new&nbsp;entry.</p>
  84. <p>For this purpose, you will have to go to your Settings, in the &#8220;Tools and apps&#8221; menu and get your <span class="caps">API</span> key. Then, you must authenticate every query you send to the <span class="caps">API</span>. To this purpose, Known uses a <span class="caps">HMAC</span> signature, to prevent from sending the <span class="caps">API</span> key in plaintext over the network. Your <span class="caps">API</span> key is private and should be kept secret on your side. You will have to create a <span class="caps">HMAC</span> signature, using sha256, of the <span class="caps">URL</span> you query, thanks to your <span class="caps">API</span> key. Snippets to do this in many languages are available <a href="http://www.jokecamp.com/blog/examples-of-creating-base64-hashes-using-hmac-sha256-in-different-languages/">here</a>. In these snippets, <code>message</code> is the <span class="caps">API</span> endpoint you query (for instance <code>/status/edit</code> in our previous example) and key is your <span class="caps">API</span>&nbsp;key.</p>
  85. <p>Then, you have to add specific headers to your query to authenticate. These are <code>X-KNOWN-USERNAME</code> which should be equal to your Known username and <code>X-KNOWN-SIGNATURE</code> which should be set to the previously computed signature. This can be done very easily with <code>curl</code> thanks to the command (updating the values of the headers to the correct&nbsp;one)</p>
  86. <div class="highlight"><pre><span></span><span class="gp">$</span> curl -H <span class="s2">&quot;X-KNOWN-USERNAME: USERNAME&quot;</span> -H <span class="s2">&quot;X-KNOWN-SIGNATURE: SIGNATURE&quot;</span> http://known.example.org/status/edit
  87. </pre></div>
  88. <p>For quick tests of the <span class="caps">API</span>, you can use the <code>API Tester</code> plugin, which will take care of forging the correct query based on your inputs. Then, you do not have to worry about building a <span class="caps">HMAC</span> signature and so on. You can also use it to check that the requests you send have valid signature (by comparing the generated one and yours) and so&nbsp;on.</p>
  89. <p>Then, you have to send a payload beside the headers. This payload will be the actual content that will be posted. You should pass it as a <span class="caps">JSON</span> encoded array (but you can also use other formats, see the <code>API Tester</code> plugin or directly the source code), as it is the easiest way. You should send it with <code>POST</code>.</p>
  90. <p>Let&#8217;s have a look in details at our previous example, status update posting, <em>via</em> <code>/status/edit</code>. As we saw, the basic thing to send is the actual content of the status update, through the <code>body</code> field. Then, to post a &#8220;blah&#8221; status, the <span class="caps">JSON</span> encoded payload would look&nbsp;like</p>
  91. <div class="highlight"><pre><span></span><span class="p">{</span><span class="nt">&quot;body&quot;</span><span class="p">:</span> <span class="s2">&quot;blah&quot;</span><span class="p">}</span>
  92. </pre></div>
  93. <p>And you can post it with the following curl&nbsp;command:</p>
  94. <div class="highlight"><pre><span></span><span class="gp">$</span> curl -H <span class="s2">&quot;X-KNOWN-USERNAME: USERNAME&quot;</span> -H <span class="s2">&quot;X-KNOWN-SIGNATURE: SIGNATURE&quot;</span> -X POST --data <span class="s1">&#39;{&quot;body&quot;: &quot;blah&quot;}&#39;</span> http://known.example.org
  95. </pre></div>
  96. <p>And here we go ! Your first status update posted through the <span class="caps">API</span>&nbsp;!</p>
  97. <p>Depending on the choosen <span class="caps">API</span> endpoint, you might want to pass extra parameters. For example, with &#8220;posts&#8221; (<code>entry/</code> in the URLs), you have both a title (logically called <code>title</code>) and a body (as previously). Then, the payload for a post with title &#8220;blah&#8221; and content &#8220;blahblah&#8221; will look&nbsp;like</p>
  98. <div class="highlight"><pre><span></span><span class="p">{</span><span class="nt">&quot;title&quot;</span><span class="p">:</span> <span class="s2">&quot;blah&quot;</span><span class="p">,</span> <span class="nt">&quot;body&quot;</span><span class="p">:</span> <span class="s2">&quot;blahblah&quot;</span><span class="p">}</span>
  99. </pre></div>
  100. <p>Most of the endpoints also offer the ability to tweak the <code>created</code> param, to post a content in the paste or in the future (defaults to now). This is what I used to upload the articles from my previous blog to Known, for instance. This parameter is passed to the <a href="http://php.net/manual/fr/function.strtotime.php"><code>strtotime</code></a> <span class="caps">PHP</span> function, and should then be in a valid format for this function. Many valid formats are available, including relative ones (see the <a href="http://php.net/manual/fr/function.strtotime.php">doc</a> for more info), but the most straight-forward one, with absolute dating, might be to use <span class="caps">ISO</span> 8601, that is <code>YYYY-MM-DD HH:MM:SS</code>.</p>
  101. <p>The common endpoints that I have used so far are <code>/status/edit</code> and <code>/entry/edit</code> to post, respectively, status updates and long posts. A working script example (in Python) can be found <a href="https://git.phyks.me/Phyks/blog/blob/master/known.py">on my blog repository</a> (taking an entry in the format I used to have for my previous blog, and posting it to&nbsp;Known).</p>
  102. <p>Finally, if you want to use extra endpoints, there is no ready to use doc at the moment (see <a href="issue #225">https://github.com/idno/idno/issues/225</a> on Github), but the source code is very easily readable, once you know where to look for the infos :) So, you should know that almost everything in Known is an <code>Entity</code> (which is a common way to describe the content you post). Then, all the specific types of <code>Entities</code> (status, long posts, photos, like etc.) are handled by plugins, located in the <code>IdnoPlugins</code> folder. For instance, status are handled by <code>IdnoPlugins/Status</code> and long posts are handled by <code>IdnoPlugins/Text</code>.</p>
  103. <p>Every plugin declares its routes in the <code>Main.php</code> file. For instance, the <code>Status</code> plugin declares the routes <code>/status/edit</code> (post a new status), <code>/status/edit/([A-Za-z0-9]+)</code> (edit an existing status, the last parameter being the id of the status) and <code>/status/delete/([A-Za-z0-9])</code> (delte a status, same thing as the previous one). Every plugin also declares a content-type which are infos about the type of content it manages, in <code>ContentType.php</code>. Finally, looking in the <code>Pages/</code> folder, you will find scripts to handle the routes. For instance, for <code>/status/edit</code>, you will find in <code>Pages/Edit.php</code> the associated routes, to get and post&nbsp;content.</p>
  104. </div>
  105. <div class="tag-cloud">
  106. <p>
  107. </p>
  108. </div>
  109. </article>
  110. <footer>
  111. <p>
  112. &copy; 2017 - This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>
  113. </p>
  114. <p>Powered by <a href="http://getpelican.com" target="_blank">Pelican</a> - <a href="https://github.com/alexandrevicenzi/flex" target="_blank">Flex</a> theme by <a href="http://alexandrevicenzi.com" target="_blank">Alexandre Vicenzi</a></p><p>
  115. <a rel="license"
  116. href="http://creativecommons.org/licenses/by-nc-sa/4.0/"
  117. target="_blank">
  118. <img alt="Creative Commons License"
  119. title="Creative Commons License"
  120. style="border-width:0"
  121. src="https://phyks.me/theme/img/cc/by-nc-sa.png"
  122. width="80"
  123. height="15"/>
  124. </a>
  125. </p> </footer>
  126. </main>
  127. <script type="application/ld+json">
  128. {
  129. "@context" : "http://schema.org",
  130. "@type" : "Blog",
  131. "name": " Phyks' blog ",
  132. "url" : "https://phyks.me",
  133. "image": "/images/profile.png",
  134. "description": "I write about dev, FOSS, DIY and more, in French and English."
  135. }
  136. </script>
  137. </body>
  138. </html>