<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mike Ralphson</title>
    <description>The latest articles on DEV Community by Mike Ralphson (@mikeralphson).</description>
    <link>https://dev.to/mikeralphson</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F15488%2Fbd34e5b0-ab6c-451e-82ed-62052f4287f8.png</url>
      <title>DEV Community: Mike Ralphson</title>
      <link>https://dev.to/mikeralphson</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mikeralphson"/>
    <language>en</language>
    <item>
      <title>OpenAPI 3.1 - The Gnarly Bits</title>
      <dc:creator>Mike Ralphson</dc:creator>
      <pubDate>Mon, 03 Apr 2023 13:08:00 +0000</pubDate>
      <link>https://dev.to/mikeralphson/openapi-31-the-gnarly-bits-58d0</link>
      <guid>https://dev.to/mikeralphson/openapi-31-the-gnarly-bits-58d0</guid>
      <description>&lt;p&gt;Though obviously support in &lt;a href="https://tools.openapis.org/"&gt;tooling&lt;/a&gt; has taken a little while to begin to appear, both for commercial and Open-Source offerings, there are already a number of resources available to help you get to grips with the latest version of the OpenAPI specification (OAS), whether you are entirely new to it, or an older hand looking to focus on the new features.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/lornajane"&gt;Lorna Mitchell&lt;/a&gt;, who championed the new &lt;code&gt;webhooks&lt;/code&gt; feature, has a range of information available: a &lt;a href="https://lornajane.net/posts/2020/whats-new-in-openapi-3-1"&gt;blog post&lt;/a&gt;, a &lt;a href="https://www.youtube.com/watch?v=49XpXD-HP0U"&gt;video&lt;/a&gt; and associated &lt;a href="https://noti.st/lornajane/YRdDlZ/whats-new-in-openapi-specification-3-1"&gt;slides&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/philsturgeon"&gt;Phil Sturgeon&lt;/a&gt;, who along with &lt;a href="https://twitter.com/relequestual"&gt;Ben Hutton&lt;/a&gt; and &lt;a href="https://twitter.com/ixat_totep"&gt;Henry Andrews&lt;/a&gt; from the &lt;a href="https://json-schema.org/"&gt;JSON Schema&lt;/a&gt; community, helped drive the push to full JSON Schema &lt;a href="https://tools.ietf.org/html/draft-bhutton-json-schema-00"&gt;Draft 2020-12&lt;/a&gt; compliance, has written a &lt;a href="https://www.openapis.org/blog/2021/02/16/migrating-from-openapi-3-0-to-3-1-0"&gt;blog post&lt;/a&gt; for the official &lt;a href="https://openapis.org/"&gt;OpenAPIs.org&lt;/a&gt; website on how to transition your OAS documents from v3.0.x to v3.1.0.&lt;/p&gt;

&lt;p&gt;My fellow OpenAPI Initiative TSC members &lt;a href="https://twitter.com/webron"&gt;Ron Ratovsky&lt;/a&gt; and &lt;a href="https://twitter.com/darrel_miller"&gt;Darrel Miller&lt;/a&gt; presented a webinar on &lt;a href="https://www.youtube.com/watch?v=Sflpzh_cAcA"&gt;what's new in v3.1&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;My fellow &lt;a href="https://postman.com/"&gt;Postman&lt;/a&gt; colleague &lt;a href="https://twitter.com/apihandyman"&gt;Arnaud Lauret&lt;/a&gt; (the API Handyman) gave a talk at the &lt;a href="https://events.linuxfoundation.org/openapi-asc/"&gt;API Specifications Conference&lt;/a&gt; (ASC) in 2022 entitled &lt;a href="https://www.youtube.com/watch?v=WePbF4_7RkY"&gt;OpenAPI 3.x Does What Swagger 2.0 Don’t&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Last but not least, the OpenAPI Initiative now has an official &lt;a href="https://oai.github.io/Documentation"&gt;getting started guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So, with all that going on, is there anything much else to add?&lt;/p&gt;

&lt;p&gt;Indeed there is, so let's take a top-down stroll through the OpenAPI specification, to focus on the details of what has changed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Top-Level changes
&lt;/h3&gt;

&lt;p&gt;As part of this release, we have decided to not follow SemVer anymore, and as such allow ourselves to introduce minor, but breaking changes. These changes are documented as part of the &lt;a href="https://github.com/OAI/OpenAPI-Specification/releases/tag/3.1.0"&gt;release notes&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Additions
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Introduced a new top-level field - &lt;code&gt;webhooks&lt;/code&gt;. This allows describing out-of-band registered webhooks that are available as part of the API.&lt;/li&gt;
&lt;li&gt;  The Info Object has a new summary field.&lt;/li&gt;
&lt;li&gt;  The License Object now has a new identifier field for &lt;a href="https://spdx.dev/"&gt;SPDX&lt;/a&gt; license codes.&lt;/li&gt;
&lt;li&gt;  The Components Object now has a new entry &lt;code&gt;pathItems&lt;/code&gt;, to allow for reusable Path Item Objects to be defined within a OpenAPI document.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Extended Functionality
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;   Updated primitive types to be based on JSON Schema Specification Draft 2020-12. This now includes type &lt;code&gt;"null"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;   Lifted the restriction of allowing Request Body only in HTTP methods where the HTTP 1.1 specification &lt;a href="https://www.rfc-editor.org/rfc/rfc9110"&gt;RFC9110&lt;/a&gt; has explicitly defined semantics. While now allowed for other methods, this use is still not recommended.&lt;/li&gt;
&lt;li&gt;   Added support for the object type for &lt;code&gt;spaceDelimited&lt;/code&gt; and &lt;code&gt;pipeDelimited&lt;/code&gt; style values.&lt;/li&gt;
&lt;li&gt;   The Encoding Object now supports &lt;code&gt;style&lt;/code&gt;, &lt;code&gt;explode&lt;/code&gt; and &lt;code&gt;allowReserved&lt;/code&gt; for the &lt;code&gt;multipart/form-data&lt;/code&gt; media type as well.&lt;/li&gt;
&lt;li&gt;   To enable better webhooks support, expressions in the Callback Object can now also reference Path Item Objects.&lt;/li&gt;
&lt;li&gt;   When using the Reference Object, &lt;code&gt;summary&lt;/code&gt; and &lt;code&gt;description&lt;/code&gt; fields can now be overridden. This is the default behaviour, tooling may optionally allow merging or appending the text.&lt;/li&gt;
&lt;li&gt;   The Schema Object is now fully compliant with JSON Schema draft 2020-12 (see &lt;a href="https://json-schema.org/draft/2020-12/json-schema-core.html"&gt;JSON Schema Core&lt;/a&gt; and &lt;a href="https://json-schema.org/draft/2020-12/json-schema-validation.html"&gt;JSON Schema Validation&lt;/a&gt;). See also, Breaking Changes.&lt;/li&gt;
&lt;li&gt;   The &lt;code&gt;$ref&lt;/code&gt; keyword within Schema Objects can now contain &lt;a href="https://json-schema.org/draft/2020-12/relative-json-pointer.html"&gt;relative JSON Pointers&lt;/a&gt;. &lt;/li&gt;
&lt;li&gt;   The Discriminator Object can now be extended with Specification Extensions, correcting an oversight in version 3.0.&lt;/li&gt;
&lt;li&gt;   Added support for mutual TLS (&lt;code&gt;mutualTLS&lt;/code&gt;) as a security scheme type.&lt;/li&gt;
&lt;li&gt;   Security requirements (such as for API keys) can now define an array of roles that are required for execution (and not only scopes for OAuth 2.0 security schemes).&lt;/li&gt;
&lt;li&gt;   Added the &lt;code&gt;jsonSchemaDialect&lt;/code&gt; top-level field to allow the definition of a default &lt;code&gt;$schema&lt;/code&gt; value for Schema Objects. This allows any past or future version of JSON Schema to be used in your OAS documents, provided that tools support them.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Changes
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;   An OpenAPI Document now requires at least one of &lt;code&gt;paths&lt;/code&gt;, &lt;code&gt;components&lt;/code&gt; or &lt;code&gt;webhooks&lt;/code&gt; to exist at the top level. While previous versions required &lt;code&gt;paths&lt;/code&gt;, now a valid OpenAPI Document can describe only &lt;code&gt;webhooks&lt;/code&gt;, or even only reusable &lt;code&gt;components&lt;/code&gt;. Thus, an OpenAPI Document no longer necessarily describes an API.&lt;/li&gt;
&lt;li&gt;   Anywhere in the 3.0 Specification that had a type of Schema Object | Reference Object has been replaced to be Schema Object only. With the move to full JSON Schema support, &lt;code&gt;$ref&lt;/code&gt; is inherently part of the Schema Object and has its own defined behavior.&lt;/li&gt;
&lt;li&gt;   Extensions prefixed with &lt;code&gt;x-oas-&lt;/code&gt; and &lt;code&gt;x-oai-&lt;/code&gt; are now reserved for the OpenAPI Initiative.&lt;/li&gt;
&lt;li&gt;   The &lt;code&gt;format&lt;/code&gt; keyword is now not validated by default. It is treated as an annotation. Tooling may allow opt-in validation on a best-case basis.&lt;/li&gt;
&lt;li&gt;   The &lt;code&gt;allowEmpty&lt;/code&gt; property on &lt;code&gt;parameters&lt;/code&gt; is now deprecated as it had confusing and less-than-useful behaviour.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Breaking changes
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;   The specification versioning no longer follows SemVer.&lt;/li&gt;
&lt;li&gt;   The &lt;code&gt;nullable&lt;/code&gt; keyword has been removed from the Schema Object (&lt;code&gt;"null"&lt;/code&gt; can be used as a type value).&lt;/li&gt;
&lt;li&gt;   &lt;code&gt;exclusiveMaximum&lt;/code&gt; and &lt;code&gt;exclusiveMinimum&lt;/code&gt; do not accept boolean values (following JSON Schema). They are independent keywords which take a &lt;code&gt;number&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;   Due to the compliance with JSON Schema, there is no longer interaction between &lt;code&gt;required&lt;/code&gt; and &lt;code&gt;readOnly&lt;/code&gt;/&lt;code&gt;writeOnly&lt;/code&gt; in relation to requests and responses.&lt;/li&gt;
&lt;li&gt;   &lt;code&gt;format&lt;/code&gt; (whether &lt;code&gt;byte&lt;/code&gt;, &lt;code&gt;binary&lt;/code&gt;, or &lt;code&gt;base64&lt;/code&gt;) is no longer used to describe file payloads. As part of JSON Schema compliance, now &lt;code&gt;contentEncoding&lt;/code&gt; and &lt;code&gt;contentMediaType&lt;/code&gt; can be used to control this.&lt;/li&gt;
&lt;li&gt;   The Server Object Variable's &lt;code&gt;enum&lt;/code&gt; array now MUST not be empty (changed from SHOULD).&lt;/li&gt;
&lt;li&gt;   The Server Object Variable's &lt;code&gt;default&lt;/code&gt; property now MUST exist in the &lt;code&gt;enum&lt;/code&gt; values, if such values are defined (changed from SHOULD).&lt;/li&gt;
&lt;li&gt;   &lt;code&gt;responses&lt;/code&gt; are no longer required to be defined under the Operation Object.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Clarifications
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;   Reworded the definition of OpenAPI Document to reflect that a document no longer must describe &lt;code&gt;paths&lt;/code&gt;, but can describe either &lt;code&gt;paths&lt;/code&gt;, &lt;code&gt;webhooks&lt;/code&gt;, &lt;code&gt;components&lt;/code&gt; or any combination of these.&lt;/li&gt;
&lt;li&gt;   Dropped the term "RESTful APIs" in favor of "HTTP APIs"&lt;/li&gt;
&lt;li&gt;   Resolution of relative references has been redefined and clarified. Note there's a difference in resolution between Schema Object References and all others.&lt;/li&gt;
&lt;li&gt;   Modification of examples to improve them and provide context for new fields and objects.&lt;/li&gt;
&lt;li&gt;   It is now clarified what happens when path template expressions do not have a corresponding path parameter.&lt;/li&gt;
&lt;li&gt;   Data types (and just primitive data types) now correspond to JSON Schema.&lt;/li&gt;
&lt;li&gt;   A new section was added to address how to handle the &lt;code&gt;$schema&lt;/code&gt; keyword (implicitly and explicitly).&lt;/li&gt;
&lt;li&gt;   Updated some inline links to more accurate or secure locations.&lt;/li&gt;
&lt;li&gt;   Path parameter values cannot contain the unescaped characters &lt;code&gt;/&lt;/code&gt;, &lt;code&gt;?&lt;/code&gt; or &lt;code&gt;#&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;   Further explanation of where Reference Object and JSON Schema's reference should be used.&lt;/li&gt;
&lt;li&gt;   Unified wording when values are URLs/URIs.&lt;/li&gt;
&lt;li&gt;   Reworded Path Item's &lt;code&gt;$ref&lt;/code&gt; to take into account reference and component changes.&lt;/li&gt;
&lt;li&gt;   Minor text changes to improve consistency and readability.&lt;/li&gt;
&lt;li&gt;   The description of the Reference Object has been updated to further clarify its behavior.&lt;/li&gt;
&lt;li&gt;   Further updated Schema Object's description to take into account the latest draft, and the default use of &lt;code&gt;https://spec.openapis.org/oas/3.1/dialect/base&lt;/code&gt; as the default OAS dialect.&lt;/li&gt;
&lt;li&gt;   Reworded "Schema Vocabularies" to "Schema dialects"&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I hope this guide proves helpful to those considering using OAS 3.1, and those migrating from earlier versions. As ever, let me know in the comments if anything is wrong, unclear or missing.&lt;/p&gt;

&lt;p&gt;Why not get involved in the &lt;a href="https://github.com/OAI/moonwalk/discussions"&gt;discussions&lt;/a&gt; around a tentative OpenAPI 4.0, codename 'Moonwalk'?&lt;/p&gt;

</description>
      <category>openapi</category>
      <category>oas</category>
      <category>api</category>
    </item>
    <item>
      <title>Raspberry Pi radio alarm clock - part 1</title>
      <dc:creator>Mike Ralphson</dc:creator>
      <pubDate>Thu, 20 May 2021 08:19:19 +0000</pubDate>
      <link>https://dev.to/mikeralphson/raspberry-pi-radio-alarm-clock-part-1-43mf</link>
      <guid>https://dev.to/mikeralphson/raspberry-pi-radio-alarm-clock-part-1-43mf</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="100%" height="166" src="https://w.soundcloud.com/player/?url=https://soundcloud.com/nocrowdsurfing/john-peel-festive-fifty-1985-1&amp;amp;auto_play=false&amp;amp;color=%23000000&amp;amp;hide_related=false&amp;amp;show_comments=true&amp;amp;show_user=true&amp;amp;show_reposts=false&amp;amp;show_teaser=true"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjumokqu8a8grbseodgcv.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjumokqu8a8grbseodgcv.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I've had this Sanyo RM5005 radio alarm clock since my 13th birthday back in 1985. It replaced a second-hand Morphy Richards model with a flip display. If you're not familiar with flip displays, they look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frrnrzs3wywlycl80bwtx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frrnrzs3wywlycl80bwtx.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Anyway, it looks like the Sanyo was available in brown (or wood-effect?), black, or like mine, a white, which has now aged to a vaguely yellowish hue. A working model will set you back about £20 from the usual places, unless you happen to chance upon one in a charity shop.&lt;/p&gt;

&lt;p&gt;I don't really want to part with this reminder of my youth (especially as it still works), but maybe doing a hack project on it would justify keeping it around?&lt;/p&gt;

&lt;p&gt;So, the plan is to replace the innards with a Raspberry Pi. I thought the Zero WH would be a suitable board to use. They're small, cheap and more than capable of running an internet radio client and network time protocol client.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjqcx8660jlyugeb4qg5a.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjqcx8660jlyugeb4qg5a.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Initial teardown
&lt;/h2&gt;

&lt;p&gt;Here's where it gets fun. I took many things apart as a child, as my Dad trained as an electrician and I was interested too. Unfortunately, most of things I dissassembled never worked again afterwards. Hopefully this won't be the case here.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhkpm8ksvse0evfj28www.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhkpm8ksvse0evfj28www.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk30t4k9z3ymlzg7ta15i.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk30t4k9z3ymlzg7ta15i.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Like I say, this still works perfectly, but isn't it just a matter of time before one of those capacitors goes bang, and the magic smoke that makes the radio work escapes? We'll be ditching all of the power supply and circuit board, except for the speaker and LED display module, if we can salvage it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk715o3z5qr44eg7js2ln.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk715o3z5qr44eg7js2ln.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5l0g5h1hc90xyzd0j4ol.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5l0g5h1hc90xyzd0j4ol.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  But would the Pi Zero fit?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2fu9th6f3vpojgxvcwj9.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2fu9th6f3vpojgxvcwj9.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looks like that's a yes. The amount of space prompted me to start thinking about adding an SSD for increased storage. Why not add the backup from my old iPod and turn this into a media server too?&lt;/p&gt;

&lt;h2&gt;
  
  
  The tuning dial
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmgn4799kuntmhng7asad.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmgn4799kuntmhng7asad.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A hi-tech solution of a plastic wheel, a small spring and a loop of cotton kept this thing in tune for over 35 years!&lt;/p&gt;

&lt;h2&gt;
  
  
  The 7-segment LED display
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh2ozdv9jbsi5lj4xrjal.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh2ozdv9jbsi5lj4xrjal.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will need to desolder the LED display or source a compatible module. It's a Sanyo SL-1042-27T. It's a very thin module, so I suspect the driver gubbins is on a separate chip. I know very little about driving LED modules, so at this stage I don't know if I can just &lt;a href="https://www.npmjs.com/package/rpio" rel="noopener noreferrer"&gt;bit-bang it from a Node.js script&lt;/a&gt; or what.&lt;/p&gt;

&lt;p&gt;In fact it turns out the whole clock radio experience, including display driving, is provided by this &lt;a href="https://hubtronics.in/electronics/1434" rel="noopener noreferrer"&gt;3M3 LM8560&lt;/a&gt; chip:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fam3l19q0n9krxve25qhp.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fam3l19q0n9krxve25qhp.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It looks like these will today set you back a whopping 60p each! Here's the &lt;a href="http://www.paulanders.com/G5-LED/ver1/datablad.pdf" rel="noopener noreferrer"&gt;datasheet&lt;/a&gt; in case we later need pin-outs etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  The speaker
&lt;/h2&gt;

&lt;p&gt;Another outstanding question is: can we drive the speaker directly from a pair of GPIO pins, or do we need to source an &lt;a href="https://thepihut.com/collections/adafruit-breakout-boards/products/adafruit-mono-2-5w-class-d-audio-amplifier-pam8302" rel="noopener noreferrer"&gt;audio module&lt;/a&gt; (or 'hat') for the Pi?&lt;/p&gt;

&lt;h2&gt;
  
  
  Next time
&lt;/h2&gt;

&lt;p&gt;Booting and configuring the Pi.&lt;/p&gt;

</description>
      <category>iot</category>
      <category>raspberrypi</category>
      <category>hack</category>
      <category>retro</category>
    </item>
    <item>
      <title>GraphQL is King</title>
      <dc:creator>Mike Ralphson</dc:creator>
      <pubDate>Thu, 04 Mar 2021 10:51:51 +0000</pubDate>
      <link>https://dev.to/mikeralphson/graphql-is-king-1bgi</link>
      <guid>https://dev.to/mikeralphson/graphql-is-king-1bgi</guid>
      <description>&lt;h4&gt;
  
  
  To the tune of &lt;a href="https://www.youtube.com/watch?v=21VeAmPOBzI"&gt;"Rock 'n' Roll is King" by The Electric Light Orchestra&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;Listen everybody let me tell you 'bout GraphQL&lt;br&gt;
It's the API architecture that's really gonna thrill your soul&lt;br&gt;
She said come along with me, to a land of graph queries&lt;/p&gt;

&lt;p&gt;She said (wam-a-lam-a bam-a-lam-a) GraphQL is king&lt;/p&gt;

&lt;p&gt;She loves that GraphQL and she daydreams SDL&lt;br&gt;
That's all she ever tells me when I ping her on the Slack channel&lt;br&gt;
Says named mutations are the key, but it isn't like RPC&lt;/p&gt;

&lt;p&gt;She says (wam-a-lam-a bam-a-lam-a) GraphQL is king&lt;/p&gt;

&lt;p&gt;Oh let Apollo run&lt;br&gt;
Run queries, run queries&lt;br&gt;
Oh let's install Relay&lt;br&gt;
That's how it's meant to be...&lt;/p&gt;

&lt;p&gt;It's coupled to the DB and it gets HATEOAS flack&lt;br&gt;
She threw a runtime error and she gave "200" back&lt;br&gt;
She loves that paradigm, she does JSON not resource-based MIME&lt;/p&gt;

&lt;p&gt;She said (wam-a-lam-a bam-a-lam-a) GraphQL is king&lt;/p&gt;

&lt;p&gt;Oh let Apollo run&lt;br&gt;
Run queries, run queries&lt;br&gt;
Oh let's install Prisma&lt;br&gt;
That's how it's meant to be&lt;/p&gt;

&lt;p&gt;When she comes 'round and I'm reading 'bout REST / RESTful,&lt;br&gt;
She says you under/over-fetch and all I resolve to do is GraphQL&lt;br&gt;
I think I'm gonna choose - to use REST and HTTP2&lt;/p&gt;

&lt;p&gt;She says (wam-a-lam-a bam-a-lam-a) GraphQL is king&lt;/p&gt;

&lt;p&gt;(wam-a-lam-a bam-a-lam-a) GraphQL is king&lt;br&gt;
(wam-a-lam-a bam-a-lam-a) GraphQL is king&lt;br&gt;
(wam-a-lam-a bam-a-lam-a) GraphQL is king&lt;/p&gt;

&lt;p&gt;She says... (wam-a-lam-a bam-a-lam-a) GraphQL is king&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;With apologies to Jeff Lynne and the GraphQL community&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>graphql</category>
      <category>rest</category>
      <category>api</category>
    </item>
    <item>
      <title>How to get your web API noticed</title>
      <dc:creator>Mike Ralphson</dc:creator>
      <pubDate>Mon, 06 Jul 2020 11:19:46 +0000</pubDate>
      <link>https://dev.to/mikeralphson/how-to-get-your-web-api-noticed-5al2</link>
      <guid>https://dev.to/mikeralphson/how-to-get-your-web-api-noticed-5al2</guid>
      <description>&lt;p&gt;Web API discovery is a somewhat sprawling and amorphous topic. There is no one right way to achieve it, and no simple silver bullet.&lt;/p&gt;

&lt;p&gt;This post offers a number of strategies, both aimed at your human-readable documentation and your machine-readable API definitions, to make them stand out and attract potential users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Document your API
&lt;/h2&gt;

&lt;p&gt;If nothing else, provide reference documentation and examples so people know how your API works. Aim for a low "time-to-first-200-OK"; can users access the root node of your hypermedia API, or a status page, with a simple &lt;code&gt;curl&lt;/code&gt; request?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/slatedocs/slate"&gt;Slate&lt;/a&gt; provides a quick and easy static site generator from simple markdown to a classic three-panel documentation display.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DQI-3ZO1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/Mermade/shins/master/docs/screenshot.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DQI-3ZO1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/Mermade/shins/master/docs/screenshot.jpg" alt="Slatedocs" width="880" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Provide an API Portal
&lt;/h2&gt;

&lt;p&gt;The next stage of API publicity is the API or developer portal. This is a home base or one-stop-shop for your API users. Some of this may only be necessary if your API is a commercial offering. It should include onboarding documentation, key / authentication management, API reference, terms of service, SLAs, pricing, support / helpdesk information, a downloadable API definition, sunset / deprecation information and anything else required during the lifecycle of using your APIs. Making everything available in one place keeps your API consumers happy and keeps them coming back for updated information.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://redoc.ly/developer-portal"&gt;Redoc.ly&lt;/a&gt; has a developer portal in-a-box offering in beta which is well worth a look.&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow industry standards
&lt;/h2&gt;

&lt;p&gt;Use of industry standards and norms will speed the onboarding process for experienced API consumers. From simply using JSON requests and responses, to following IETF RFCs for problem reporting and healthcheck status, standards for the HTTP &lt;code&gt;PATCH&lt;/code&gt; method and sunset / deprecation information, standing on the shoulders of giants saves you API design time and potential rework in the future.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://standards.rest/"&gt;standards.rest&lt;/a&gt; is a great starting point to ensure that you're not reinventing the wheel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Publish an OpenAPI document
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/OAI/OpenApi-Specification"&gt;OpenAPI Specification&lt;/a&gt; [OAS] is the industry-leading API description standard. By making your API documentation machine-readable, you enable a complete &lt;a href="https://apis.guru/awesome-openapi3/"&gt;eco-system of tooling&lt;/a&gt; which supports your API through interactive documentation and testing / mocking to client and server code generation and more.&lt;/p&gt;

&lt;p&gt;OAS version 3.0 recommends your API definition be called &lt;code&gt;openapi.yaml&lt;/code&gt; or &lt;code&gt;openapi.json&lt;/code&gt; though currently makes no further suggestions on discovery.&lt;/p&gt;

&lt;p&gt;Your API definition should be prominently linked to from your API portal, and included in your repository if your project is Open-Sourced. Don't forget to validate your API definition to make sure it is OAS compliant and lint it to make sure it is complete and consistent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Submit to APIs.guru OpenAPI Directory
&lt;/h2&gt;

&lt;p&gt;If your API meets the inclusion criteria:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Public - anyone can access it as long as they follow some clearly defined steps (subscribe, pay fees, etc.).&lt;/li&gt;
&lt;li&gt;Persistent - API is made with long-lived goal, and not for a particular event (conference, hackathon, etc.).&lt;/li&gt;
&lt;li&gt;Useful - API should provide useful functionality not only for its owner.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;then the &lt;a href="https://github.com/apis-guru/OpenAPI-Directory"&gt;APIs.guru OpenAPI-Directory&lt;/a&gt; is an excellent showcase for your API definition. It is the largest independent directory of machine-readable API definitions. Submit your API &lt;a href="https://apis.guru/add-api/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The directory currently includes over 3,100 API definitions ranging from world-leading cloud vendors to self-hosted informational APIs. Inclusion in the directory automatically makes your API available to several &lt;a href="https://github.com/APIs-guru/openapidirectory#existing-integrations"&gt;integrated platforms and products&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SukEB7h8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://mermade.github.io/images/apis-guru.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SukEB7h8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://mermade.github.io/images/apis-guru.png" alt="APIs.guru OpenAPI-Directory" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Other directories / marketplaces you might consider submitting your API to include &lt;a href="https://rapidapi.com/"&gt;RapidAPI&lt;/a&gt;, the &lt;a href="https://explore.postman.com/"&gt;Postman Collection network&lt;/a&gt; and &lt;a href="https://www.programmableweb.com/"&gt;ProgrammableWeb&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;service-desc&lt;/code&gt; Link relation type
&lt;/h2&gt;

&lt;p&gt;One way to point to your OAS document is to use an HTTP &lt;code&gt;Link&lt;/code&gt; header with a relation-type (&lt;code&gt;rel&lt;/code&gt; value) of &lt;code&gt;service-desc&lt;/code&gt;. More information can be found in &lt;a href="https://tools.ietf.org/html/rfc8631"&gt;RFC-8631&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Schema.org WebAPI type
&lt;/h2&gt;

&lt;p&gt;Another way to make your API and its definition discoverable is to use the &lt;a href="https://schema.org/"&gt;Schema.org&lt;/a&gt; &lt;a href="https://schema.org/WebAPI"&gt;WebAPI type&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Using a format such as JSON Linked-Data (JSON-LD) you can embed machine-readable metadata in your web pages describing your API and linking to your documentation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"application/ld+json"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@context&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://schema.org/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;WebAPI&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Google Knowledge Graph Search API&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The Knowledge Graph Search API lets you find entities in the Google Knowledge Graph. The API uses standard schema.org types and is compliant with the JSON-LD specification.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;documentation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://developers.google.com/knowledge-graph/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;termsOfService&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://developers.google.com/knowledge-graph/terms&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;provider&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Organization&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Google Inc.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  APIs.json
&lt;/h2&gt;

&lt;p&gt;A little obscure and pending some work to update it, &lt;a href="http://apisjson.org/"&gt;apis.json&lt;/a&gt; is "a machine readable approach that API providers can use to describe their API operations, similar to how web sites are described using sitemap.xml".&lt;/p&gt;

&lt;p&gt;This format can come into its own when you have a number of APIs to describe, and need to link to various documentation and support pages for each.&lt;/p&gt;

&lt;h2&gt;
  
  
  Others?
&lt;/h2&gt;

&lt;p&gt;Please let me know if you think I've missed anything important in this round-up, and I'll be sure to update and credit you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Thanks
&lt;/h2&gt;

&lt;p&gt;To &lt;a href="https://twitter.com/_aijaz_"&gt;Aijaz Ansari&lt;/a&gt; for inspiring this post with a question on Twitter.&lt;/p&gt;

</description>
      <category>api</category>
      <category>webapi</category>
      <category>openapi</category>
      <category>discovery</category>
    </item>
    <item>
      <title>Slate and the Future</title>
      <dc:creator>Mike Ralphson</dc:creator>
      <pubDate>Tue, 23 Jun 2020 10:36:10 +0000</pubDate>
      <link>https://dev.to/mikeralphson/slate-and-the-future-1d4a</link>
      <guid>https://dev.to/mikeralphson/slate-and-the-future-1d4a</guid>
      <description>&lt;p&gt;Two announcements today, first thanks to the hard work of my co-maintainers Matthew Peveler and Robert Lord, and many members of the Slate community, we are happy to present &lt;a href="https://github.com/slatedocs/slate/releases/tag/v2.7.0"&gt;Slate v2.7.0&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Secondly, we have something we'd like lots of feedback on.&lt;/p&gt;

&lt;p&gt;The Slate v3 technology preview (in the &lt;code&gt;v3-tp0&lt;/code&gt; branch) is a ground-up reworking of Slate using pure Node.js and the &lt;a href="https://www.11ty.dev/"&gt;eleventy&lt;/a&gt; static-site-generator.&lt;/p&gt;

&lt;p&gt;The Slate v3 technology preview uses the exact same CSS and client-side JavaScript (apart from a couple of compatibility tweaks) as Ruby Slate, so the output HTML should function exactly as in Ruby Slate.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/slatedocs/slate/wiki/Slate-Related-Tools"&gt;Ports of Slate&lt;/a&gt; including to Node.js are nothing new and indeed my own &lt;a href="https://github.com/Mermade/shins"&gt;Shins&lt;/a&gt; project has been tracking releases of Ruby Slate since late 2016, however, this technology preview is not based on Shins or any of the other outdated ports, and leverages &lt;code&gt;eleventy&lt;/code&gt; to minimise the amount of custom code and dependencies required to build your documentation with Slate.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Project&lt;/th&gt;
&lt;th&gt;Top-Level Deps&lt;/th&gt;
&lt;th&gt;Bundled JS Deps&lt;/th&gt;
&lt;th&gt;Docker Image Size&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Slate 2.7&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;482MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Slate 3-tp0&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;176MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shins&lt;/td&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;177MB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The fact that three of our core client-side JS libraries can be included in the Node.js &lt;code&gt;package.json&lt;/code&gt; dependencies makes the process of keeping them up to date much simpler. It also paves the way to potentially move the &lt;code&gt;lunr&lt;/code&gt; search index generation to the server side, which would allow multi-page searches.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Future
&lt;/h2&gt;

&lt;p&gt;It is important to be clear what the function of the technology preview is. It is primarily focused on getting feedback from the community. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We are &lt;strong&gt;not&lt;/strong&gt; saying that Slate 2.7.0 will be the last release of Ruby Slate&lt;/li&gt;
&lt;li&gt;We are &lt;strong&gt;not&lt;/strong&gt; saying that the next major version of Slate &lt;strong&gt;will&lt;/strong&gt; be Node.js-based&lt;/li&gt;
&lt;li&gt;We are &lt;strong&gt;not&lt;/strong&gt; saying that the next major version of Slate &lt;strong&gt;will&lt;/strong&gt; be &lt;code&gt;eleventy&lt;/code&gt;-based&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We are saying that we recognise that the Ruby and &lt;code&gt;middleman&lt;/code&gt; infrastructure used by Slate has historically caused the community, and maintainers, a good deal of headaches over the years.&lt;/p&gt;

&lt;p&gt;We particularly want to hear your experiences of using the technology preview in these areas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compatibility with Ruby Slate&lt;/li&gt;
&lt;li&gt;Any bugs found in building or the resultant HTML&lt;/li&gt;
&lt;li&gt;Operating system compatibility, particularly on Windows&lt;/li&gt;
&lt;li&gt;Should we symlink JS dependencies as now, or simply copy them?&lt;/li&gt;
&lt;li&gt;Should we mirror the Ruby Slate &lt;code&gt;source&lt;/code&gt; directory structure or have a clean break?&lt;/li&gt;
&lt;li&gt;Ease of use&lt;/li&gt;
&lt;li&gt;Speed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition to the concrete areas above, we would welcome feedback on the adoption of &lt;code&gt;eleventy&lt;/code&gt; itself; we note that the project is relatively young (circa two and a half years) and has not yet reached the milestone of a stable &lt;code&gt;v1.0.0&lt;/code&gt; release. Also, &lt;code&gt;eleventy&lt;/code&gt; has a fair number of &lt;a href="https://github.com/11ty/eleventy/issues"&gt;open issues&lt;/a&gt; and this is with it using the &lt;a href="https://twitter.com/samselikoff/status/991395669016436736"&gt;lodash style of issue management&lt;/a&gt; where enhancement requests and documentation change issues are closed, but still monitored. &lt;code&gt;eleventy&lt;/code&gt; while not being one of the most well-known &lt;a href="https://www.staticgen.com/"&gt;static site generators&lt;/a&gt;, is actively maintained and it fits the requirements of supporting markdown and &lt;code&gt;ejs&lt;/code&gt; templates while not including large unnecessary dependencies such as &lt;code&gt;React&lt;/code&gt; or &lt;code&gt;Vue.js&lt;/code&gt;, or being primarily focused on being a blog framework. We believe the Slate community could be beneficial to the &lt;code&gt;eleventy&lt;/code&gt; community in terms of visibility and additional contributors. &lt;code&gt;eleventy&lt;/code&gt; also has a well thought-out &lt;a href="https://www.11ty.dev/docs/plugins/"&gt;plugin system&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We know that the provided documentation is very bare-bones at the moment, but we would plan to copy over the remainder of the &lt;code&gt;README&lt;/code&gt; and start the process of updating the Wiki if the technology preview warrants moving to the next phase.&lt;/p&gt;

&lt;p&gt;One more thing to make clear, we &lt;strong&gt;are&lt;/strong&gt; accepting Pull-Requests against the technology-preview branch, but these should be bug fixes and documentation improvements rather than new features at this stage.&lt;/p&gt;

&lt;p&gt;Many thanks for reading, and we look forward to your feedback.&lt;/p&gt;

</description>
      <category>slate</category>
      <category>slatedocs</category>
      <category>node</category>
      <category>eleventy</category>
    </item>
    <item>
      <title>A brief history of Web APIs</title>
      <dc:creator>Mike Ralphson</dc:creator>
      <pubDate>Sun, 30 Dec 2018 09:14:03 +0000</pubDate>
      <link>https://dev.to/mikeralphson/a-brief-history-of-web-apis-47k4</link>
      <guid>https://dev.to/mikeralphson/a-brief-history-of-web-apis-47k4</guid>
      <description>&lt;p&gt;In the late 1990's and the early 2000's, the predominant use of distributed APIs over the HTTP protocol involved the exchange of Extensible Markup Language (XML) formatted documents in a relatively simple remote procedure call (RPC) fashion. &lt;/p&gt;

&lt;p&gt;One down-side of XML-based RPC APIs, if you live or work in an affected territory, is that their status with regards to applicable patents is unclear (see &lt;a href="https://patents.google.com/patent/US7028312B1/en"&gt;US7028312&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Protocols such as XML-RPC evolved into the Simple Object Access Protocol, or SOAP, giving birth to the approach widely known as Web Services. These were largely machine-to-machine interactions, and though they used the technologies of the world wide web, they were used only infrequently between web-servers and web-clients (browsers).&lt;/p&gt;

&lt;p&gt;SOAP calls over HTTP involve either a &lt;code&gt;GET&lt;/code&gt; or &lt;code&gt;POST&lt;/code&gt; request to an HTTP endpoint, specifying the &lt;code&gt;SOAPAction&lt;/code&gt; either as an HTTP header or a URL query parameter. Although SOAP can also support less common transports such as e-mail. XML namespaces are used to disambiguate the SOAP envelope elements from the message body elements defined by the web service, but this arguably does nothing to make SOAP messages more readable by humans.&lt;/p&gt;

&lt;p&gt;Example of a SOAP request, taken from &lt;a href="https://www.w3.org/2001/03/14-annotated-WSDL-examples:"&gt;https://www.w3.org/2001/03/14-annotated-WSDL-examples:&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;SOAP-ENV:Envelope&lt;/span&gt;
  &lt;span class="na"&gt;xmlns:SOAP-ENV=&lt;/span&gt;&lt;span class="s"&gt;"http://schemas.xmlsoap.org/soap/envelope/"&lt;/span&gt;
  &lt;span class="na"&gt;SOAP-ENV:encodingStyle=&lt;/span&gt;&lt;span class="s"&gt;"http://schemas.xmlsoap.org/soap/encoding/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;SOAP-ENV:Body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;m:GetEndorsingBoarder&lt;/span&gt; &lt;span class="na"&gt;xmlns:m=&lt;/span&gt;&lt;span class="s"&gt;"http://namespaces.snowboard-info.com"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;manufacturer&amp;gt;&lt;/span&gt;K2&lt;span class="nt"&gt;&amp;lt;/manufacturer&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;model&amp;gt;&lt;/span&gt;Fatbob&lt;span class="nt"&gt;&amp;lt;/model&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/m:GetEndorsingBoarder&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/SOAP-ENV:Body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/SOAP-ENV:Envelope&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example of a SOAP response, from the same source:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;SOAP-ENV:Envelope&lt;/span&gt;
  &lt;span class="na"&gt;xmlns:SOAP-ENV=&lt;/span&gt;&lt;span class="s"&gt;"http://schemas.xmlsoap.org/soap/envelope/"&lt;/span&gt;
  &lt;span class="na"&gt;SOAP-ENV:encodingStyle=&lt;/span&gt;&lt;span class="s"&gt;"http://schemas.xmlsoap.org/soap/encoding/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;SOAP-ENV:Body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;m:GetEndorsingBoarderResponse&lt;/span&gt; &lt;span class="na"&gt;xmlns:m=&lt;/span&gt;&lt;span class="s"&gt;"http://namespaces.snowboard-info.com"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;endorsingBoarder&amp;gt;&lt;/span&gt;Chris Englesmann&lt;span class="nt"&gt;&amp;lt;/endorsingBoarder&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/m:GetEndorsingBoarderResponse&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/SOAP-ENV:Body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/SOAP-ENV:Envelope&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because SOAP over HTTP is limited to &lt;code&gt;GET&lt;/code&gt; and &lt;code&gt;POST&lt;/code&gt; HTTP methods, it fails to get the benefit of the wider range of HTTP methods available (such as &lt;code&gt;PUT&lt;/code&gt;, &lt;code&gt;DELETE&lt;/code&gt;, &lt;code&gt;HEAD&lt;/code&gt; and &lt;code&gt;OPTIONS&lt;/code&gt;) and the full range of HTTP status codes associated with them. This can have a negative effect on cacheability and thus performance.&lt;/p&gt;

&lt;h4&gt;
  
  
  AJAX
&lt;/h4&gt;

&lt;p&gt;In February 2005, Jesse James Garrett published an article entitled &lt;a href="https://adaptivepath.org/ideas/ajax-new-approach-web-applications/"&gt;Ajax: A New Approach to Web Applications&lt;/a&gt;, which detailed a relatively lightweight approach developed at Google where a web client could load content from a server asynchronously (i.e. in the background). AJAX, standing for Asynchronous JavaScript And XML, soon became a popular approach for making web sites dynamic, giving birth to the "Web 2.0" concept.&lt;/p&gt;

&lt;p&gt;Although originally concerned with loading HTML and XHTML document fragments, developers soon began to use AJAX to exchange data with web servers, and several factors (such as performance and cross-browser compatibility) led to a gradual shift from XML to JavaScript Object Notation (JSON) as the data format of choice. The acronym however, has stuck.&lt;/p&gt;

&lt;p&gt;Once common, a web site which combined content or data from more than one "Web 2.0" source was known as a "Mash-up". Though this term has largely fallen out of use, remnants of this terminology can still be seen in organisation names such as Mashery (now part of Tibco) and Mashape (now known as Kong).&lt;/p&gt;

&lt;p&gt;The simplicity of AJAX and the growing popularity of JavaScript libraries such as jQuery led to an explosion in the use of web APIs between the server and the browser. With the rise of mobile applications since 2007, the usage of web APIs has only grown further, and this approach, now decoupled from JavaScript, XML and the browser itself has effectively supplanted other web API technologies such as SOAP.&lt;/p&gt;

&lt;h4&gt;
  
  
  REST and RESTful APIs
&lt;/h4&gt;

&lt;p&gt;The term REST - standing for Representational State Transfer - was coined by Roy T. Fielding, in his doctoral dissertation published in 2000; &lt;a href="https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm"&gt;Architectural Styles and the Design of Network-based Software Architectures&lt;/a&gt;. It aimed to describe how networks like the World Wide Web, and software such as web applications should work. It rejects the RPC-style approach to APIs and advocates the use of features we are familiar with from the World Wide Web, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;meaningful resource identifiers, such as URIs&lt;/li&gt;
&lt;li&gt;the passing of resource representations, as opposed to messages or function calls&lt;/li&gt;
&lt;li&gt;use of standard media-types and HTTP status codes&lt;/li&gt;
&lt;li&gt;explicit support for cacheing where appropriate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;to transmit hypermedia documents (data - including text - containing links, just as hypertext refers simply to text containing links).&lt;/p&gt;

&lt;p&gt;REST is described as an architectural style, and this is how its tenets and recommendations should be viewed. There is a lot to learn from REST, and it is very often a good touch-stone to return to when confronted with a complex design decision. REST is not "the new SOAP", they address radically different styles of APIs, and do this in a fundamentally different way. The REST style, when applied to HTTP also leverages this underlying protocol to its fullest, and thus can be very performant when well implemented, though this was not its original focus. Benefits from improvements in HTTP/2 will only further this performance capability. However, REST is not a standard with which you must comply, nor should it be seen as the one true path, to be taken as if gospel. Knowing when to break the 'rules' can be just as important as knowing when to stick to them, and it is important not to see strict REST adherence as a goal in and of itself, particularly if it conflicts with your, or your API consumers, business needs.&lt;/p&gt;

&lt;p&gt;REST does have specific constraints which it applies to the design of the web to define its architectural style, much as architectural styles such as Palladian or neoclassical are used to divide and describe the range of building architecture. An API cannot truly be called a RESTful API if it does not exhibit all of the mandatory REST constraints. This has led to the coining of such terms as REST-like, and even RESTish, to describe APIs which display some of the aspects of the REST style, or have more in common with REST than RPC-like APIs. REST itself pre-dates the rise of web APIs, and there can be some difficulties in mapping the REST style for the web / web applications to APIs as we now know and describe them. For example, the US White House has elements of both Palladian and neoclassical architecture, but this does not make it any less of a grand building, nor any more likely to fall down any time soon.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Like most real-world systems, not all components of the deployed Web architecture obey every constraint present in its architectural design."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Fielding's dissertation, section 6.2.5&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Commonly web-APIs are referred to as RESTful APIs, meaning those that conform to &lt;em&gt;most or all&lt;/em&gt; of the constraints imposed by the REST architectural style. &lt;/p&gt;

&lt;h4&gt;
  
  
  GraphQL
&lt;/h4&gt;

&lt;p&gt;In January 2015 Facebook announced that its internal client APIs were being built on a new technology called GraphQL (though it had been in development in one shape or another since 2011). This is an API framework which owes a little to the RPC model, a little to REST and its use of web protocols, but also strikes out in its own direction.&lt;/p&gt;

&lt;p&gt;GraphQL is based on a type schema, where the types of data and the relationships between them are modelled in an interface description language (IDL, also known as the Schema Description Language, or SDL) and this information is dynamically queryable by the client, using what is known as an introspection query.&lt;/p&gt;

&lt;p&gt;Instead of having fixed functions like RPC, or fixed resource representations accessible via URLs like in REST, GraphQL is a query language similar in concept to Structured Query Language (SQL), which allows the client to request just the data it needs to perform a task, and sometimes to avoid multiple API calls to fetch all of the data required. GraphQL can also batch and combine queries. GraphQL divides queries into those that merely read data, and those that can alter it, known as 'mutations'.&lt;/p&gt;

&lt;p&gt;Here's an example of a GraphQL query, which uses a syntax somewhat similar to JSON:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;allPeople&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;people&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;homeworld&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="pi"&gt;}}}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And an extract of the response, in JSON, from &lt;a href="http://graphql.org/swapi-graphql"&gt;http://graphql.org/swapi-graphql&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allPeople"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"people"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Luke Skywalker"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"homeworld"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Tatooine"&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C-3PO"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"homeworld"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Tatooine"&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"R2-D2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"homeworld"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Naboo"&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are some potential performance downsides with this approach, because of the difficulty of cacheing GraphQL queries at the HTTP level and because clients may issue queries which have never been seen before or been adequately tested.&lt;/p&gt;

&lt;p&gt;There is also an argument that GraphQL's type system encourages a tighter coupling between the underlying data model (such as an SQL database schema) and the data model presented to the client (though this is not always the case).&lt;/p&gt;

&lt;p&gt;There is an interactive console provided with the Facebook GraphQL stack, called GraphiQL (pronounced 'graphical'). Other organisations provide implementations of GraphQL (such as the open source Apollo framework) and GraphQL is in use publicly by organisations such as GitHub, Shopify and Yelp.&lt;/p&gt;

&lt;h4&gt;
  
  
  gRPC
&lt;/h4&gt;

&lt;p&gt;In recent years, the RPC style of API has made something of a resurgence in the form of Google's gRPC (the 'g' stands for gRPC, in the fashion of a recursive acronym, not Google).&lt;/p&gt;

&lt;p&gt;gRPC is focussed on performance, as you can imagine from the amount of data Google's systems exchange, and mandates the use of HTTP/2. Messages are defined by the Protocol Buffers (protobuf) interface description language, which has both a textual / human-readable and binary serialisation. Code to generate and serialise data into protocol buffer format is usually generated from the protobuf IDL using the &lt;code&gt;protoc&lt;/code&gt; compiler, making for a compact and performant representation, though one which cannot as easily be inspected as in the case of a textual transfer protocol such as HTTP/1.x.&lt;/p&gt;

&lt;p&gt;A Google open-source project, &lt;a href="https://github.com/googleapis/gnostic"&gt;gnostic&lt;/a&gt; aims to allow the use of the OpenAPI Specification to define APIs using the protobuf format.&lt;/p&gt;

&lt;p&gt;Thanks to Marco Palladino for catching a thinko in this article.&lt;/p&gt;

</description>
      <category>api</category>
      <category>web</category>
      <category>rest</category>
      <category>graphql</category>
    </item>
    <item>
      <title>A brief history of the OpenAPI Specification</title>
      <dc:creator>Mike Ralphson</dc:creator>
      <pubDate>Mon, 17 Dec 2018 09:45:28 +0000</pubDate>
      <link>https://dev.to/mikeralphson/a-brief-history-of-the-openapi-specification-3g27</link>
      <guid>https://dev.to/mikeralphson/a-brief-history-of-the-openapi-specification-3g27</guid>
      <description>&lt;p&gt;In 2009, Tony Tam of Wordnik (an online dictionary service) had begun working on what would become the Swagger Specification. Used to describe Wordnik's JSON API, Swagger was used to drive Wordnik's developer console / documentation (which can still be seen at &lt;a href="https://developer.wordnik.com/docs" rel="noopener noreferrer"&gt;https://developer.wordnik.com/docs&lt;/a&gt;), their server integration and code-generation within the company.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9kg5dqfr66kk62lb5iln.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9kg5dqfr66kk62lb5iln.png" alt="wordnik"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Initially known as SWAGR - "why WADL, when you can SWAGR?" said Wordnik colleague Zeke Sikelianos when discussing potential names for the project with Tam (though if SWAGR ever stood for anything, it appears to be lost in the mists of time) - Tam published the first version of the Swagger Specification (1.0) in August 2011, just one month after Mashery announced I/O Docs, though there had been at least a 0.1a version used internally.&lt;/p&gt;

&lt;p&gt;While working at Reverb Technologies, Tam published version 1.1 of the Swagger Specification in August 2012. This was a minor refinement of the specification only.&lt;/p&gt;

&lt;p&gt;Version 1.2 of the Swagger Specification was the first version written up as a formal specification document, in March 2014, separating the specification itself from the Swagger implementation. Improvements were made to the type system, to bring it more into line with JSON Schema Draft 4. This was the first version to gain widespread adoption across the API industry, and is still in use by some API providers today.&lt;/p&gt;

&lt;p&gt;September 2014 saw the release of the Swagger Specification 2.0. This saw a reorganisation from the two-file format of Swagger 1.2 and earlier into a single document structure, but one that could still reference sub-documents using the JSON-Reference standard. Further improvements were made to the type system / JSON Schema support, fuller API metadata support with the &lt;code&gt;contact&lt;/code&gt; and &lt;code&gt;license&lt;/code&gt; objects, the use of markdown in descriptions was allowed and vendor extensions (now known as specification extensions) and response headers were supported among other more minor changes. Swagger 2.0 saw more growth and adoption across the industry, and the number of supporting commercial solutions and open-source offerings increased dramatically.&lt;/p&gt;

&lt;p&gt;In March 2015, SmartBear Software, a leading API testing and development tool company, acquired the interests in the Swagger intellectual property and open-source projects from Reverb Technologies.&lt;/p&gt;

&lt;p&gt;In September 2015, Tam joined SmartBear Software as VP of Products, Swagger.&lt;/p&gt;

&lt;p&gt;In December 2015, the Swagger Specification was donated by SmartBear Software to a new open-governance organisation, set up under the auspices of the Linux Foundation: the OpenAPI Initiative (&lt;a href="https://openapis.org" rel="noopener noreferrer"&gt;https://openapis.org&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Version 2.0 of the OpenAPI Specification (as it was now known) was identical to the Swagger 2.0 specification. Although there was, and remains, some confusion between the use of the terms Swagger and OpenAPI, this was a positive first step in the transition to the new governance body and the new name for the specification.&lt;/p&gt;

&lt;p&gt;Ten companies were founding members of the OpenAPI Initiative (3Scale, Apigee, CapitalOne, Google, IBM, Intuit, Microsoft, PayPal, Restlet and SmartBear) and the number of member organisations now stands at over 30.&lt;/p&gt;

&lt;p&gt;The OpenAPI Specification is now managed by a Technical Steering Committee (TSC), and since the departure of Tony Tam in 2017 this has comprised long-time contributor Ron Ratovsky of SmartBear Software, Darrel Miller of Microsoft, Jeremy Whitlock and Marsh Gardiner, both now at Google, Uri Sarid of Mulesoft, and the author of this blog. The TSC draw from the wider Technical Developer Community to develop the specification in an open, transparent fashion. Membership of the OAI does not confer voting rights over content of the specification itself.&lt;/p&gt;

&lt;p&gt;In July 2017, the OpenAPI Initiative announced the release of version 3.0.0 of the OpenAPI Specification, containing several structural improvements, closer alignment with JSON Schema draft 5, new features such as &lt;code&gt;links&lt;/code&gt; and &lt;code&gt;callbacks&lt;/code&gt;, standardisation on CommonMark for descriptions and many small tweaks and clarifications. Two patch releases to the 3.0 line were made in 2018. Version 3.1.0 of the specification is being actively worked on, and a release is expected in mid 2019.&lt;/p&gt;

&lt;p&gt;The OpenAPI Initiative defines the OpenAPI Specification in these terms:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The OpenAPI Specification (OAS) defines a standard, programming language-agnostic interface description for REST APIs, which allows both humans and computers to discover and understand the capabilities of a service without requiring access to source code, additional documentation, or inspection of network traffic. When properly defined via OpenAPI, a consumer can understand and interact with the remote service with a minimal amount of implementation logic. Similar to what interface descriptions have done for lower-level programming, the OpenAPI Specification removes guesswork in calling a service."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Just as REST is not the new SOAP, OpenAPI is not the new WSDL. Its capacity for design-first development, wide range of tooling and cross-platform support take it to places only dreamed of by web services.&lt;/p&gt;

&lt;p&gt;Like any API description language, the OpenAPI Specification is not capable of fully describing every conceivable API design, so retrofitting it to an existing code-base can be an uphill struggle. But as you gain familiarity with the OAS and adopt or transition to a design-first workflow, you will begin to see patterns emerge in the specification which will help shape your design decisions. Not only will you be working with the specification and not against it, you will gain commonality with other APIs described using the OAS, which will translate into familiarity and clear understanding by users of your API who also understand the OAS and perhaps have experience of many other APIs described with it.&lt;/p&gt;

&lt;p&gt;The OpenAPI Specification has a rich ecosystem of tooling, both commercial and open-source (where more than 2,000 projects are known to exist, though not all of them yet have support for OpenAPI 3.0). This ranges from editors and low-level parsers and validators, to documentation-generators and dynamic consoles, testing tools and code-generation services.&lt;/p&gt;

&lt;p&gt;Thanks to Tony Tam for providing a correction to this article.&lt;/p&gt;

</description>
      <category>openapi</category>
      <category>swagger</category>
      <category>oasv3</category>
    </item>
    <item>
      <title>Why there is no such thing as the Richardson Maturity Model</title>
      <dc:creator>Mike Ralphson</dc:creator>
      <pubDate>Thu, 13 Dec 2018 08:01:14 +0000</pubDate>
      <link>https://dev.to/mikeralphson/why-there-is-no-such-thing-as-the-richardson-maturity-model-3b4</link>
      <guid>https://dev.to/mikeralphson/why-there-is-no-such-thing-as-the-richardson-maturity-model-3b4</guid>
      <description>&lt;p&gt;One common yardstick used to measure the RESTishness of an API design is what has become known as the &lt;strong&gt;Richardson Maturity Model&lt;/strong&gt; (or RMM). Originally known simply as the &lt;strong&gt;Maturity Heuristic&lt;/strong&gt;, Leonard Richardson's scale defines the following levels of &lt;strong&gt;maturity&lt;/strong&gt; of an API design:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Level Zero: One URI, one HTTP method&lt;/li&gt;
&lt;li&gt;Level One: Many URIs, one HTTP method&lt;/li&gt;
&lt;li&gt;Level Two: Many URIs, each supporting many HTTP methods&lt;/li&gt;
&lt;li&gt;Level Three: Hypermedia&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can recognise Level Zero as RPC, or SOAP style APIs.&lt;/p&gt;

&lt;p&gt;Level One APIs have the concept of resources (or representations), but all requests use one HTTP method (such as &lt;code&gt;GET&lt;/code&gt; or &lt;code&gt;POST&lt;/code&gt;). This fails to leverage the HTTP protocol to its fullest, and as Richardson notes, makes it very easy to destroy data by accident.&lt;/p&gt;

&lt;p&gt;Level Two is probably the commonest level seen in production APIs today. It represents all of Fielding's mandatory REST constraints apart from HATEOAS.&lt;/p&gt;

&lt;p&gt;Level Three is REST, including the hypermedia constraint. Though Richardson in his original discussion (&lt;a href="https://www.crummy.com/writing/speaking/2008-QCon/act3.html" rel="noopener noreferrer"&gt;https://www.crummy.com/writing/speaking/2008-QCon/act3.html&lt;/a&gt;) states:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"A lot of people settle for level two because hypermedia is difficult to understand and its value in the web service domain isn't as clear."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Unfortunately, the Richardson Maturity Model has been popularised by Martin Fowler in a somewhat bowdlerised form from the original. Unhelpfully, the graphic on his website, often reproduced, chooses to rename the levels above as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Level Zero: The Swamp of POX&lt;/li&gt;
&lt;li&gt;Level One: Resources&lt;/li&gt;
&lt;li&gt;Level Two: HTTP verbs&lt;/li&gt;
&lt;li&gt;Level Three: Hypermedia controls&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ftvqx562vgax2h5kr20qu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ftvqx562vgax2h5kr20qu.png" alt="Fowler's take"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Even if we accept the application of a maturity model to API design as being somewhat biased, implying as it does that REST APIs are more "mature" than RPC APIs (when in fact they simply serve different needs and purposes), there is little excuse for using pejorative terms like "swamp". "POX" also sounds unpleasant, but here simply means 'Plain Old XML'.&lt;/p&gt;

&lt;p&gt;Either way, the popularised version of the RMM makes no distinction between resources and representations and only adds to the confusion between HTTP 'verbs' and HTTP methods, which the original does not.&lt;/p&gt;

&lt;p&gt;Richardson himself at RESTFest 2015, in a talk subtitled "What Have I Done?", described the whole thing as "very embarrassing" and clarified that if you want to proceed up the steps of the Maturity Heuristic, you have to have either a technical reason or a political reason to do so. There is also no prize or "glory" at the top - sorry to disappoint. (&lt;a href="https://vimeo.com/147237932" rel="noopener noreferrer"&gt;https://vimeo.com/147237932&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Do please refer to Richardson's original work for more details on this model.&lt;/p&gt;

&lt;p&gt;Thanks to Darrel Miller for pointing out Richardson's later talk.&lt;/p&gt;

</description>
      <category>richardson</category>
      <category>maturity</category>
      <category>rest</category>
      <category>api</category>
    </item>
    <item>
      <title>The Bluffer's Guide to PC Memory (archive)</title>
      <dc:creator>Mike Ralphson</dc:creator>
      <pubDate>Thu, 08 Nov 2018 10:21:39 +0000</pubDate>
      <link>https://dev.to/mikeralphson/the-bluffers-guide-to-pc-memory-archive-4idp</link>
      <guid>https://dev.to/mikeralphson/the-bluffers-guide-to-pc-memory-archive-4idp</guid>
      <description>&lt;h2&gt;
  
  
  Note
&lt;/h2&gt;

&lt;p&gt;This is an example of why it's so important to put a date on your blog posts! This is one of my earliest posts (can anyone hazard a guess at the date it was written?) and in fact, pre-dates the whole notion of blogs. It was written for a FidoNet echomail area and for download via modem.&lt;/p&gt;

&lt;p&gt;I'd love to hear your thoughts in the comments. Especially if it comes in handy for anyone using DOS emulators etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Starting with the Basics
&lt;/h3&gt;

&lt;p&gt;Conventional memory is the PC's native type of memory, and can be accessed directly by DOS and applications programs. It can be limited physically by the amount of memory installed (usually on the motherboard) to say 256 or 512 Kb, but normally 640 Kb will be installed.  &lt;/p&gt;

&lt;p&gt;Most 8086 based PCs (usually known as XT architecture) will have 640 Kb of conventional memory and nothing else; therefore DOS, device drivers, configuration resources (FILES and BUFFERS), Terminate and Stay Resident (TSR) programs and applications must all co-exist in this 640Kb area of memory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Is There a 640Kb Limit in DOS?
&lt;/h3&gt;

&lt;p&gt;Simple answer: there isn't. The original Intel 8086 processor chip (as used in the first PCs) can access 1 Mb of RAM directly, and so can DOS. It was IBM's decision to reserve the area from 640 Kb to 1 Mb for the system BIOS (Basic Input / Output System), adaptor ROMs (for example for Hard Disks and Network cards), as well as areas of memory used for graphics adaptors such as MDA, Hercules, CGA, EGA and VGA.&lt;/p&gt;

&lt;p&gt;Because there are so many adaptor cards that can be installed in a PC, it is not possible to predict which areas of this 384 Kb reserved area are being used and which are not. Some manufacturers use a BIOS of 128 Kb (IBM and Compaq notably) though most clone machines have a 64 Kb BIOS.&lt;/p&gt;

&lt;p&gt;Thus it is not really possible to produce a machine with a full 1 Mb of conventional memory, though it is possible to use the areas of RAM installed for VGA and Mono graphics modes for additional DOS use, thus extending DOS's 'memory arena' from 640 Kb to 736 Kb. An example of a program to do this is Quarterdeck's VIDRAM which is supplied with their QEMM memory manager.&lt;/p&gt;

&lt;h3&gt;
  
  
  I've Got a Bloody Big Spreadsheet and I Need More Memory!
&lt;/h3&gt;

&lt;p&gt;A typical cry heard in the early 1980's, which was solved by the invention of Expanded Memory (or EMS). EMS memory is located outside the conventional 1 Mb, which is accessed by a 64 Kb window. In XT architecture machines EMS is usually provided on a special memory expansion card and accessed with a device driver.  &lt;/p&gt;

&lt;p&gt;The device driver allocated 64 Kb of conventional memory, which can be used to move chunks of data between EMS and conventional memory. Most EMS managers can handle about 16 Mb of memory on 8086 and 80286 machines. It is not possible to run programs (device drivers, TSRs or applications) in EMS memory, as only small chunks are 'paged' in at any one time.&lt;/p&gt;

&lt;h3&gt;
  
  
  EMS on 80286, 386 and 486 Machines
&lt;/h3&gt;

&lt;p&gt;With the advent of Intel's new processor chips which have inbuilt memory management functions, it became much easier to bypass the DOS 640 Kb barrier.  The 80286 can have up to 16 Mb of extended memory to play with and the 80386 / 486 can access up to 32 Gigabytes (32,000 Mb).&lt;/p&gt;

&lt;p&gt;Hang on? Extended memory, not Expanded? That's right. Intel added a new mode to their processors starting with the 286, called Protected Mode (the 8086 can only operate in what is now called Real Mode). In this mode the processor can access all of the available memory in the same manner, without having to resort to complicated paging schemes like EMS.&lt;/p&gt;

&lt;p&gt;There were three alternatives; scrap EMS and start using Extended Memory, scrap DOS and start using OS/2 (which runs the processor in Protected Mode and can access that whole 16 Mb), or write device drivers that simulated EMS in Extended Memory.&lt;/p&gt;

&lt;p&gt;A few people moved to OS/2 version 1, but the number of applications available was very small. OS/2 version 2 which uses the abilities of the 80386 (a third mode called Virtual Mode) to manage memory and multi-task without fear of one program corrupting another, is a much more viable operating system.&lt;/p&gt;

&lt;p&gt;Most people didn't want to give up their favourite applications, and their favourite applications wanted EMS. The easiest solution was to write those device drivers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why The 80386 So Soon?
&lt;/h3&gt;

&lt;p&gt;The reason the 80286 was never used as much except a faster version of the 8086 is that it has quite a major design flaw in it. You can change the processor from running Real Mode to Protected Mode with a machine code instruction, but you can't change it back!&lt;/p&gt;

&lt;p&gt;Eventually motherboard designers came up with a hardware solution, they wired the SHUTDOWN pin of the 286 back to the RESET pin. Then a program can tell the processor to turn itself off, and this will in fact cause the 286 to reset itself into the mode it uses when it is first turned on, which happens to be Real Mode.&lt;/p&gt;

&lt;p&gt;Unfortunately, it's not quite as easy as that, as the program has to make sure that the processor will remember what it was supposed to be doing when it switches back into Real Mode, and this involves quite a detailed knowledge of 80286 machine code and behaviour.&lt;/p&gt;

&lt;p&gt;Enter the 80386 processor. As well as Real Mode and a Protected Mode which worked properly, it also had one important new ability. The ability to lie.  With the 386 it is possible to instruct the chip to pretend that a range of memory addresses are really another range of addresses. When a program accesses a byte of memory in the 'logical' range, the processor will translate this into a different physical address and use that instead.&lt;/p&gt;

&lt;p&gt;(Some later 286 systems with better chipsets, for example NEAT and C&amp;amp;T, can perform some of the memory-relocation functions of the 386, but only with the supplied driver programs.)&lt;/p&gt;

&lt;p&gt;The 386 can even implement a virtual memory system, where it can declare areas of the 32 Gb address-space to exist not as physical memory, but as say hard disk space, so the most often used areas of memory will be held in RAM and the less often used areas will be held on disk. DOS doesn't use this technique, but OS/2 version 2 does and Windows/NT might when it is released.&lt;/p&gt;

&lt;p&gt;As mentioned above, a new mode was also added called Virtual 8086 Mode, which allows the processor to emulate several separate Real Mode computers, each of which can be running its own programs. This is an extremely safe method of multi-tasking. Windows and OS/2 both use this method to run several programs at once, although OS/2 is more stable than Windows because Windows for some reason runs all Windows programs in the same Virtual Machine (it runs DOS programs in separate VMs though). Thus if one Windows program crashes, the whole system will go down.&lt;/p&gt;

&lt;p&gt;OS/2 runs each DOS, Windows or OS/2 application in its own VM, offering extremely good protection against badly behaved or badly written programs.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's Upper Memory Then?
&lt;/h3&gt;

&lt;p&gt;With the advanced memory management features of the 386 (and a few 286s), it is possible to move a section of memory from one address to another (as far as programs are concerned). Using this technique, the unused areas of memory between 640 Kb and 1 Mb can be 'back-filled' with memory from above 1 Mb.&lt;/p&gt;

&lt;p&gt;This creates Upper Memory Blocks or UMBs.&lt;/p&gt;

&lt;p&gt;This memory looks just like normal conventional memory to DOS, and you can use it for storing programs and data just like memory below 640 Kb. Because some older programs might get upset if the 'top' of DOS memory isn't at 640 Kb, the UMBs are usually treated as a separate pool of memory, accessed with the DEVICEHIGH command in CONFIG.SYS for loading Device Drivers and the LOADHIGH (or LH) command for loading programs.&lt;/p&gt;

&lt;p&gt;There is an undocumented feature of DOS which allows the UMBs to be joined to the rest of DOS memory, allowing COMMAND.COM to be loaded high, and this gives more memory to certain programs.&lt;/p&gt;

&lt;p&gt;To switch DOS into this memory-allocation strategy you need a small program (such as my AUTOHIGH.EXE) which tells EMM386.EXE to enable this feature.&lt;/p&gt;

&lt;h3&gt;
  
  
  And the High Memory Area?
&lt;/h3&gt;

&lt;p&gt;The High Memory Area (or HMA) is a 64 Kb area of Extended Memory which can be used from Real Mode because of a quirk in the way the Intel chips access memory.&lt;/p&gt;

&lt;p&gt;With 16 bit registers the PC would only be able to access 64 Kb. Not a lot. To access the 1 Mb in the original IBM PC, the 8086 would have needed 20 bit registers. To get around this problem Intel decided to use a segmented memory scheme. The 1 Mb is divided up into 64 Kb segments, but these start every 16 bytes, thus they overlap quite a lot.&lt;/p&gt;

&lt;p&gt;The last memory address in the first 1 Mb is FFFFFh, which is expressed in segment:offset form as FFFF:000F (to calculate the actual address, shift the segment left by one hex-digit and then add the offset).&lt;/p&gt;

&lt;p&gt;XT architecture machines have address lines to the processor called A0 to A19.  These are the 20 bits needed to access 1 Mb. Processors such as the 286 and above have further address lines from A20 upwards to allow them to access the rest of their 16 Mb.&lt;/p&gt;

&lt;p&gt;If there was a way to allow use of the A20 line in addition to the A0 - A19 lines in Real Mode, there would be nothing stopping a program accessing the rest of the segment that starts at FFFF:0000 all the way up to FFFF:FFFF.  &lt;/p&gt;

&lt;p&gt;This would give DOS another 64 Kb of memory to use, without having to switch processor modes between Real and Protected to get at it. This is quite an advantage as switching modes is quite a slow process, and the extra 64 Kb could be used for loading DOS itself (IBMBIO.COM &amp;amp; IBMDOS.COM or IO.SYS &amp;amp; MSDOS.SYS depending upon whether your copy of DOS comes from IBM or MicroSoft).&lt;/p&gt;

&lt;p&gt;Because not all motherboards control the address lines in the same way, a routine called an A20 handler must be installed, one that matches the motherboard or chipset in use. DOS's HIMEM.SYS contains several A20 handlers and will load the correct one when it is installed.  &lt;/p&gt;

&lt;h3&gt;
  
  
  What About Extended Memory?
&lt;/h3&gt;

&lt;p&gt;Ok, so we know about Upper Memory Blocks and the High Memory Area, can we use Extended Memory instead of Expanded Memory? I mean, you wouldn't be limited to accessing it 64 Kb at a time, and you wouldn't have to give up 64 Kb of conventional memory for a 'Page Frame' like you do with EMS.&lt;/p&gt;

&lt;p&gt;Well, yes. You could access Extended Memory yourself, like old versions of RAMDRIVE.SYS used to do, but there isn't a standard way of checking to see which bits of Extended Memory are being used by other programs. You would have to try to communicate with each program that you suspect might be using some Extended Memory and ask it, using its API (or Application Programing Interface).&lt;/p&gt;

&lt;p&gt;This is, to say the least, extremely tedious. To standardise use of Extended Memory, and to give it a proper abbreviation, XMS was devised. This is a management specification for Extended Memory, and allows all programs to enquire about and use Extended Memory in a standard manner.&lt;/p&gt;

&lt;p&gt;The normal way to manage Extended Memory is with an XMS memory manager (or XMS provider) like DOS's HIMEM.SYS or Quarterdeck's QEMM.SYS&lt;/p&gt;

&lt;p&gt;MicroSoft in particular has gone XMS mad, if you want EMS on your 386 these days, you have to load HIMEM.SYS first to convert your Extended Memory into managed XMS (HIMEM also loads an A20 handler if possible to convert 64 Kb of your Extended Memory into the High Memory Area), then load EMM386.EXE to emulate EMS in XMS. EMM386.EXE is also DOS's UMB provider, though you can have UMBs without having EMS and vice versa.&lt;/p&gt;

&lt;p&gt;QEMM combines the features of HIMEM.SYS and EMM386.EXE and allows dynamic allocation of memory, thus your free memory is in limbo until a program asks for it using either the XMS or EMS APIs. If you have 2 Mb of managed memory, you can allocate all of it as EMS, all of it as XMS or as a bit of both.  &lt;/p&gt;

&lt;p&gt;As programs free up memory, you can then use it again for either of the memory standards.&lt;/p&gt;

&lt;p&gt;Windows requires XMS, SmartDrive requires XMS, RamDrive requires XMS.  Unfortunately, older applications and games tend to still require EMS and don't know about the newer and rather more sophisticated XMS specification.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Version of DOS and What Sort of Memory Should I Have?
&lt;/h3&gt;

&lt;p&gt;Consult the following table for some guidelines:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Processor&lt;/th&gt;
&lt;th&gt;DOS Version&lt;/th&gt;
&lt;th&gt;Memory Type&lt;/th&gt;
&lt;th&gt;Where&lt;/th&gt;
&lt;th&gt;Software Driver&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;8086 / 8088&lt;/td&gt;
&lt;td&gt;3.30 or 3.31&lt;/td&gt;
&lt;td&gt;Expanded&lt;/td&gt;
&lt;td&gt;Add on card&lt;/td&gt;
&lt;td&gt;H/ware specific&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;80286&lt;/td&gt;
&lt;td&gt;3.30 or 3.31&lt;/td&gt;
&lt;td&gt;Expanded&lt;/td&gt;
&lt;td&gt;Motherboard&lt;/td&gt;
&lt;td&gt;H/ware specific&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;80286&lt;/td&gt;
&lt;td&gt;5.00 +&lt;/td&gt;
&lt;td&gt;Extended&lt;/td&gt;
&lt;td&gt;Motherboard&lt;/td&gt;
&lt;td&gt;DOS / QEMM etc&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;80386&lt;/td&gt;
&lt;td&gt;5.00 +&lt;/td&gt;
&lt;td&gt;Extended&lt;/td&gt;
&lt;td&gt;Motherboard&lt;/td&gt;
&lt;td&gt;DOS / QEMM etc&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;80486&lt;/td&gt;
&lt;td&gt;5.00 +&lt;/td&gt;
&lt;td&gt;Extended&lt;/td&gt;
&lt;td&gt;Motherboard&lt;/td&gt;
&lt;td&gt;DOS / QEMM etc&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The Memory Type column shows the type of Hardware memory installed, 386s can emulate Expanded memory in Extended (XMS) memory.&lt;/p&gt;

&lt;p&gt;DOS version 3.31 is an OEM version supplied by Compaq and Tandon (and possibly a few other manufacturers) that can support hard disks above 32 Mb. If you can't get hold of it, use 3.30 with Ontrack's Disk Manager if the hard disk is bigger than 32 Mb.&lt;/p&gt;

&lt;p&gt;If you can't get hold of DOS 3.3 for an 8086 or 80286, then use DOS 5.00 + rather than DOS 4 which is notoriously flaky.&lt;/p&gt;

&lt;p&gt;DOS 5.00 + refers to MSDOS or PCDOS version 5.00 or higher. It does not mean DRDOS 5 (which is a DOS 3 compatible product) or DRDOS 6 which is not command-compatible with any official version of DOS.&lt;/p&gt;

&lt;h3&gt;
  
  
  While You're At It, How About VCPI and DPMI?
&lt;/h3&gt;

&lt;p&gt;The Virtual Control Program Interface and DOS Protected Mode Interface are commonly known as DOS Extenders. DPMI effectively replaces VCPI. These allow programs to run in Protected Mode without having to change to another operating system, allowing both Code and Data to reside above 1 Mb. XMS and EMS only allow data to be stored above 1 Mb and the PC remains in Real Mode at all other times.&lt;/p&gt;

&lt;p&gt;Programs written to use DOS extenders must load a VCPI or DPMI server program before they can run. Some memory managers such as QEMM support VCPI (but not currently DPMI I think), DOS's memory managers do not, so you may have to install a device driver, or even buy a runtime copy of the DOS extender.&lt;/p&gt;

&lt;p&gt;Advanced DPMI servers like Borland's are royalty-free (so programmers can include them with their applications) and automatically load themselves when the application program starts up.  &lt;/p&gt;

&lt;h3&gt;
  
  
  What Is Memory Parity?
&lt;/h3&gt;

&lt;p&gt;To hold one byte of data in memory, you need 8 bits. However, as processors get faster and motherboards get more complicated it becomes necessary to be able to check that what you put into a memory location is the same as what you read from it. The PC has had this mechanism from day one, because in the early days of PCs motherboards and memory were less reliable than now, even though hardware speeds were much lower.&lt;/p&gt;

&lt;p&gt;If you add a ninth bit to every byte of memory, you can store a 1 or 0 in that extra bit depending on whether the contents of the other 8 bits have an Even or Odd number of 1's. This provides a simple check to see that the contents of memory haven't been changed by stray electro-magnetic influences.&lt;/p&gt;

&lt;p&gt;If you experience Memory Parity Errors, you should check that all memory (whether chips, SIMMs or SIPPs) modules are securely seated and they are all rated at the correct speed (or faster). Typical memory speeds are around 180 to 120 ns (nano-seconds) for XT machines and anywhere between 90 and 60 ns for more modern ATs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Memory Hardware Types
&lt;/h3&gt;

&lt;p&gt;Memory typically comes in three forms, chips (more properly known as DIPs - Dual Inline Packages), SIPPs (Single Inline Pin Package) and SIMMs (Single Inline Memory Module).&lt;/p&gt;

&lt;p&gt;SIMMs are basically a replacement for SIPPs, both are small 2 x 9 cm PCBs with chips surface mounted onto them. There might be 8 or 9 chips (the 9 chip variety are those with parity and the most common), or the new breed of SIMMs with three chips, the two larger ones are 4 bits 'wide' each and the smaller one is for parity.&lt;/p&gt;

&lt;p&gt;SIPPs have a row of pins at the base to plug into the motherboard or expansion card, SIMMs have a small edge connector, like expansion cards themselves.&lt;/p&gt;

&lt;p&gt;SIMMs and SIPPs usually come in 256 Kb, 1Mb and now 4 Mb capacities.&lt;/p&gt;

&lt;p&gt;DIPs can usually be identified by the last 4 digits of the part number on the chip casing. They take the form of XYYY, where X is the width in bits and YYY is the 'length' in kilo-bits. (Not all chip manufacturers use this notation.)&lt;/p&gt;

&lt;p&gt;Thus if the code is 4256, then the chips are 4 bits wide and 256 kilo-bits (262144 bits) long, so you would need 2 to make 256 Kb because each is only half the width of one byte. You can simply say that each chip is 128 Kb in size. To make 1 Mb, you would need 8 chips, or 9 if parity is required.&lt;/p&gt;

&lt;p&gt;Motherboards with more than 1 or 2 Mb fitted will usually have SIMM or SIPP sockets.&lt;/p&gt;

&lt;h3&gt;
  
  
  Static and Dynamic RAM
&lt;/h3&gt;

&lt;p&gt;There are two types of RAM, that which has to be refreshed (read and rewritten) fairly often and that which does not. Dynamic RAM (the type that has to be refreshed) is cheap and therefore used for the majority of your PC's memory.  &lt;/p&gt;

&lt;p&gt;On XT machines you can actually alter the rate at which the timer circuitry refreshed the RAM, the less time spent refreshing the RAM, the more time the CPU / bus can be doing something else (an increase in PC speed of a few percent was possible). All you needed to do was slow down the rate of refresh rate until the machine stopped working, and then use a refresh rate just a tad faster than that! IBM stopped people mucking about like this with the introduction of the AT.&lt;/p&gt;

&lt;p&gt;Static RAM does not need to be refreshed, because it holds its electrical charge better, this makes it much faster than dynamic RAM. It is also much more expensive, and is only used in critical areas of memory (see Processor Cache RAM below).&lt;/p&gt;

&lt;p&gt;CMOS memory (Complimentary Metal-Oxide Semiconductor) can hold its charge for a very long length of time, while provided with a constant (but small) voltage.  CMOS RAM (sometimes called Non-Volatile RAM or NVR) is used to hold the configuration information on AT machines and in some modems. Some CMOS chips require an external battery, while others have a small cell actually inside the chip casing. Both sorts of battery are usually trickle-charged while the machine or modem is powered from the mains.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Processor Cache RAM
&lt;/h3&gt;

&lt;p&gt;Processor Cache RAM can be either internal (on the processor chip itself) or external. All 486s have an internal cache (8 Kb on Intel models, only 1 Kb on Cyrix's plug in 386sx replacement the 486SLC). Most 386s and 486s have external caches. This is to prevent the memory being a bottleneck in the system, as processor speeds start to outstrip the speed at which memory can store and retrieve information.&lt;/p&gt;

&lt;p&gt;Processor RAM caches are always Static RAM rather than Dynamic RAM to give the speed advantage required.&lt;/p&gt;

&lt;p&gt;Typical external cache sizes are 16, 32, 64, 128 or even 256 Kb. A cache of just a few Kb will allow the processor to fetch over 90% of instructions from the cache rather than main memory (called the hit-rate), after that the law of diminishing returns kicks in. The more cache you add over say 64 Kb the benefits you will see start to get smaller and smaller.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hard Disk Caches
&lt;/h3&gt;

&lt;p&gt;There are three types of Hard Disk Caches, internal, external and software.  Most IDE, ESDI and SCSI drives will have a small read-ahead cache internally as part of the drive electronics of a few Kb. When the hard disk is asked for the data on a particular sector of the disk, the cache will buffer the next few sectors as well, as it is quite likely that they will be the next sectors asked for by the program.&lt;/p&gt;

&lt;p&gt;External caches and software caches work in similar ways. External caches are usually situated on the drive controller card and populated with SIMMs, software caches are usually set up in Extended memory. Either kind can be a read-only or a read-write cache.  &lt;/p&gt;

&lt;p&gt;Read-only caches try to keep track of the data that is read from the disk most often as well as using read-ahead techniques similar to those described above.  Areas such as the FAT (File Allocation Table) and directories of the disk are typical areas that are likely to be kept in the cache.&lt;/p&gt;

&lt;p&gt;Hard Disk caches are useful because retrieving data from RAM is orders of magnitude faster than even the fastest hard drive.&lt;/p&gt;

&lt;p&gt;Read-Write caches save up writes to the hard disk and tries to perform them in more efficient bursts, either when the processor doesn't have anything else to do, or to perform them in the most efficient order, meaning the drive heads don't have to travel so far.  &lt;/p&gt;

&lt;p&gt;One problem with read-write caches is that the power to the machine could be interrupted before crucial data is written to the hard disk. Most read-write caches trap the CTRL-ALT-DEL keypress, but none can prevent data loss through a power-cut or the accidental touch of the reset-button.&lt;/p&gt;

</description>
      <category>memory</category>
      <category>pc</category>
      <category>archive</category>
      <category>retro</category>
    </item>
    <item>
      <title>Replacing embedded GoogleMaps with OpenStreetMap</title>
      <dc:creator>Mike Ralphson</dc:creator>
      <pubDate>Tue, 08 May 2018 09:32:19 +0000</pubDate>
      <link>https://dev.to/mikeralphson/replacing-embedded-googlemaps-with-openstreetmap-554i</link>
      <guid>https://dev.to/mikeralphson/replacing-embedded-googlemaps-with-openstreetmap-554i</guid>
      <description>&lt;p&gt;Recently, Google &lt;a href="https://cloud.google.com/maps-platform/user-guide/" rel="noopener noreferrer"&gt;announced&lt;/a&gt; that as of June 11th 2018 a billing account (credit/debit card) and API key would be mandatory requirements for using GoogleMaps, even if your usage currently fell below the free tier of $200 'value' per month.&lt;/p&gt;

&lt;p&gt;If however, you feel this is an unnecessary complication, and wish to avoid nasty surprises, especially if someone else were to use your API key, then it may be time to investigate an alternative, such as &lt;a href="https://www.openstreetmap.org/" rel="noopener noreferrer"&gt;OpenStreetMap&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;My usage was simply to provide a dynamic location map on my website, so the steps for me were particularly simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to &lt;a href="https://openstreetmap.org" rel="noopener noreferrer"&gt;OpenStreetMap.org&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Search for the location you want as the centre of the map, or use the arrow to Show My Location&lt;/li&gt;
&lt;li&gt;Select the desired layers, such as Standard, Cycle Map, Transport etc&lt;/li&gt;
&lt;li&gt;Zoom and pan as necessary, using the + and - icons and your mouse&lt;/li&gt;
&lt;li&gt;Select the Share icon&lt;/li&gt;
&lt;li&gt;Decide if you want to show a marker, and tick the checkbox if so&lt;/li&gt;
&lt;li&gt;Highlight the HTML tab&lt;/li&gt;
&lt;li&gt;Copy and paste the resultant HTML fragment into your website&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;iframe&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"425"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"350"&lt;/span&gt; &lt;span class="na"&gt;frameborder=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt; &lt;span class="na"&gt;scrolling=&lt;/span&gt;&lt;span class="s"&gt;"no"&lt;/span&gt; 
&lt;span class="na"&gt;marginheight=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt; &lt;span class="na"&gt;marginwidth=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt; 
&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://www.openstreetmap.org/export/embed.html?bbox=-2.493209838867188%2C53.50540525319918%2C-2.246360778808594%2C53.61980121473449&amp;amp;amp;layer=mapnik&amp;amp;amp;marker=53.56274386269267%2C-2.3699569702148438"&lt;/span&gt; 
&lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"border: 1px solid black"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;br/&amp;gt;&amp;lt;small&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://www.openstreetmap.org/?mlat=53.5627&amp;amp;amp;mlon=-2.3700#map=12/53.5626/-2.3698"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
View Larger Map&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/small&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the key ingredients are the latitude and longitude co-ordinates of the bounding-box of the map area required. The&lt;code&gt;%2C&lt;/code&gt;s are URL-encoded commas. You can also tweak the &lt;code&gt;iframe&lt;/code&gt; width and height etc to suit your needs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa8eypx82nfy6wqyimcd8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa8eypx82nfy6wqyimcd8.png" alt="Map example" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy mapping.&lt;/p&gt;

</description>
      <category>maps</category>
      <category>google</category>
      <category>googlemaps</category>
      <category>openstreetmap</category>
    </item>
    <item>
      <title>Defining reusable components with the OpenAPI specification</title>
      <dc:creator>Mike Ralphson</dc:creator>
      <pubDate>Mon, 29 Jan 2018 07:39:18 +0000</pubDate>
      <link>https://dev.to/mikeralphson/defining-reusable-components-with-the-openapi-specification-4077</link>
      <guid>https://dev.to/mikeralphson/defining-reusable-components-with-the-openapi-specification-4077</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fomgj3cyi8trhh0w2zuyh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fomgj3cyi8trhh0w2zuyh.png" alt="OAS building blocks" width="549" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A pattern I'm seeing increasingly, is to compose &lt;a href="https://www.openapis.org/" rel="noopener noreferrer"&gt;OpenAPI specification&lt;/a&gt; (OAS, formerly known as Swagger) documents from multiple files. This allows re-use, easier collaboration and makes larger documents much easier to follow.&lt;/p&gt;

&lt;p&gt;The resultant document can be parsed by tools which fully understand and implement the &lt;a href="https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03" rel="noopener noreferrer"&gt;JSON Reference specification&lt;/a&gt; (i.e. they include a resolver), or it can be 'bundled' by de-referencing external references using such a JSON Reference-implementing tool.&lt;/p&gt;

&lt;p&gt;But what should those fragments of OAS documents look like?&lt;/p&gt;

&lt;p&gt;The OAS specification makes no rulings on this, other than the object being referenced must be of the expected type.&lt;/p&gt;

&lt;p&gt;Thus a &lt;code&gt;parameter&lt;/code&gt; definition in a self-contained OAS document may look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;...&lt;/span&gt;
&lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;/&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;$ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#/components/parameters/sort'&lt;/span&gt;
&lt;span class="nn"&gt;...&lt;/span&gt;
&lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;sort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sort&lt;/span&gt;
      &lt;span class="na"&gt;in&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;query&lt;/span&gt;
      &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;The&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;direction&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;of&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;sort'&lt;/span&gt;
        &lt;span class="na"&gt;enum&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;asc&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;desc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A parameter referencing an external fragment may look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;...&lt;/span&gt;
&lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;/&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;$ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;./includes/parameters.yaml#/sort'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and &lt;code&gt;parameters.yaml&lt;/code&gt; could simply look like this, with no additional structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;sort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sort&lt;/span&gt;
  &lt;span class="na"&gt;in&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;query&lt;/span&gt;
  &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;The&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;direction&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;of&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;sort'&lt;/span&gt;
    &lt;span class="na"&gt;enum&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;asc&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;desc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we wished to compose our reusable components across subject-matter areas rather than structurally relating to the OAS, we might structure our documents like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;/&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;$ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;./includes/parameters.yaml#/parameters/sort'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;sort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sort&lt;/span&gt;
    &lt;span class="na"&gt;in&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;query&lt;/span&gt;
    &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;$ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#/definitions/sortType'&lt;/span&gt;
&lt;span class="na"&gt;definitions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;sortType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;The&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;direction&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;of&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;sort'&lt;/span&gt;
    &lt;span class="na"&gt;enum&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;asc&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;desc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem with both styles of included document, is that neither is defined by any standard other than being valid JSON or YAML. Neither can be validated against a specification, even though their contents should be composed of valid OAS objects.&lt;/p&gt;

&lt;p&gt;It raises questions such as: is it allowable to share the definition of the &lt;code&gt;sortType&lt;/code&gt; schema across OAS v2 and OAS v3 documents, even though the definition of the Schema Object differs between the two specifications?&lt;/p&gt;

&lt;p&gt;I would argue there are significant benefits in always structuring your included documents as fully valid OAS documents.&lt;/p&gt;

&lt;p&gt;At the cost of the following six lines of metadata overhead (a little more in JSON), and slightly longer &lt;code&gt;$ref&lt;/code&gt; values, our &lt;code&gt;parameters.yaml&lt;/code&gt; document becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;openapi&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;3.0.1&lt;/span&gt;
&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;An include file to define sortable attributes&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1.0.0&lt;/span&gt;
&lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
&lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;sort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sort&lt;/span&gt;
      &lt;span class="na"&gt;in&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;query&lt;/span&gt;
      &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;$ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#/components/schemas/sortType'&lt;/span&gt;
  &lt;span class="na"&gt;schemas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;sortType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;The&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;direction&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;of&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;sort'&lt;/span&gt;
      &lt;span class="na"&gt;enum&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;asc&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;desc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This document now has the benefits that it can be validated, linted, converted, transformed and edited using OAS compliant &lt;a href="http://openapi.tools" rel="noopener noreferrer"&gt;tools&lt;/a&gt;. In the case of conversion, it means OAS v2 document fragments can be upgraded in place to OAS v3 without having to bundle the document into a monolith.&lt;/p&gt;

&lt;p&gt;The minimal &lt;code&gt;info&lt;/code&gt; object gives us properties to describe the expected usage of the fragment, and an ability to version it separately from the 'master' OAS documents which reference it.&lt;/p&gt;

&lt;p&gt;Simply by the presence of the empty &lt;code&gt;paths&lt;/code&gt; object, we can tell we are dealing with a fragment, not a fully-defined OAS document.&lt;/p&gt;

&lt;p&gt;These reusable sub-documents can also be shared between projects, allowing for industry-specific standard components to emerge.&lt;/p&gt;

</description>
      <category>openapi</category>
      <category>swagger</category>
      <category>oas</category>
    </item>
    <item>
      <title>The Hypermedia Hitchhiker's Guide to Standardised Affordance Metadata</title>
      <dc:creator>Mike Ralphson</dc:creator>
      <pubDate>Mon, 22 Jan 2018 19:00:07 +0000</pubDate>
      <link>https://dev.to/mikeralphson/the-hypermedia-hitchhikers-guide-to-standardised-affordance-metadata-4g61</link>
      <guid>https://dev.to/mikeralphson/the-hypermedia-hitchhikers-guide-to-standardised-affordance-metadata-4g61</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;REST is asking Siri "What can you do?" RPC is lookup up a list of commands from osxdaily or trying to guess.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  &lt;a href="https://twitter.com/philsturgeon/status/955371535073767425" rel="noopener noreferrer"&gt;Phil Sturgeon&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fs-media-cache-ak0.pinimg.com%2Foriginals%2F03%2F9b%2F93%2F039b936b15253a16ed6537c0e3b01d0e.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fs-media-cache-ak0.pinimg.com%2Foriginals%2F03%2F9b%2F93%2F039b936b15253a16ed6537c0e3b01d0e.gif" alt="Babel fish"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's extrapolate from that a little.&lt;/p&gt;

&lt;p&gt;What is Siri's response likely to be, and what would that look like from a REST API?&lt;/p&gt;

&lt;h2&gt;
  
  
  Siri: What can you do?
&lt;/h2&gt;

&lt;p&gt;Let's bang the root of that hoopy API and see if we get back anything useful.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GET /&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Holy swutting Belgium man!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"_links"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"rel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"self"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"rel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"siri:whats-playing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/nowplaying"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"rel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"siri:play-song"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/nowplaying/{songName}"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"rel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"siri:send-message"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/messages/{recipient}/{message}"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"rel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"siri:buy-book-by-title"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/purchases/book/{title}"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"rel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"siri:buy-book-by-title-and-author"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/purchases/book/{title}/by/{author}"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By the way, being a Linux user, I naturally had to get the information for the list above from &lt;a href="http://osxdaily.com/2016/09/28/use-mac-siri-commands/" rel="noopener noreferrer"&gt;OSXDaily&lt;/a&gt;, which we can think of as a static API description document (a la &lt;a href="https://github.com/OAI/OpenAPI-Specification" rel="noopener noreferrer"&gt;the OpenAPI Specification&lt;/a&gt;), after having to google for it, which we can think of as some kind of API discovery mechanism / registry lookup.&lt;/p&gt;

&lt;p&gt;The perennial question now is &lt;em&gt;how&lt;/em&gt; do we perform those link relation actions?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Accessing any hypermedia API in the sophisticated Eastern spiral arm of the galaxy tends to pass through three distinct and recognizable phases, those of Location, Enquiry and Confusion, otherwise known as the Where, What, and How phases. For instance, the first phase is characterized by the question 'Where is this API?' the second by the question 'What can I do with this API?' and the third by the question 'Oh I give up, how am I supposed to know what to do next?” &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  With apologies to Douglas Adams
&lt;/h4&gt;

&lt;p&gt;It may be obvious that a &lt;code&gt;GET&lt;/code&gt; request to &lt;code&gt;/nowplaying&lt;/code&gt; will return information on the currently-playing piece of Bach, but to rock out to some Procol Harum, do I &lt;code&gt;POST&lt;/code&gt; to &lt;code&gt;/nowplaying/whiter%20%shade%20of%20pale&lt;/code&gt;, or possibly &lt;code&gt;PUT&lt;/code&gt; or even &lt;code&gt;PATCH&lt;/code&gt; the resource representation?&lt;/p&gt;

&lt;p&gt;If I want to buy a book by a particular author (I want the original "&lt;a href="https://www.amazon.co.uk/Last-Chance-Douglas-Adams-1991-12-31/dp/B019TM0JNC/ref=sr_1_4?s=books&amp;amp;ie=UTF8&amp;amp;qid=1516646527&amp;amp;sr=1-4&amp;amp;keywords=last+chance+to+see" rel="noopener noreferrer"&gt;Last Chance to See&lt;/a&gt;" by Douglas Adams and Mark Cawardine, not the &lt;a href="https://www.amazon.co.uk/Last-Chance-to-See/dp/B0041T4NF4/ref=sr_1_7?s=books&amp;amp;ie=UTF8&amp;amp;qid=1516646527&amp;amp;sr=1-7&amp;amp;keywords=last+chance+to+see" rel="noopener noreferrer"&gt;sequel&lt;/a&gt; by Mark C. and Stephen Fry), can I pass both authors? Do I concatenate them? Do I use an array?&lt;/p&gt;

&lt;p&gt;What if I could consult the Hitchhiker's Guide to the API?&lt;/p&gt;

&lt;p&gt;Obviously, out-of-band documentation is a REST no-no, but what about in-band documentation?&lt;/p&gt;

&lt;p&gt;What if there was a standardised way of retrieving metadata about a resource... such as:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;OPTIONS /nowplaying/:songName&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Which returned a minimal, dynamically-generated OpenAPI definition for the given endpoint (including any necessary supporting definitions, such as parameters, headers, responses etc).&lt;/p&gt;

&lt;p&gt;The OpenAPI format is used to describe the affordances of the endpoint, and the &lt;code&gt;Allow&lt;/code&gt; response header gives us the supported HTTP methods for the endpoint to act as indices into the OpenAPI &lt;a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#path-item-object" rel="noopener noreferrer"&gt;pathItem object&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The affordances metadata can be effectively cached by using the &lt;code&gt;ETag&lt;/code&gt; and &lt;code&gt;If-None-Match&lt;/code&gt; headers.&lt;/p&gt;

&lt;p&gt;If the metadata hasn't changed since the last time the client checked, the API should respond to the &lt;code&gt;OPTIONS&lt;/code&gt; request with HTTP &lt;a href="https://httpstatuses.com/412" rel="noopener noreferrer"&gt;412&lt;/a&gt; - "Precondition Failed" as per &lt;a href="https://tools.ietf.org/html/rfc7232#section-3.2" rel="noopener noreferrer"&gt;RFC7232&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Obviously, other API description formats could be returned based on content-type negotiation.&lt;/p&gt;

&lt;p&gt;An alternative to using the &lt;code&gt;OPTIONS&lt;/code&gt; method is to include a link with the relation type of &lt;a href="https://tools.ietf.org/html/rfc8631#section-4.2" rel="noopener noreferrer"&gt;service-desc&lt;/a&gt;, and link your partial OAS definition that way.&lt;/p&gt;

&lt;p&gt;If you want to play with returning partial OpenAPI definitions, I've knocked together a proof-of-concept utility in Node.js - &lt;a href="https://github.com/Mermade/openapi-extract" rel="noopener noreferrer"&gt;openapi-extract&lt;/a&gt;. It works with OpenAPI (fka Swagger) 2.0 and 3.0.x.&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Aka there's nothing new under the sun
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://zacstewart.com/2012/04/14/http-options-method.html" rel="noopener noreferrer"&gt;http://zacstewart.com/2012/04/14/http-options-method.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.iana.org/assignments/link-relations/link-relations.xhtml" rel="noopener noreferrer"&gt;https://www.iana.org/assignments/link-relations/link-relations.xhtml&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://json-schema.org/latest/json-schema-hypermedia.html" rel="noopener noreferrer"&gt;http://json-schema.org/latest/json-schema-hypermedia.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>openapi</category>
      <category>hypermedia</category>
      <category>http</category>
      <category>rest</category>
    </item>
  </channel>
</rss>
