PUT-API

  • Revision slug: User:lmorchard/PUT-API
  • Revision title: PUT-API
  • Revision id: 326289
  • Created:
  • Creator: lmorchard
  • Is current revision? No
  • Comment

Revision Content

Overview

The MDN wiki now provides an HTTP PUT API for updating documents in whole or by section. This can be handy for things such as:

  • You can create a page for your project and update content in certain sections from automated build, testing, and deployment scripts. This can help you keep your community up to date with your project's progress.
  • If your project offers documentation alongside source code, you can push HTML renderings into a subsection of MDN. This lets you maintain docs in a way that's appropriate for your team's workflow, while still contributing to MDN and allowing localizers to translate the content.

A word about testing

In developing the software that runs MDN, we host instances of the site on servers in various stages of readiness:

Accordingly, in order to keep from cluttering up the site with experimental content, you should try developing your application against Staging first. Then, when you are reasonably certain that it'll do what you want, reconfigure it to work against Production. You can also try working against Development, but you may run into issues.

Creating an API key

An API key allows an application to act on your behalf, without requiring your intervention to sign in with Persona every time. It provides a username and password for use with HTTP Basic authentication over SSL. It collects basic usage tracking, so you can see how it's been used. And, you can delete an API key to revoke access, in case it has been accidentally released to parties who shouldn't have it.

To create an API key, sign into MDN and visit the API keys management page. This page lets you create and delete API keys, as well as inspect recent usage history.

{{NoteStart}}The above link goes to the Production site, and the same keys do not work between Production and Staging. You can also get to this page by visiting your profile on the respective site: Click on your username in the upper right of the site. On your profile page, you should see a "Manage API Keys" button.{{NoteEnd}}

Clicking on the "Create a new API key" button should reveal a form with a single text field. You can use the field to describe the purposes for which the key will be used. This is an important field, because nothing else about the key will be visible in the future besides usage history.

After you fill out the text field and click "Create", the randomly generated key ID and secret will be displayed. This is the username and password, respectively. Copy these down somewhere safe (eg. to your application's configuration settings); the site will never display them again, and there is no recovery method. If you lose them, simply delete the API key and create another.

Making a PUT request

Since the PUT API works by way of HTTP, it should be compatible with the application environment and libraries of your choice. This first example uses the command-line tool cURL and a UNIX shell to demonstrate how to issue a simple PUT request to MDN.

Request

# Base URL and API key from staging (example only; substitute your own)
MDN_BASE_URL="https://developer.allizom.org"
MDN_KEY_ID="frsNFFR3w0yEALRE9IA9oN1KwoDno8vVGrzsBNvCofI"
MDN_SECRET="423PdCvnvraH0FkCDTKnizTmKGNkEdgQTi6RlEFTiWs"

# Document-specific details
DOC_USERNAME="lmorchard"  # Change this to your name
DOC_PATH="/en-US/docs/User:$DOC_USERNAME/PutExample"
DOC_TYPE="text/html"
DOC_DATA="<b>HELLO WORLD</b>"

# Putting it all together...
curl -si -X PUT -H"Content-Type: $DOC_TYPE" -d"$DOC_DATA" -u"$MDN_KEY_ID:$MDN_SECRET" "$MDN_BASE_URL$DOC_PATH"

Since there's a lot going on in this cURL invocation, the example is broken into variables:

  • MDN_BASE_URL - as mentioned before, you should plan to switch your application between staging and production servers on MDN. This variable allows for that.
  • MDN_KEY_ID - the key ID from the API key you created. Note that these are server-specific - the same keys do not work between staging and production.
  • MDN_SECRET - the secret from the API key that corresponds with the key ID.
  • DOC_USERNAME - change this to your MDN username.
  • DOC_PATH - the URL path to the document with content you want to manipulate.
  • DOC_TYPE - the content in the request will be text/html
  • DOC_DATA - the content sent in the PUT request body; this is the content that will be used in a new revision to the document

So, along with the variables, here are some general notes on the example and its use of the PUT API:

  • The key ID and secret are supplied as username and password, respectively, in HTTP Basic authentication over SSL.
  • The DOC_PATH for this example includes a username - presumably yours - but that's just for the sake of example and ensuring you have your own sample document to play with. You can use any URL path to any document on the wiki.
  • A Content-Type header is required, and lets MDN know how to process the content sent in the PUT request. Several content types are supported, and this feature will be described in greater detail shortly.
  • Content intended for the document is sent in the request body, using the representation promised in the Content-Type header

Response

There are several responses you may see if you try this example: 403, 404, 201, or 205. (You may see others, but those suggest something has gone wrong with the site. That will, hopefully, be rare.)

403 Forbidden

If either the key ID or secret are incorrect, you'll see a 403 Forbidden response. Double check your key details and that you're using the right pair for the right server. Create a new API key, if necessary.

404 Not Found

If you've never created a document at the URL path /en-US/docs/User:$MDN_USERNAME, you'll see a 404 Not Found response.

{{NoteStart}}The PUT API will not automatically create parent documents. If you're creating a number of documents intended to comprise a subsection of MDN, make sure to create parent documents first from the top down in the hierarchy.{{NoteEnd}}

201 Created

If the parent document exists, but the path itself doesn't, you should see a 201 Created response. This signifies that a new document was created, as opposed to an existing one having been updated.

205 Reset Content

In the case of an updated document, you'll see a 205 Reset Content response. This means that the document content has been updated, and that you should reload the document if you happen to need to see the results.

{{NoteStart}}MDN performs certain filtering and processing steps on content, so what you put in may not be exactly what gets served back.{{NoteEnd}}

Supported Content Types

The PUT API accepts one of several content types in the request body.

text/html

There are actually two forms of text/html accepted: fragment and document.

An HTML fragment is just an arbitrary chunk of markup, and is used as-is to revise document content. This is the simplest way to update documents.

However, content is treated as an HTML document if it consists of an <html> element containing <head> and <body> elements. The contents of <body> is extracted as the content intended as a new revision. From the <head> element, the contents of <title> is extracted and used as the title for the document on MDN. This is a more complex way to update documents, but is intended to accomodate submission of existing HTML pages.

application/json

Although the text/html content type is handy, there are more fields belonging to documents that are useful to manage. These include the following:

  • title - the document title
  • content - the content intended for the new revision
  • tags - tags used to organize documents
  • review_tags - tags used to request content reviews
  • summary - a comment describing the revision to be made
  • show_toc - a flag (0/1) indicating whether the table of contents should be shown for this document

These fields can be supplied as string values in a JSON-encoded object with the application/json content-type in a PUT request.

@@TODO: Need a JSON example here.

multipart/form-data

This content type is handled basically like application/json - the same fields are accepted. But, it might be less useful than JSON and is supported mainly for testing purposes.

Updating a single section

Normally, an HTTP PUT request replaces the entirety of a document with the submitted content in a new revision. However, you can use the query parameter ?section to constrain revision to a single section of the document and leave the rest of the content as-is. This is handy for automating changes to one part of a document that is otherwise managed by hand, or even for aggregating changes from many sources or scripts into one document.

Breaking a document into sections

Headers (ie. <h2> .. <h6>) make sections in MDN documents. The text of each header is transformed automatically into an ID, and that's used for anchor links in the table of contents sidebar on most documents. Those auto-generated IDs can be overriden with the name attribute on headers. Either way, looking at the table of contents is the easiest way to see how a document is broken up into sections, and to discover the IDs for those sections.

The contents of a section include its header and everything following the header up to (but not including) another header of the same or higher level. So, a section that starts with an <h2> continues until the next <h2>, including any subsections started by <h3> .. <h6>. That also means sections can be nested: An <h3> appearing after an <h2> creates a subsection, including any further nested subsections started by <h4> .. <h6>, up to the next <h3> or <h2>.

@@TODO: Show an HTML example with headers, here. This is a bit confusing.

Setting an id attribute on a container element (eg. a <div> or <span> or <section>) in the source view also creates a section, at least with respect to the PUT API. This is a bit more advanced and requires manual changes to raw HTML, rather than using the WYSIWYG editor. But, if you want to update a chunk of the page without the need for headers, this is how to do it.

Specifying a section for update

  • Look at the table of contents, note the anchor ID for the link (ie. the #hash part of the URL).
    For example: https://developer.mozilla.org/en-US/docs/User:lmorchard/PUT-API#Specifying_a_section
  • Minus the actual "#" character, that is the section ID.
    For example: Specifying_a_section
  • Take that ID, add ?section={ID} to the URL for the document.
    For example: https://developer.mozilla.org/en-US/docs/User:lmorchard/PUT-API?section=Specifying_a_section
  • If you view that URL in a browser (ie. HTTP GET), you'll see just that section of the document.
  • If you issue a PUT request to that URL, you'll modify just that section of the document.
    (But, don't do that to this URL, or you'll clobber the page you're reading right now!)

@@TODO: Show how to get IDs for sections from the table of contents

Revision Source

<h2 id="Overview">Overview</h2>
<p>The MDN wiki now provides an HTTP PUT API for updating documents in whole or by section. This can be handy for things such as:</p>
<ul>
  <li>You can create a page for your project and update content in certain sections from automated build, testing, and deployment scripts. This can help you keep your community up to date with your project's progress.</li>
  <li>If your project offers documentation alongside source code, you can push HTML renderings into a subsection of MDN. This lets you maintain docs in a way that's appropriate for your team's workflow, while still contributing to MDN and allowing localizers to translate the content.</li>
</ul>
<h3 id="A_word_about_testing">A word about testing</h3>
<p>In developing the software that runs MDN, we host instances of the site on servers in various stages of readiness:</p>
<ul>
  <li>Production (<a href="http://developer.mozilla.org/" title="http://developer.mozilla.org/">http://developer.mozilla.org/</a>), the real site with stable code and where changes to content matter.</li>
  <li>Staging (<a href="http://developer.allizom.org/" title="http://developer.allizom.org/">http://developer.allizom.org/</a>), a version of the site where changes are throwaway and upcoming features are tested.</li>
  <li>Development (<a href="http://developer-dev.allizom.org/" title="http://developer-dev.allizom.org/">http://developer-dev.allizom.org/</a>), a version of the site running the absolute latest and untested code.</li>
</ul>
<p>Accordingly, in order to keep from cluttering up the site with experimental content, you should try developing your application against Staging first. Then, when you are reasonably certain that it'll do what you want, reconfigure it to work against Production. You can also try working against Development, but you may run into issues.</p>
<h2 id="Creating_an_API_key">Creating an API key</h2>
<p>An API key allows an application to act on your behalf, without requiring your intervention to sign in with Persona every time. It provides a username and password for use with HTTP Basic authentication over SSL. It collects basic usage tracking, so you can see how it's been used. And, you can delete an API key to revoke access, in case it has been accidentally released to parties who shouldn't have it.</p>
<p>To create an API key, sign into MDN and <a href="https://developer.mozilla.org/en-US/keys/" title="https://developer.mozilla.org/en-US/keys/">visit the API keys management page</a>. This page lets you create and delete API keys, as well as inspect recent usage history.</p>
<p>{{NoteStart}}The above link goes to the Production site, and the same keys do not work between Production and Staging. You can also get to this page by visiting your profile on the respective site: Click on your username in the upper right of the site. On your profile page, you should see a "Manage API Keys" button.{{NoteEnd}}</p>
<p>Clicking on the "<a href="https://developer.mozilla.org/en-US/keys/new" title="https://developer.mozilla.org/en-US/keys/new">Create a new API key</a>" button should reveal a form with a single text field. You can use the field to describe the purposes for which the key will be used. This is an important field, because nothing else about the key will be visible in the future besides usage history.</p>
<p>After you fill out the text field and click "Create", the randomly generated key ID and secret will be displayed. This is the username and password, respectively. Copy these down somewhere safe (eg. to your application's configuration settings); the site will never display them again, and there is no recovery method. If you lose them, simply delete the API key and create another.</p>
<h2 id="Making_a_PUT_request">Making a PUT request</h2>
<p>Since the PUT API works by way of HTTP, it should be compatible with the application environment and libraries of your choice. This first example uses <a href="http://curl.haxx.se/" title="http://curl.haxx.se/">the command-line tool cURL</a> and a UNIX shell to demonstrate how to issue a simple PUT request to MDN.</p>
<h3 id="Request">Request</h3>
<pre class="brush: bash">
# Base URL and API key from staging (example only; substitute your own)
MDN_BASE_URL="https://developer.allizom.org"
MDN_KEY_ID="frsNFFR3w0yEALRE9IA9oN1KwoDno8vVGrzsBNvCofI"
MDN_SECRET="423PdCvnvraH0FkCDTKnizTmKGNkEdgQTi6RlEFTiWs"

# Document-specific details
DOC_USERNAME="lmorchard"  # Change this to your name
DOC_PATH="/en-US/docs/User:$DOC_USERNAME/PutExample"
DOC_TYPE="text/html"
DOC_DATA="&lt;b&gt;HELLO WORLD&lt;/b&gt;"

# Putting it all together...
curl -si -X PUT -H"Content-Type: $DOC_TYPE" -d"$DOC_DATA" -u"$MDN_KEY_ID:$MDN_SECRET" "$MDN_BASE_URL$DOC_PATH"</pre>
<p>Since there's a lot going on in this cURL invocation, the example is broken into variables:</p>
<ul>
  <li><code>MDN_BASE_URL</code> - as mentioned before, you should plan to switch your application between staging and production servers on MDN. This variable allows for that.</li>
  <li><code>MDN_KEY_ID</code> - the key ID from the API key you created. Note that these are server-specific - the same keys do not work between staging and production.</li>
  <li><code>MDN_SECRET</code> - the secret from the API key that corresponds with the key ID.</li>
  <li><code>DOC_USERNAME</code> - change this to your MDN username.</li>
  <li><code>DOC_PATH</code> - the URL path to the document with content you want to manipulate.</li>
  <li><code>DOC_TYPE</code> - the content in the request will be <code>text/html</code></li>
  <li><code>DOC_DATA</code> - the content sent in the PUT request body; this is the content that will be used in a new revision to the document</li>
</ul>
<p>So, along with the variables, here are some general notes on the example and its use of the PUT API:</p>
<ul>
  <li>The key ID and secret are supplied as username and password, respectively, in HTTP Basic authentication over SSL.</li>
  <li>The <code>DOC_PATH</code> for this example includes a username - presumably yours - but that's just for the sake of example and ensuring you have your own sample document to play with. You can use any URL path to any document on the wiki.</li>
  <li>A <code>Content-Type</code> header is required, and lets MDN know how to process the content sent in the PUT request. Several content types are supported, and this feature will be described in greater detail shortly.</li>
  <li>Content intended for the document is sent in the request body, using the representation promised in the <code>Content-Type</code> header</li>
</ul>
<h3 id="Response">Response</h3>
<p>There are several responses you may see if you try this example: <code>403</code>, <code>404</code>, <code>201</code>, or <code>205</code>. (You may see others, but those suggest something has gone wrong with the site. That will, hopefully, be rare.)</p>
<h4 id="403_Forbidden">403 Forbidden</h4>
<p>If either the key ID or secret are incorrect, you'll see a <code>403 Forbidden</code> response. Double check your key details and that you're using the right pair for the right server. Create a new API key, if necessary.</p>
<h4 id="404_Not_Found">404 Not Found</h4>
<p>If you've never created a document at the URL path <code>/en-US/docs/User:$MDN_USERNAME</code>, you'll see a <code>404 Not Found</code> response.</p>
<p>{{NoteStart}}The PUT API will not automatically create parent documents. If you're creating a number of documents intended to comprise a subsection of MDN, make sure to create parent documents first from the top down in the hierarchy.{{NoteEnd}}</p>
<h4 id="201_Created">201 Created</h4>
<p>If the parent document exists, but the path itself doesn't, you should see a <code>201 Created</code> response. This signifies that a new document was created, as opposed to an existing one having been updated.</p>
<h4 id="205_Reset_Content">205 Reset Content</h4>
<p>In the case of an updated document, you'll see a <code>205 Reset Content</code> response. This means that the document content has been updated, and that you should reload the document if you happen to need to see the results.</p>
<p>{{NoteStart}}MDN performs certain filtering and processing steps on content, so what you put in may not be exactly what gets served back.{{NoteEnd}}</p>
<h2 id="Supported_Content_Types">Supported Content Types</h2>
<p>The PUT API accepts one of several content types in the request body.</p>
<h3 id="text.2Fhtml">text/html</h3>
<p>There are actually two forms of <code>text/html</code> accepted: fragment and document.</p>
<p>An HTML fragment is just an arbitrary chunk of markup, and is used as-is to revise document content. This is the simplest way to update documents.</p>
<p>However, content is treated as an HTML document if it consists of an <code>&lt;html&gt;</code> element containing <code>&lt;head&gt;</code> and <code>&lt;body&gt;</code> elements. The contents of <code>&lt;body&gt;</code> is extracted as the content intended as a new revision. From the <code>&lt;head&gt;</code> element, the contents of <code>&lt;title&gt;</code> is extracted and used as the title for the document on MDN. This is a more complex way to update documents, but is intended to accomodate submission of existing HTML pages.</p>
<h3 id="application.2Fjson">application/json</h3>
<p>Although the <code>text/html</code> content type is handy, there are more fields belonging to documents that are useful to manage. These include the following:</p>
<ul>
  <li><code>title</code> - the document title</li>
  <li><code>content</code> - the content intended for the new revision</li>
  <li><code>tags</code> - tags used to organize documents</li>
  <li><code>review_tags</code> - tags used to request content reviews</li>
  <li><code>summary</code> - a comment describing the revision to be made</li>
  <li><code>show_toc</code> - a flag (0/1) indicating whether the table of contents should be shown for this document</li>
</ul>
<p>These fields can be supplied as string values in a JSON-encoded object with the <code>application/json</code> content-type in a PUT request.</p>
<p>@@TODO: Need a JSON example here.</p>
<h3 id="multipart.2Fform-data">multipart/form-data</h3>
<p>This content type is handled basically like <code>application/json</code> - the same fields are accepted. But, it might be less useful than JSON and is supported mainly for testing purposes.</p>
<h2 id="Updating_a_single_section">Updating a single section</h2>
<p>Normally, an HTTP PUT request replaces the entirety of a document with the submitted content in a new revision. However, you can use the query parameter <code>?section</code> to constrain revision to a single section of the document and leave the rest of the content as-is. This is handy for automating changes to one part of a document that is otherwise managed by hand, or even for aggregating changes from many sources or scripts into one document.</p>
<h3 id="Breaking_a_document_into_sections">Breaking a document into sections</h3>
<p>Headers (ie. <code>&lt;h2&gt;</code> .. <code>&lt;h6&gt;</code>) make sections in MDN documents. The text of each header is transformed automatically into an ID, and that's used for anchor links in the table of contents sidebar on most documents. Those auto-generated IDs can be overriden with the <code>name</code> attribute on headers. Either way, looking at the table of contents is the easiest way to see how a document is broken up into sections, and to discover the IDs for those sections.</p>
<p>The contents of a section include its header and everything following the header up to (but not including) another header of the same or higher level. So, a section that starts with an <code>&lt;h2&gt;</code> continues until the next <code>&lt;h2&gt;</code>, including any subsections started by <code>&lt;h3&gt;</code> .. <code>&lt;h6&gt;</code>. That also means sections can be nested: An <code>&lt;h3&gt;</code> appearing after an <code>&lt;h2&gt;</code> creates a subsection, including any further nested subsections started by <code>&lt;h4&gt;</code> .. <code>&lt;h6&gt;</code>, up to the next <code>&lt;h3&gt;</code> or <code>&lt;h2&gt;</code>.</p>
<p>@@TODO: Show an HTML example with headers, here. This is a bit confusing.</p>
<p>Setting an <code>id</code> attribute on a container element (eg. a <code>&lt;div&gt;</code> or <code>&lt;span&gt;</code> or <code>&lt;section&gt;</code>) in the source view also creates a section, at least with respect to the PUT API. This is a bit more advanced and requires manual changes to raw HTML, rather than using the WYSIWYG editor. But, if you want to update a chunk of the page without the need for headers, this is how to do it.</p>
<h3 id="Specifying_a_section">Specifying a section for update</h3>
<ul>
  <li>Look at the table of contents, note the anchor ID for the link (ie. the <code>#hash</code> part of the URL).<br />
    For example: <code>https://developer.mozilla.org/en-US/docs/User:lmorchard/PUT-API#Specifying_a_section</code></li>
  <li>Minus the actual "#" character, that is the section ID.<br />
    For example: <code>Specifying_a_section</code></li>
  <li>Take that ID, add <code>?section={ID}</code> to the URL for the document.<br />
    For example: <code>https://developer.mozilla.org/en-US/docs/User:lmorchard/PUT-API?section=Specifying_a_section</code></li>
  <li>If you view <a href="https://developer.mozilla.org/en-US/docs/User:lmorchard/PUT-API?section=Specifying_a_section" title="https://developer.mozilla.org/en-US/docs/User:lmorchard/PUT-API?section=Specifying_a_section">that URL</a> in a browser (ie. HTTP GET), you'll see just that section of the document.</li>
  <li>If you issue a PUT request to that URL, you'll modify just that section of the document.<br />
    (But, don't do that to <em>this</em> URL, or you'll clobber the page you're reading right now!)</li>
</ul>
<p>@@TODO: Show how to get IDs for sections from the table of contents</p>
Revert to this revision