Skip to content

Latest commit

 

History

History
128 lines (97 loc) · 4.79 KB

File metadata and controls

128 lines (97 loc) · 4.79 KB

Binary Data

JmpAPI can receive binary request bodies (raw or multipart), store and read binary BLOBs in the database, and return raw binary responses.

Binary values do not live in the JSON args namespace — JSON has no byte type. They are exposed through two interpolation roots, {body} and {files.*}, which may be used only where binary is meaningful: bound into a SQL query, passed to an exec as a temporary file, or written back as the response. Their byte content is never interpolated into a string.

Receiving a raw body

A non-multipart request body is available as {body}:

Ref Value
{body} the raw request body (bytes)
{body.size} length in bytes
{body.type} the request Content-Type
/avatar:
  put:
    body: {max-size: 1MB, type: image/*}
    sql: CALL SetAvatar({session.user}, {body}, {body.type})

The optional body: block validates the body before the handler runs (see Validation). Without it, {body} is still available whenever a request carries a body.

Receiving multipart uploads

A multipart/form-data request is split by each part's form-field name:

  • File parts (those with a filename) are exposed under {files.<name>}.
  • Plain fields (no filename) fold into the normal {args.*} namespace and validate like any other arg (see args.md).
Ref Value
{files.<name>} the part's bytes
{files.<name>.filename} client-supplied filename
{files.<name>.type} the part's Content-Type
{files.<name>.size} length in bytes
/photos:
  post:
    args:
      caption: {max: 200}             # a plain text field of the form
    files:
      photo: {required: true, max-size: 5MB, type: [image/png, image/jpeg]}
    sql: >
      CALL AddPhoto({session.user}, {args.caption}, {files.photo},
        {files.photo.filename}, {files.photo.type})

Storing blobs

A binary reference used in a query — {body} or {files.<name>} — binds its bytes as a statement parameter, exactly like every other ref (see sql.md). Binding is binary-safe (NUL bytes and arbitrary content are preserved) at any size.

sql: CALL StoreImage({args.id}, {files.image})

Like any ref, a binary ref must stand alone as a whole value — embedding it in a string literal ('x-{body}') is an error. A rendition that may be absent binds NULL with {~files.<name>}.

Binary in exec

An exec step exchanges binary with the process through temporary files: a binary ref in its input: is written to a file and the path is sent in the envelope, and files the process returns become new {files.<name>} values — storable, transformable, and servable like any upload. See Temporary files.

Returning a blob

return: binary writes a single value from the query result as the raw response body: the first column of the first row.

/image/{id}:
  get:
    args: {id: {type: u64}}
    sql:  CALL GetImage({args.id})
    return: binary
    content-type: image/png

The response Content-Type is taken from, in order:

  1. the content-type key — a literal or an interpolated {ref}; else
  2. a second selected column, if the query returns one; else
  3. application/octet-stream.

If the query returns no row, the response is 404.

Any binary value — a captured return: binary result or an exec-returned file — can also be served directly with reply:, e.g. reply: '{files.thumb}'.

Blobs are not emitted by the JSON return types (dict, list, …) — a BLOB column there would be corrupted by JSON string escaping. Select a blob only with return: binary.

Static files and compiled-in assets are served by the file and resource handlers instead — see handlers.md.

Validation

body: and each entry under files: accept:

Key Effect
required Reject with 400 if the body/part is absent.
max-size Maximum byte length (e.g. 5MB); larger → 413.
type Allowed Content-Type: a string, a list, or a * glob (e.g. image/*); mismatch → 415.
help Description for the OpenAPI spec.

Declared body:/files: also appear in the generated OpenAPI spec as the request body (application/octet-stream or multipart/form-data).