Upload
begriffs
View
3.454
Download
0
Tags:
Embed Size (px)
Citation preview
Design Philosophy
goal: Schema → API
Can we use the declarative information in a
relational db schema to mechanically generate
an HTTP API?
Tables/views → Routes
Always one level deep
WHERE clause → query params
Just simple operators like less, greater,
equality, inequality
Provide more complicated logic as views
Primary key → eq: param(s)
A primary key identifies at most a single row
They can be compound and/or natural
Routes like /foo/1 don’t always suffice
/foo?k1=eq.v1&k2=eq.v2
For instance,
if an employee belongs to a dept
Link: <http://me.com/dept?id=eq:7>; rel="dept"
Foreign keys → header links
Limit, offset → Range headers
HTTP/1.1 206 Partial Content
Accept-Ranges: items
Content-Range: 0-24/100
Range-Unit: items
RFC7233
GET /items HTTP/1.1
Range-Unit: items
Range: 0-24
SQL update → HTTP patch
PATCH /people?age=lt.12
{ "type": "child" }
Updates all the matching ones
SQL insert → HTTP post
POST /items
PUT /items?pk=eq.val
with all fields specified in body
SQL upsert → HTTP put
schema search path → API Version
Use numerical schema names in the db
Set schema search path to mask endpoints and
fall through when desired
GET /foo HTTP/1.1
Accept: application/vnd.me.com+format; version=n
DB Roles → OAuth
Web server authenticates you
then connects as your user to db
DB authorizes your (hence server) actions
Column constraints → OPTIONS
We can pipe the options output into a client
side “Faker” to mock server responses for the
client test suite.
PG stats collector → cache headers
The access and modification patterns in a table
can provide a heuristic for http caching headers
Perhaps a special view could allow overriding
etags, max-age, etc for each table via a sql
expression
EXPLAIN → HTTP 413
The server can examine the query plan and
preemptively forbid inefficient requests
Like large seq scans or nested join loops
Deployment is easy
For instance on Heroku create a buildpack that
installs the server binary
Then push new migrations and run them. The
only way to update your api server is through
migrations.
Use robust migration tool
github.com / theory / squitch
• Follows a git-inspired workflow
• Models dependencies as a graph, not a line
• TDD at the SQL level!
• No conflicts between branches with git union merge strategy (unlike schema.rb)
Efficiency!
This can be much
faster than Rails
Efficiency! Use a fast language.
The web server itself doesn’t change so we
don’t need the convenience of a scripting
language.
Compile it once for your platform.
I’m using the Warp server on Haskell
Removing imperative cruft
Processing that happens in Ruby models is
glacially slow compared with tuned C inside
postgres.
Generate JSON inside Postgres
Dockyard measured that Postgres’ internal
JSON generation was 2X/10X faster than
ActiveRecord Serializers for small data and
160X faster for large data.
github.com/begriffs/postgrest
github.com/begriffs/postgrest-heroku
github.com/begriffs/postgrest-example