Chapter 12. API

Table of Contents

General
Clients
API Version
Object References
Reference Data
Date and Time Data
Invocations and Transport
Security
If-Modified-Since Header
RPC-over-HTTP API
Error Codes
Generating RPC-over-REST API Client for Python
Raising, Waiting and Fetching Data for Background Jobs
Schema
REST API
Entry Point
Trigger Import Repository Data
Get Package Icon
Get All Packages' Icons as an Archive
Get All Package Versions Details
Get Reference Data
Get All Repositories' Details
Get Screenshot Image
Get Raw Screenshot Image
Add Screenshot Image

General

This information applies to all areas of the API for the system. Some of the APIs are "REST" in nature. Other APIs are RPC-over-HTTP in nature. An older API exists which is presented in JSON-RPC.

Clients

A client of this system's API may be a desktop application (eg; Haiku Depot) or may be logic in a web page where the web page is using some java-script to call back to the server. It is also possible for other applications to also interact with HDS using its API.

API Version

The JSON-RPC API is known as "version 1" and the RPC-over-HTTP is known as "version 2". The latter will eventually completely replace the former. Version 1 is still required for some time until all clients using the version 1 are no longer required.

Object References

When objects such as packages or users are referred to in the API, the database primary key is not used. Instead either a natural or artifical identifier is employed. For example, in the case of a package, the package's name may be used. In the case of a screen-shot, a GUID (unique identifier) will be used to identify a particular screenshot.

Reference Data

Reference data means data in the application that is generally invariant. Examples include the mime types, natural language, url types and so on. In these cases, an API will generally provide for access to the list of reference data. The client is expected to obtain such reference data as necessary and cache reference data locally.

Date and Time Data

The system has only a concept of a "moment in time" which is called a timestamp. The timestamp is typically communicated as the number of milliseconds elapsed since the epoc represented as a 64bit integer. The timestamp communicated via the API is always relative to UTC.

Invocations and Transport

The term "invocation" refers to a request-response cycle from the client software into the application server over the HTTP protocol. Each API invocation is made in a stateless manner in that each invocation is not dependent on the prior invocation.

Security

See the security chapter for details on how to authenticate API requests as well as how API requests are authorized.

If-Modified-Since Header

This header is only observed in some APIs where large quantities of data are being downloaded or where the data is computationally expensive to assemble. Examples of these situations include the assembly of a tar-ball of pacakges' icons or the download of bulk package data.

In order to prevent clients from downloading and processing data they already have, the client may add a "If-Modified-Since" header to the initial request. The form of this header is RFC-1123 compliant and looks like "Sat, 3 Dec 2016 23:48:05 GMT". Taking the example of downloading a tar-ball of icon data; if the icon data has not been modified since the "If-Modified-Since" header time, then the API will return a 304 (Not Modified) response.

RPC-over-HTTP API

This API is achieved by sending JSON payloads over HTTP. The request is expressed as JSON and the response is also expressed as JSON. The request is a JSON object with key-value pairs of data. The response has the following shape;

{
  "result": {
    "code": "beam",
    "name": "Beam Email Program"
  }
}

In the event that there is an error, this is expressed in the response as follows;

{
  "error": {
    "code": 12345,
    "message": "Something has gone wrong",
    "data": [
      { "key": "something", "value": "Feet" }
    ]
  }
}

One can find the definitions for the APIs in Open-API format in the source code in the module "haikudepotserver-api2".

Error Codes

A set of known RPC error codes are agreed between the client and server. See the RPC specification for known error codes used for transport-related issues such as invalid parameters. Application-specific error codes are documented in the java source at "org.haiku.haikudepotserver.api1.support.Constants".

Some errors such as the validation error (code -32800) may also carry additional data that provides detail as to the nature of the error that has arisen. Java logic for assembling the error payloads can be found at "org.haiku.haikudepotserver.api1.support.ErrorResolverImpl".

Generating RPC-over-REST API Client for Python

The RPC-over-REST API is expressed as Open-API specifications. These specifications can be used to generate code that represents a client. To generate a client for the Python language, issue the following commands from the top level of the project;

./mvnw --projects haikudepotserver-api2 package -Ppython

The resulting code can be found at "./haikudepotserver-api2/target/generated-sources/openapi/openapi_client".

Raising, Waiting and Fetching Data for Background Jobs

Some requests are instant and some take some time to complete. An example of an instant API is fetching the details of a user. An example of a request that may take some time is producing an archive of all of the icons for all packages in the system.

For the long-run requests the HDS API system provides an asynchronous interface with a generalized pattern of interaction. This section covers how to use this pattern. The pattern generally follows the following steps;

  • Create the job using a POST request to a specific job-creation API. An example would be a POST request to "/__api/v2/pkg-job/queue-pkg-icon-export-archive-job". This API will return a job code.
  • Poll until complete by sending a series of POST requests to "/__api/v2/job/get-job" with the job code and wait for the job status to be "FINISHED" or "FAILED" or "CANCELLED".
  • The "get-job" response has some data codes under "generatedData" which you can use to obtain the data.
  • GET "/__secured/jobdata/{datacode}/download" to obtain the data. Note this will need to handle redirects.

Details about the specific API call signatures for any API with paths "/__api/..." can be obtained from the Open-API specification in the "haikudepotserver-api2" module.

Some jobs may require data to be provided. An example of this might be where a tar-ball of screenshots is uploaded to be imported. In this case, HDS provides an API to upload the data which will then return a data code. Where required, the data code can be used with the API to start a job. To access the data upload function, invoke a POST request to "/__secured/jobdata". The API call will return the data code in a response header "X-HaikuDepotServer-DataGuid".

Schema

Some of the data transfer objects (DTO) in the system are generated. This means that a software artifact is stored in the project and the java objects that are used in the running software are generated from the schema document. In the java environment this is done using maven plugins, but it is also made possible in the C++ environment too. Python scripts are provided to cater for this.

The HaikuDepot build system will use the schema to generate C++ objects. You can find this in the "build" directory of the HaikuDepot source. The schema are read and are trans-coded to C++ using Python scripts. The schema files are copied manually from HDS to the HaikuDepot source.

REST API

REST API is generally required where data is inappropriate to encode as JSON-RPC. This tends to be situations where the data is binary in nature or where data is large in size. An example of this is where a package icon needs to be uploaded or where bulk packages' data should be returned.

Entry Point

This API will provide the web application's HTML user interface.

HTTP Method
GET
Path
/
Response Content-Type
text/html

Trigger Import Repository Data

This API provides a mechanism by which an external client is able to trigger the application to start importing package-related data from a remote repository. This API is provided as REST because the client is likely to be scripted using a scripting language and REST is the most appropriate protocol to employ in this situation. This invocation will trigger the import process, but the import process will execute in a background thread in the application server and will not block the client.

In order to prevent the possibility of this API causing undue load on the application server, it will coalesce overlapping requests. This means that if a succession of requests come in requesting that the repository "xyz" is imported then onle the first one will be honoured and only after the first one is completed with another be accepted.

It is possible for an administrator to configure a password on the Repository. If this is the case then this API will require a Basic authentication header to be sent to authenticate the request with the configured password. The username provided in the Basic authentication header is ignored.

HTTP Method
POST
Path
/__repository/<repositorycode>/import
Path
/__repository/<repositorycode>/source/<repositorysourcecode>/import
Specific Request Headers
Authorization
Allows for "Basic" authentication mechanism for situations where the repository has a password configured.
Response Content-Type
text/plain
Expected HTTP Status Codes
200
The import job was accepted.
401
The provided password was rejected.
404
The repository or source was not able to be found.

Example 12.1. Example: Prompt Repository Update

In this example, a remote system build script has just completed the assembly of repository and would now like to prompt HDS to import the HPKR data for processing. The Repository and the RepositorySource are correctly configured on the HDS system. The Repository code is "haikuports" and the RepositorySource is "haikuports_x86_64". Using the CURL command, HDS could be prompted as follows;

curl -X POST \
-u ":password" \
"http://depot.haiku-os.org/__repository/haikuports/source/haikuports_x86_64/import"


Get Package Icon

This API is able to provide the icon for a package. If there is no icon stored then this method will provide a fall-back image if the "f" query parameter is configured to "true" — otherwise it will return a 404 HTTP status code. Providing a fallback image may not be possible in all cases. The request will return a "Last-Modified" header. The timestamps of this header will correlate to the "modifyTimestamp" that is provided in API responses such as "GetPkResult" and "SearchPkgsResult". The value for "modifyTimestamp" will be at millisecond resolution, but the HTTP headers will be at second resolution. The path includes a "mediatype-extension" which can have one of the following values;

  • png
  • hvif

Details of the API;

HTTP Method
GET, HEAD
Path
/__pkgicon/<pkgname>.<mediatype-extension>
Response Content-Type
"image/png" or "application/x-vnd.haiku-icon"
Query Parameters
s
Either 16 or 32 for the number of pixels; omitt for hivf files
f
"true" will yield a fallback image in the response if possible
Expected HTTP Status Codes
200
The icon is provided in the response (for GET)
415
The path did not include ".png" or the size is invalid
400
The package name was not supplied
404
The package was not found or no image was present

An example URL for obtaining a bitmap image would be "http://localhost:8080/__pkgicon/apr.png?size=32&f=true".

An example URL for obtaining a Haiku vector image file image would be "http://localhost:8080/__pkgicon/apr.hvif"

Get All Packages' Icons as an Archive

This API is able to generate a "tar-ball" containing all of the icon data together with some meta-data about the icons. Note that the data will be compressed using gzip compression. After making this call, the client may be redirected to a different URL to actually access the data. Clients should not make assumptions about the form of the redirected URL.

This API supports the If-Modified-Since header.

The tar-ball contains a file "info.json" which has a field "dataModifyTimestamp" that can be used to form the "If-Modified-Since". Otherwise, the file contains each entry in the form "hicn/<package-name>/<icon-leaf>.<extension>". Possible values for the extension are;

  • png
  • hvif

The icon-leaf may be "icon" in the case of HVIF data or in the case of a bitmap icon, the icon-leaf will be the size of the image; for example 16, 32 or 64.

Details of the API;

HTTP Method
GET
Path
/__pkgicon/all.tar.gz
Expected HTTP Status Codes
302
Redirect to the actual payload data.
304
The data was not modified since the supplied timestamp.

Get All Package Versions Details

This API is able to provide all of the packages' details sufficient for running the desktop application.

This API supports the If-Modified-Since header.

The resultant data transfer objects (DTO) used in this API are available as a json schema within the source.

Details of the API;

HTTP Method
GET
Path
/__pkg/all-<repositorySourceCode>-<naturalLanguageCode>.json.gz
Expected HTTP Status Codes
302
Redirect to the actual payload data.
304
The data was not modified since the supplied timestamp.

Get Reference Data

This API is able to generate a JSON payload containing reference data for selected pieces of information in the system such as Countries, Natural Languages and Package Categories. This can then be used in applications such as HaikuDepot in order to support provision of choices for the user in drop-down lists etc...

This API supports the If-Modified-Since header.

The resultant data transfer objects (DTO) used in this API are available as a json schema within the source.

Details of the API;

HTTP Method
GET
Path
/__reference/all-<natural-language-code>.json.gz
Expected HTTP Status Codes
302
Redirect to the actual payload data.
304
The data was not modified since the supplied timestamp.

Get All Repositories' Details

This API is able to generate a large JSON payload containing details regarding each active repository. Note that the path contains a natural language code such as "de" but at the time of writing there is no support for localizing this information.

This API supports the If-Modified-Since header.

The resultant data transfer objects (DTO) used in this API are available as a json schema within the source.

Details of the API;

HTTP Method
GET
Path
/__repository/all-<natural-language-code>.json.gz
Expected HTTP Status Codes
302
Redirect to the actual payload data.
304
The data was not modified since the supplied timestamp.

Get Screenshot Image

This API is able to produce an image for a screenshot. The screenshot is identified in the path by its code. The response will return a "Last-Modified" header. The timestamps of this header will correlate to the "modifyTimestamp" that is provided in API responses such as "GetPkResult" and "SearchPkgsResult". The value for "modifyTimestamp" will be at millisecond resolution, but the HTTP headers will be at second resolution. Requests for screenshot image should be accompanied by a target width and height. These values must be within a range of 1..1500. The image will maintain its aspect ratio as it is scaled to fit within the supplied target width and height.

HTTP Method
GET, HEAD
Path
/__pkgscreenshot/<screenshotcode>.png
Response Content-Type
"image/png"
Query Parameters
tw
An integer value that describes the width that the image should be scaled to
th
An integer value that describes the height that the image should be scaled to
Expected HTTP Status Codes
200
The image data is provided in the response (for GET)
415
The path did not include ".png" or the target width or height is invalid or the length of the data is too large
400
The screenshot code was not supplied
404
The screenshot was not found

An example URL is "http://localhost:8080/pkgscreenshot/a78hw20fh2p20fh122jd92.png?tw=640&th=480".

Get Raw Screenshot Image

This API is able to provide the raw screenshot data.

HTTP Method
GET
Path
/__pkgscreenshot/<screenshotcode>/raw
Response Content-Type
As per the stored data
Expected HTTP Status Codes
200
The image data is provided in the response
404
The screenshot was not found for the code supplied

An example URL is "http://localhost:8080/__pkgscreenshot/a78hw20fh2p20fh122jd92/raw".

Add Screenshot Image

This API is able to add an image as a screenshot for the nominated package. The screenshot will be ordered last. The payload of the POST must be a PNG image that is a maximum of 1500x1500 pixels and a maximum of 2MB in size.

HTTP Method
POST
Path
/__pkgscreenshot/<pkgname>/add
Query Parameters
format
The string "png" to define the image format.
Expected HTTP Status Codes
200
The screenshot image was stored
415
The path did not include ".png" or the size (pixels or data) of the image is invalid or the payload is not PNG image data.
404
The package identified in the path was not able to be found
400
The package name was not supplied
Specific Response Headers
X-HaikuDepotServer-ScreenshotCode
Supplies the code of the newly created screenshot.

An example URL is "http://localhost:8080/__pkgscreenshot/apr/add?format=png".