HTTP API
These are all the requests supported by Seafowl's HTTP API.
Query result format
Seafowl returns query results in the HTTP response body using the JSON Lines format, with one line per row:
{"text_column":"VALUE 1","float_column":12.34,"int_column":12}
{"text_column":"VALUE 2","float_column":56.78,"int_column":13}
{"text_column":"VALUE 3","float_column":91.01,"int_column":14}
It currently doesn't return any other (like type) information or support other return formats.
Authorization
For the purposes of authorization, Seafowl distinguishes between read-only
(SELECT
) and write (all other statements) SQL queries. By default, write
queries require authorization and read-only don't.
Where authorization is required, it is performed by passing an
Authorization: Bearer (password)
HTTP header.
You can change the authorization settings in the configuration.
Endpoints
POST /q
Execute a read/write query.
Body: {"query": "(SQL query)"}
Headers:
Authorization
:Bearer (password)
: if authorization is requiredContent-Type
:application/json
: required
Returns:
- 200 OK: if the query is successful
- 400 Bad Request: error executing or planning the query, with the reason in the response body
- 401 Unauthorized: no or invalid password
- 403 Forbidden: tried to write as an anonymous user or using a read-only password
GET /q/(query_or_hash)[.extension]
Conditionally execute a read-only (SELECT
) query if its result has changed.
query_or_hash
: Either a URL-encoded SQL query, or a SHA-256 hash of the raw query. Required.extension
: Optional extension, like.csv
. Ignored.
Headers:
X-Seafowl-Query
: Optional—when the query SHA-256 hash is supplied as the URL path parameter either this header or the GET request body are required. Contains the actual query, which must match the hash after decoding withdecodeURIComponent()
.If-None-Match
: ETag denoting the query result cached by the client. Optional.Authorization
:Bearer (password)
: if authorization is required. This endpoint abides by the read access config setting only, since it doesn't support writes. Optional.
Body: {"query": "(SQL query)"}
. Optional. Must match the SHA-256 hash.
Either the request body or the X-Seafowl-Query
header are required when the
query hash is supplied as the URL path parameter.
Returns:
- 200 OK: If no ETag has been passed or the passed ETag doesn't match the
current ETag, generated from the latest versions of all tables involved in the
query: the query result with a header
ETag: [current ETag]
. - 301 Not Modified response: if the ETag matches the current version.
- 400 Bad Request: error executing or planning the query, with the reason in the response body, or a mismatch between the query SHA and the SHA of the query body
- 401 Unauthorized: cached read-only endpoint is disabled because reads require a password
POST /upload/(schema_name)/(table_name)
Upload a CSV/Parquet file to a certain table. If the table already exists, attempt to insert the new data, if the schemas match.
Body: A multipart/form-data
body with the following attributes:
schema
: Optional. Instead of Seafowl inferring the schema automatically, allows the user to provide an explicit JSON representation of the Arrow columnar data. Applicable only for CSV uploads.has_headers
: Optional. Whether an explicit schema is passed throughschema
or one is being referred, by default it is assumed that the headers are present, to denote otherwise set to false (has_headers=false
). Applicable only for CSV uploads.data
: the file that's being uploaded
Headers:
Authorization
:Bearer (password)
: if authorization is required
Returns:
- 200 OK: successful upload
- 400 Bad Request: missing or invalid body or schema
- 401 Unauthorized: no or invalid password
- 403 Forbidden: tried to write as an anonymous user or using a read-only password
OPTIONS (any URL)
CORS pre-flight request (see the MDN).
Response headers:
Access-Control-Allow-Origin
: same value as the inboundOrigin
headerAccess-Control-Allow-Methods
:GET, POST
Access-Control-Allow-Headers
:X-Seafowl-Query, Authorization, Content-Type
Response Headers
Seafowl returns a variety of headers. Let's take a look at a simple query:
curl -i -H "Content-Type: application/json" \
-X POST "http://localhost:8080/q" -d@- <<EOF
{"query": "SELECT 1"}
EOF
HTTP/1.1 200 OK
content-type: application/json; arrow-schema=%7B%22fields%22%3A%5B%7B%22children%22%3A%5B%5D%2C%22name%22%3A%22Int64%281%29%22%2C%22nullable%22%3Afalse%2C%22type%22%3A%7B%22bitWidth%22%3A64%2C%22isSigned%22%3Atrue%2C%22name%22%3A%22int%22%7D%7D%5D%2C%22metadata%22%3A%7B%7D%7D
x-seafowl-query-time: 6
vary: Authorization, Content-Type, Origin, X-Seafowl-Query
transfer-encoding: chunked
date: Fri, 23 Jun 2023 10:16:04 GMT
{"Int64(1)":1}
x-seafowl-query-time
seeks to measure the total processing time, as delineated by the interval between when Seafowl finished reading the HTTP request body, and when it started writing the HTTP response body.content-type
- at the time of writing, Seafowl returns the HTTP response body in ndjson format aka JSON Lines, so this is set toapplication/json
. After that comes the Arrow schema, URL encoded.The above example decodes into:
{ "fields": [ { "children": [], "name": "Int64(1)", "nullable": false, "type": { "bitWidth": 64, "isSigned": true, "name": "int" } } ], "metadata": {} }
vary
helps browsers more easily cache if the origin changes. More infocache-control
is user-configurable and may be helpful if you front Seafowl with a CDN. More in the docs. At the time of writing defaults tomax-age=43200, public