JavaScript
Plain JavaScript for a web page, using fetch and the Web Crypto API.
The API must be enabled first, see Enabling the API. How a request is signed is explained in Authentication.
Client
// Signs requests with the Web Crypto API, which browsers only provide on https (or localhost).
// The API token has full access to FileFlows, only use this in a page you trust everyone who can open it with.
const SERVER_URL = 'http://localhost:19200';
const API_TOKEN = 'YOUR_API_TOKEN';
const encoder = new TextEncoder();
const toHex = buffer => Array.from(new Uint8Array(buffer), x => x.toString(16).padStart(2, '0')).join('');
// calls the FileFlows API, each request is signed with the API token (the token is never sent)
async function fileflowsApi(method, path, body = null) {
const json = body === null ? '' : JSON.stringify(body);
const timestamp = Math.floor(Date.now() / 1000).toString();
const nonce = crypto.randomUUID().replace(/-/g, '');
const bodyHash = json === '' ? '' : toHex(await crypto.subtle.digest('SHA-256', encoder.encode(json)));
const signedPath = decodeURIComponent(path.split('?')[0]);
const stringToSign = method.toUpperCase() + ':' + signedPath + ':' + timestamp + ':' + nonce + ':' + bodyHash;
const key = await crypto.subtle.importKey('raw', encoder.encode(API_TOKEN),
{ name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
const signature = toHex(await crypto.subtle.sign('HMAC', key, encoder.encode(stringToSign)));
const headers = { 'X-Timestamp': timestamp, 'X-Nonce': nonce, 'X-Signature': signature };
if (json !== '')
headers['Content-Type'] = 'application/json';
const response = await fetch(SERVER_URL + path, { method, headers, body: json === '' ? undefined : json });
const text = await response.text();
if (!response.ok)
throw new Error(response.status + ': ' + text);
return text ? JSON.parse(text) : null;
}
// const status = await fileflowsApi('GET', '/api/status');
Browsers only provide the Web Crypto API (crypto.subtle) on pages served over https, or from localhost.
The API token has full access to FileFlows, and anyone who can open the page can read it. Only use this in a page that only you, or people you would trust with full access, can open. For anything else, call the API from a server, e.g. with Node.js.
Your browser may also block the request if the page is on a different address to your FileFlows server (CORS).
Usage
const status = await fileflowsApi('GET', '/api/status');
console.log(status);
To send a JSON body, pass it as the body argument. The function serializes it once, and signs and sends that same JSON text.