Farwest Demo

An overview and a demo of the Farwest project

Loïc Hoguin, Nine Nines

What is Farwest?

Erlang/OTP REST framework

HATEOAS

Standards based (whenever possible)

Built on top of cowboy_rest

Building blocks

  • Resource modules
  • URI and URI Templates (RFC 6570)
  • Media types
  • Operations (forms)
  • Metadata

Client libraries

One library per language/platform

Build on top of existing HTTP clients

Don't write a separate client per API

Work done so far

Discovery

  • Link HTTP header (RFC 8288)
  • Links in response bodies
  • URI Templates router, reverse routing
  • Variants (draft)
  • Skeleton Erlang/OTP client library

Generate response bodies

  • Automatic HTML generation
  • Skeleton forms
  • Automatic BED (binary Erlang data) generation

Mod:describe()

  • URI or URI Template
  • Operations
  • Operation/media type pairs (input/output)
  • Links

Configurable operations

  • HTTP method used
  • Semantics (not yet enforced)

Demo

  1. git clone https://github.com/ninenines/farwest_demo
  2. cd farwest_demo
  3. make run
  4. Open http://localhost:8080 in your browser
  5. Use curl -i http://localhost:8080

describe() → #{
    uri ⇒ "/",
    media_types ⇒ #{
        html ⇒ ["text/html"],
        bed ⇒ ["application/x-bed"]
    },
    operations ⇒ #{
        get ⇒ #{output ⇒ [html, bed]}
    }
}.
		

links(Req) →
    {ok, [
        {child, fwd_processes_r},
        {child, fwd_tables_r}
    ], Req}.
		

$ curl -I http://localhost:8080       
HTTP/1.1 200 OK
content-length: 2398
content-type: text/html
date: Mon, 27 Jan 2020 11:56:23 GMT
link: </processes>; rel="child";
    variants-06="accept=(\"text/html\" \"application/x-bed\")",
    </tables>; rel="child"; variants-06="accept=(\"text/html\")"
server: Cowboy
variant-key-06: ("text/html")
variants-06: accept=("text/html" "application/x-bed")
vary: accept
		

get(Req) →
    Info = observer_backend:sys_info(),
    Data = #{
        «"System Version"» ⇒ g(otp_release, Info),
        ...
    },
    {ok, Data, Req}.

to_representation(Req, html, Data) →
    {ok, farwest_html:from_term(Req, Data), Req};
to_representation(Req, bed, Data) →
    {ok, farwest_bed:from_term(Req, Data), Req}.
		

$ curl -I http://localhost:8080/tables
HTTP/1.1 200 OK
content-length: 7052
content-type: text/html
date: Mon, 27 Jan 2020 11:56:10 GMT
farwest-link-templates: </tables/{name}>; rel="child";
    variants-06="accept=(\"text/html\")"
link: </>; rel="parent"; variants-06="accept=
    (\"text/html\" \"application/x-bed\")"
server: Cowboy
		

{'$fw_link', child,
    farwest:link_to(fwd_table_r, #{«"name"» ⇒ TableName}),
    TableName}
		

describe() → #{
    uri ⇒ "/tables/{name}/{key}",
    media_types ⇒ #{
        html ⇒ ["text/html"],
        term ⇒ ["text/plain+erlang-term"]
    },
    operations ⇒ #{
        get ⇒ #{output ⇒ [html]},
        put ⇒ #{input ⇒ [term]},
        delete ⇒ #{}
    }
}.
		

put(Req0=#{bindings := #{name := Name0}}) →
    Name = binary_to_atom(Name0, utf8),
    {ok, Body, Req} = cowboy_req:read_body(Req0),
    {ok, Tuple} = parse_string(
        unicode:characters_to_list(Body) ++ "."),
    ets:delete_object(Name, Tuple),
    ets:insert(Name, Tuple),
    {ok, Req}.
		

delete(Req=#{bindings := #{name := Name0, key := Key0}}) →
    Name = binary_to_atom(Name0, utf8),
    {ok, Key} = parse_string(
        unicode:characters_to_list(Key0) ++ "."),
    ets:delete(Name, Key),
    {ok, Req}.
		

Upcoming work

Improved discovery

Automatic sitemap?

External resources?

Link relation resources?

Better discovery of operations

Cache metadata (etag, cache-control...)

Generate response bodies

Template-based HTML generation

Replace/insert your own templates

Automatic JSON/JSON-LD/... generation

Semantics

Type "objects" first, then their values

Schemas (schema.org or other)

Better forms using schemas

Read data and expand URI Templates

Improved client libraries

More functions

Client-side cache for Gun HTTP client

Non-Erlang client libraries

Thanks

github.com/ninenines/farwest

github.com/ninenines/farwest_demo

Looking for early adopters!