diff --git a/swh/web/templates/api/api.html b/swh/web/templates/api/api.html index c9776112..e80d6931 100644 --- a/swh/web/templates/api/api.html +++ b/swh/web/templates/api/api.html @@ -1,239 +1,277 @@ {% extends "layout.html" %} {% comment %} -Copyright (C) 2015-2020 The Software Heritage developers +Copyright (C) 2015-2020 The Software Heritage developers See the AUTHORS file at the top-level directory of this distribution License: GNU Affero General Public License version 3, or any later version See top-level LICENSE file for more information {% endcomment %} {% block title %} Overview – Software Heritage API {% endblock %} -{% block navbar-content %} -

Web API

-{% endblock %} +{% block navbar-content %}

Web API

{% endblock %} {% block content %}
+

Endpoint index

-

You can jump directly to the - - endpoint index - , which lists all available API functionalities, or read on for more general information about the API.

+

+ You can jump directly to the endpoint index , which + lists all available API functionalities, or read on for more general information about the API. +

+

Data model

-

The - Software Heritage project harvests publicly available source code by - tracking software distribution channels such as - version control systems, tarball releases, and distribution packages.

-

All retrieved source code and related metadata are stored in the Software Heritage archive, that is conceptually a - Merkle DAG. All nodes in the graph are content-addressable, - i.e., their node identifiers are computed by hashing their - content and, transitively, that of all nodes reachable from them; and no node or edge is ever removed from the graph: - the - Software Heritage archive is an append-only data structure.

-

The following types of objects (i.e., graph nodes) can be found in the Software Heritage archive - (for more information see the - Software Heritage glossary):

+

+ The Software Heritage project harvests publicly + available source code by tracking software distribution channels such as version control + systems, tarball releases, and distribution packages. +

+

+ All retrieved source code and related metadata are stored in the Software Heritage archive, that + is conceptually a Merkle DAG. All nodes + in the graph are content-addressable, i.e., their node identifiers are computed by hashing their + content and, transitively, that of all nodes reachable from them; and no node or edge is ever + removed from the graph: the Software Heritage archive is an append-only data structure. +

+

+ The following types of objects (i.e., graph nodes) can be found in the Software Heritage archive + (for more information see the Software Heritage + glossary): +

+

Version

-

The current version of the API is - v1.

+

The current version of the API isv1.

- Warning: this version of the API is not to be considered stable yet. Non-backward compatible changes - might happen - even without changing the API version number.

+ Warning: this version of the API is not to be considered stable yet. + Non-backward compatible changes might happen even without changing the API version number. +

+

Schema

API access is over HTTPS.

-

All API endpoints are rooted at - https://archive.softwareheritage.org/api/1/.

+

+ All API endpoints are rooted at + https://archive.softwareheritage.org/api/1/. +

Data is sent and received as JSON by default.

Example:

+

Response format override

-

The response format can be overridden using the - Accept request header. In particular, - Accept: text/html (that web browsers send by default) requests HTML pretty-printing, whereas - Accept: application/yaml requests YAML-encoded responses.

+

+ The response format can be overridden using the Accept request header. In + particular, Accept: text/html (that web browsers send by default) requests HTML + pretty-printing, whereas Accept: application/yaml requests YAML-encoded responses. +

Example:

Parameters

-

Some API endpoints can be tweaked by passing optional parameters. For GET requests, optional parameters can be passed - as - an HTTP query string.

-

The optional parameter - fields is accepted by all endpoints that return dictionaries and can be used to restrict the list of - fields returned - by the API, in case you are not interested in all of them. By default, all available fields are returned.

+

+ Some API endpoints can be tweaked by passing optional parameters. For GET requests, optional + parameters can be passed as an HTTP query string. +

+

+ The optional parameter fields is accepted by all endpoints that return dictionaries + and can be used to restrict the list of fields returned by the API, in case you are not + interested in all of them. By default, all available fields are returned. +

Example:

+

Errors

-

While API endpoints will return different kinds of errors depending on their own semantics, some error patterns are - common - across all endpoints.

-

Sending malformed data, including syntactically incorrect object identifiers, will result in a - 400 Bad Request HTTP response. Example:

+

+ While API endpoints will return different kinds of errors depending on their own semantics, some + error patterns are common across all endpoints. +

+

+ Sending malformed data, including syntactically incorrect object identifiers, will result in a + 400 Bad Request HTTP response. Example: +

-

Requesting non existent resources will result in a - 404 Not Found HTTP response. Example:

+

+ Requesting non existent resources will result in a 404 Not Found HTTP response. + Example: +

-

Unavailability of the underlying storage backend will result in a - 503 Service Unavailable HTTP response.

+

+ Unavailability of the underlying storage backend will result in a 503 Service + Unavailable HTTP response. +

+

UTF-8 decoding errors

-

While attempting to decode UTF-8 strings from raw bytes stored in the archive, some errors - might happen when generating an API response. In that case, an extra field decoding_failures - will be added to each concerned JSON object (possibly nested). It will contain the list of its key - names where UTF-8 decoding failed. +

+ While attempting to decode UTF-8 strings from raw bytes stored in the archive, some errors might + happen when generating an API response. In that case, an extra field + decoding_failures will be added to each concerned JSON object (possibly nested). It + will contain the list of its key names where UTF-8 decoding failed.

A string that could not be decoded will have the bytes of its invalid UTF-8 sequences escaped as \\x<hex value>.

+

Pagination

Requests that might potentially return many items will be paginated.

-

Page size is set to a default (usually: 10 items), but might be overridden with the - per_page query parameter up to a maximum (usually: 50 items). Example:

+

+ Page size is set to a default (usually: 10 items), but might be overridden with the + per_page query parameter up to a maximum (usually: 50 items). Example: +

curl https://archive.softwareheritage.org/api/1/origin/1/visits/?per_page=2
-

To navigate through paginated results, a - Link HTTP response header is available to link the current result page to the next one. Example:

+

+ To navigate through paginated results, a Link HTTP response header is available to + link the current result page to the next one. Example: +

curl -i https://archive.softwareheritage.org/api/1/origin/1/visits/?per_page=2 | grep ^Link:
-  Link: </api/1/origin/1/visits/?last_visit=2&per_page=2>; rel="next",
+Link: </api/1/origin/1/visits/?last_visit=2&per_page=2>; rel="next", +

Rate limiting

-

Due to limited resource availability on the back end side, API usage is currently rate limited. Furthermore, as API - usage - is currently entirely anonymous (i.e., without any authentication), API "users" are currently identified by - their - origin IP address.

-

Three HTTP response fields will inform you about the current state of limits that apply to your current rate limiting - bucket:

+

+ Due to limited resource availability on the back end side, API usage is currently rate limited. + Furthermore, as API usage is currently entirely anonymous (i.e., without any authentication), + API "users" are currently identified by their origin IP address. +

+ +

+ Three HTTP response fields will inform you about the current state of limits that apply to your + current rate limiting bucket: +

Example:

curl -i https://archive.softwareheritage.org/api/1/stat/counters/ | grep ^X-RateLimit
-  X-RateLimit-Limit: 60
-  X-RateLimit-Remaining: 54
-  X-RateLimit-Reset: 1485794532
+X-RateLimit-Limit: 60 +X-RateLimit-Remaining: 54 +X-RateLimit-Reset: 1485794532
{% endblock %} diff --git a/swh/web/templates/api/apidoc.html b/swh/web/templates/api/apidoc.html index 65067a1e..05f2a8f5 100644 --- a/swh/web/templates/api/apidoc.html +++ b/swh/web/templates/api/apidoc.html @@ -1,212 +1,212 @@ {% extends "layout.html" %} {% comment %} -Copyright (C) 2015-2019 The Software Heritage developers +Copyright (C) 2015-2020 The Software Heritage developers See the AUTHORS file at the top-level directory of this distribution License: GNU Affero General Public License version 3, or any later version See top-level LICENSE file for more information {% endcomment %} {% load swh_templatetags %} {% block title %}{{ heading }} – Software Heritage API {% endblock %} {% block navbar-content %} {% endblock %} {% block content %}
-{% if description %} -
-

Description

- {{ description | docstring_display | safe }} -
-{% endif %} -{% if response_data is not None %} -
-

Request

-
{{ request.method }} {{ request.build_absolute_uri }}
-
-

Response

- {% if status_code != 200 %} -
Status Code
-
{{ status_code }}
- {% endif %} - {% if headers_data %} -
Headers
- {% for header_name, header_value in headers_data.items %} -
{{ header_name }} {{ header_value | urlize_header_links | safe }}
- {% endfor %} - {% endif %} -
Body
-
{{ response_data | urlize_links_and_mails | safe }}
-
-{% endif %} -
-{% if urls and urls|length > 0 %} -
- - - - - - - - - {% for url in urls %} + {% if description %} +
+

Description

+ {{ description | docstring_display | safe }} +
+ {% endif %} + {% if response_data is not None %} +
+

Request

+
{{ request.method }} {{ request.build_absolute_uri }}
+
+

Response

+ {% if status_code != 200 %} +
Status Code
+
{{ status_code }}
+ {% endif %} + {% if headers_data %} +
Headers
+ {% for header_name, header_value in headers_data.items %} +
{{ header_name }} {{ header_value | urlize_header_links | safe }}
+ {% endfor %} + {% endif %} +
Body
+
{{ response_data | urlize_links_and_mails | safe }}
+
+ {% endif %} +
+ {% if urls and urls|length > 0 %} +
+
URLAllowed Methods
+ - - + + - {% endfor %} - -
{{ url.rule | docstring_display | safe }}{{ url.methods | dictsort:0 | join:', ' }}URLAllowed Methods
-
-
-{% endif %} -{% if args and args|length > 0 %} -
-

Arguments

- {% for arg in args %} -
-
{{ arg.name }} ({{ arg.type }})
-
{{ arg.doc | docstring_display | safe }}
-
- {% endfor %} -
-
-{% endif %} -{% if params and params|length > 0 %} -
-

Query parameters

- {% for param in params %} -
-
{{ param.name }} ({{ param.type }})
-
{{ param.doc | docstring_display | safe }}
-
- {% endfor %} -
-
-{% endif %} -{% if reqheaders and reqheaders|length > 0 %} -
-

Request headers

- {% for header in reqheaders %} -
-
{{ header.name }}
-
{{ header.doc | docstring_display | safe }}
-
- {% endfor %} -
-
-{% endif %} -{% if input_type %} -
-

Request data

-
-
{{ input_type }}
-
-

- {% if input_type == 'array' and inputs_list == '' %} - {{ inputs.0.doc | safe }} - {% elif input_type == 'array' and inputs_list != '' %} - an array of objects containing the following keys: - {% elif input_type == 'octet stream' %} - raw data as an octet stream - {% elif input_type == 'object' %} - an object containing the following keys: - {% endif %} - {% if inputs_list != '' %} - {{ inputs_list | docstring_display | safe }} - {% endif %} -

-
-
-
-
-{% endif %} -{% if resheaders and resheaders|length > 0 %} -
-

Response headers

- {% for header in resheaders %} -
-
{{ header.name }}
-
{{ header.doc | docstring_display | safe }}
-
- {% endfor %} -
-
-{% endif %} -{% if return_type %} -
-

Returns

-
-
{{ return_type }}
-
-

- {% if return_type == 'array' and returns_list == '' %} - {{ returns.0.doc | safe }} - {% elif return_type == 'array' and returns_list != '' %} - an array of objects containing the following keys: - {% elif return_type == 'octet stream' %} - raw data as an octet stream - {% elif return_type == 'object' %} - an object containing the following keys: - {% endif %} - {% if returns_list != '' %} - {{ returns_list | docstring_display | safe }} - {% endif %} -

-
-
-
-
-{% endif %} -{% if status_codes and status_codes|length > 0 %} -
-

HTTP status codes

- {% for status in status_codes %} + + + {% for url in urls %} + + {{ url.rule | docstring_display | safe }} + {{ url.methods | dictsort:0 | join:', ' }} + + {% endfor %} + + +
+
+ {% endif %} + {% if args and args|length > 0 %} +
+

Arguments

+ {% for arg in args %} +
+
{{ arg.name }} ({{ arg.type }})
+
{{ arg.doc | docstring_display | safe }}
+
+ {% endfor %} +
+
+ {% endif %} + {% if params and params|length > 0 %} +
+

Query parameters

+ {% for param in params %} +
+
{{ param.name }} ({{ param.type }})
+
{{ param.doc | docstring_display | safe }}
+
+ {% endfor %} +
+
+ {% endif %} + {% if reqheaders and reqheaders|length > 0 %} +
+

Request headers

+ {% for header in reqheaders %} +
+
{{ header.name }}
+
{{ header.doc | docstring_display | safe }}
+
+ {% endfor %} +
+
+ {% endif %} + {% if input_type %} +
+

Request data

-
{{ status.code }}
-
{{ status.doc | docstring_display | safe }}
+
{{ input_type }}
+
+

+ {% if input_type == 'array' and inputs_list == '' %} + {{ inputs.0.doc | safe }} + {% elif input_type == 'array' and inputs_list != '' %} + an array of objects containing the following keys: + {% elif input_type == 'octet stream' %} + raw data as an octet stream + {% elif input_type == 'object' %} + an object containing the following keys: + {% endif %} + {% if inputs_list != '' %} + {{ inputs_list | docstring_display | safe }} + {% endif %} +

+
- {% endfor %} -
-
-{% endif %} -{% if examples and examples|length > 0 %} -
-

Examples

- {% for example in examples %} +
+
+ {% endif %} + {% if resheaders and resheaders|length > 0 %} +
+

Response headers

+ {% for header in resheaders %} +
+
{{ header.name }}
+
{{ header.doc | docstring_display | safe }}
+
+ {% endfor %} +
+
+ {% endif %} + {% if return_type %} +
+

Returns

-
+
{{ return_type }}
- {{ example }} +

+ {% if return_type == 'array' and returns_list == '' %} + {{ returns.0.doc | safe }} + {% elif return_type == 'array' and returns_list != '' %} + an array of objects containing the following keys: + {% elif return_type == 'octet stream' %} + raw data as an octet stream + {% elif return_type == 'object' %} + an object containing the following keys: + {% endif %} + {% if returns_list != '' %} + {{ returns_list | docstring_display | safe }} + {% endif %} +

- {% endfor %} -
-{% endif %} +
+
+ {% endif %} + {% if status_codes and status_codes|length > 0 %} +
+

HTTP status codes

+ {% for status in status_codes %} +
+
{{ status.code }}
+
{{ status.doc | docstring_display | safe }}
+
+ {% endfor %} +
+
+ {% endif %} + {% if examples and examples|length > 0 %} +
+

Examples

+ {% for example in examples %} +
+
+
+ {{ example }} +
+
+ {% endfor %} +
+ {% endif %} {% endblock %}