Thanks to visit codestin.com
Credit goes to github.com

Skip to content
/ sator Public

A tiny HTTP server for accepting authenticated HTML form data, validating it using JSON Schema and saving it to a database

License

Notifications You must be signed in to change notification settings

robb-j/sator

Repository files navigation

sator

Named for Sator

Sator is a tiny HTTP server for accepting authenticated HTML form data, validating it using JSON Schema and saving it to a database.

It is designed to be ran as a container that is configured through environment variables and configuration files.

Configuration

There are two files, /app/config.json and /app/schema.json that configure how the server works.

You can use the /app/config.json file or environment variables to set these values:

name type flag variable fallback
database.url url ~ DATABASE_URL postgres://user:secret@localhost:5432
env string ~ NODE_ENV development
meta.name string ~ APP_NAME sator
meta.version string ~ APP_VERSION 0.0.0
server.grace number ~ SERVER_GRACE 10000
server.hostname string ~ HOSTNAME 127.0.0.1
server.port number ~ PORT 3000
server.url string ~ SELF_URL http://localhost:3000
cors.origins string[] ~ ~ []

Schema

You also mount your /app/schema.json to tell Sator how to validate your HTTP requests. It needs to contain a valid JSON Schema which will applied to any inputs.

A simple schema might look like this. Responses are objects that have a string "name" field and a numeric "age" field

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "name": { "type": "string" },
    "age": { "type": "number" }
  }
}

Currently, only basic JSON schema types are supported. more could be added in the future

So your responses might look like this:

Sator accepts JSON or HTML Form data

{ "name": "The Protagonist", "age": 42 }

You can do more complicated things with unions.

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "anyOf": [
    {
      "type": "object",
      "properties": {
        "type": { "const": "person" },
        "name": { "type": "string" },
        "age": { "type": "number" }
      }
    },
    {
      "type": "object",
      "properties": {
        "type": { "const": "pet" },
        "name": { "type": "string" },
        "kind": { "enum": ["cat", "dog", "rabbit"] }
      }
    }
  ]
}

where responses could be:

{ "type": "person", "name": "The Protagonist", "age": 42 }

or:

{ "type": "pet", "name": "Hugo", "kind": "dog" }

Endpoints

// Check the service is running and get deployment information
const status = await fetch('http://sator.example.com/')

// Check the service health
const healthz = await fetch('http://sator.example.com/healthz')

// Submit a response
const submit = await fetch('http://sator.example.com/responses', {
  method: "POST",
  headers: {
    'Content-Type': 'application/json'
    'Authorization': 'bearer top_secret'
  },
  body: JSON.stringify({})
})

// List responses
const responses = await fetch('http://sator.example.com/responses', {
  headers: { 'Authorization': 'bearer top_secret' }
})

// Check authorization
const authorization = await fetch('http://sator.example.com/me', {
  headers: { 'Authorization': 'bearer top_secret' }
})

Authorization

There are currently two authentication strategies, public and allow_list.

When you submit a response, Sator looks for an Authorization: bearer {token} header, or a sator_token cookie on the request. The value from that is set as the token field in the database.

When set to public any token will be allowed to submit requests,

{
  "authz": { "type": "public" }
}

When set to allow_list only the allowed tokens can be used to create responses.

{
  "authz": {
    "type": "allow_list",
    "allowed_values": ["top_secret"]
  }
}

Database

Sator is designed to work with a Postgres database or write to the local file system.

Use a file: protocol URL to tell Sator the directory you want the file(s) to be written to. By default, it will create a data.ndjson file in that directory and append all responses into it.

The URL should end with a trailing slash, /

grouping

You can group the files based on a value from the response by adding a ?group search parameter onto the file URL. The value is the key you want to group by. Any validated value from the response can be used along with:

  • id — the unique id for the response
  • created_at — the timestamp of the response, in ISO format
  • token — the authenticated token used to created the response

format

There is also a ?format parameter to further refine the grouping, it can be set to:

  • slug — formats the filename in kebab-case
  • daily — trims date-based values into a YYYY-mm-dd
{
  "database": { "url": "file:///home/protagonist/data/" }
}

postgres

Alternatively, you can save files to Postgres by configuring a postgres: URL. You will also need to run the database migrations using the CLI

{
  "database": { "url": "postgres:user:secret@localhost/database" }
}

About

A tiny HTTP server for accepting authenticated HTML form data, validating it using JSON Schema and saving it to a database

Resources

License

Stars

Watchers

Forks

Packages