liberated apis in clojureland - paris clojure user group

34
All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved. Liberated APIs in ClojureLand Paris Clojure User Group

Upload: gaylord-mazelier

Post on 15-Jul-2015

2.609 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

Liberated APIs in ClojureLand

Paris Clojure User Group

Page 2: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

Gaylord Mazelier, CTO

Page 3: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

Rationale

Page 4: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

• Why web services?

• How to design a good API?

• Why Clojure?

• Why Liberator?

Page 5: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

The Clojure Web Stack

Page 6: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

Ring

• A low level spec for conforming libraries

• An ecosystem to compose your own stack

• Clojure maps for requests and responses

• Functions for handlers and middleware

Page 7: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

Requests and Responses

• Requests

• :server-port, :server-name,

• :remote-addr,

• :request-method, :uri, :query-string,

• :scheme, :headers and :body

Page 8: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

Requests and Responses

• Responses

• :status (HTTP status code)

• :headers

• :body (String, ISeq, File or InputStream)

Page 9: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

Requests and Responses

(-> (response "Hello World") (content-type "text/plain")) => {:status 200 :headers {"Content-Type" "text/plain"} :body "Hello World"} (redirect "http://example.com") => {:status 302 :headers {"Location" "http://example.com"} :body ""}

Page 10: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

Handlers and Middleware• Handlers

• Do the work of your application

• Just function that takes and returns a map

• Ring request and response

• Middleware

• High-order functions

• Add functionality to handlers

Page 11: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

Handlers and Middleware

(defn what-is-my-ip [request] {:status 200 :headers {"Content-Type" "text/plain"} :body (:remote-addr request)}) (defn wrap-content-type [handler content-type] (fn [request] (let [response (handler request)] (assoc-in response [:headers "Content-Type"] content-type))))

Page 12: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

Adapters and Servers• Adapters

• Connecting a handler to a server

• Abstracting away details of that server

• Standardising to the Ring format

• Servers

• Host an HTTP server as part of your application

• Host your application as a servlet in a container

• Talk over some protocol to a web server outside your JVM

Page 13: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

Page 14: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

Liberator Basics

Page 15: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

Webmachine• Resources

• A set of functions

• Referential transparency

• Small and isolated functions

• HTTP semantics

• A system with conventions

Page 16: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

Resources• Resources

• Ring handlers that adhere to the Ring contract

• resource function or defresource macro

• Developers

• Provide a set of functions

• Parametrised resources

• Base implementation

Page 17: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

Decisions• Decision points for resources implementors

• Resource behaviour

• allowed?, exists?, malformed?, etc.

• Internal decision points

• Override is possible but not useful in general

• accept-exists?, method-put?, etc.

Page 18: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

Decisions

• Context

• Single argument for all functions

• A map that initially contains

• :representation, :request, :response

• Updated by decision and action functions

Page 19: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

Decisions

• Decision functions result

• A boolean value

• Or a vector

• First element as the boolean decision

• Second element as the update to the context

Page 20: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

Actions• For side effects

• Evaluated like decision functions but

• The boolean value has no effect

• The next decision step is constant

• Action functions

• :post!, :put!, :delete!, :patch!

Page 21: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

Handlers• Final step of a request processing

• Must return a representation

• A function for each HTTP status code

• handle-ok for 200 OK

• Redirecting

• Corresponding handlers will set a Location header

• :location key in context or in resource definition

Page 22: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

Representations• Returned by handlers

• Protocol liberator.representation/Representation

• A single method as-response

• Returns a Ring response map

• The most types for response bodies are supported

• Can be represented as text, JSON, Clojure, etc.

Page 23: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

Decision Graph

• Handling a resource

• Executing a set of decisions

• Determining the correct response status code

• Generating the appropriate response

• Decisions are made according to a flowchart

Page 24: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

In Practice

Page 25: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

Content Negotiation

(defn check-content-type "For PUT and POST, check if the content type is valid." [ctx content-types] (if (#{:put :post} (get-in ctx [:request :request-method])) (or (some #{(get-in ctx [:request :headers "content-type"])} content-types) [false {:message "Unsupported Content-Type"}]) true)) (defresource facts :available-media-types #{"application/edn"} :known-content-type? #(check-content-type % ["application/edn"]))

Page 26: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

Malformed Request

(defresource fact [id] :allowed-methods #{:get} :malformed? (fn [_] (if (ObjectId/isValid id) false {:message "Invalid id."})))

Page 27: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

“Say Friend and enter.”(defn friend-auth "Returns a base resource that authenticates using the supplied auth-fn. Authorization failure will trigger Friend's default unauthorized response." [auth-fn] {:authorized? auth-fn}) (defn role-auth "Returns a base resource that authenticates users against the supplied set of roles." [role-input] (friend-auth (comp (roles? role-input) :request))) (defresource facts (role-auth #{:admin}) :handle-ok "This is OK")

Page 28: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

Others

• Logging

• ring.middleware.logger/wrap-with-logger

• Debugging

• liberator.dev/wrap-trace

• See this example

Page 29: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

Demo

Page 30: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

Final Thoughts

Page 31: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

• Benefits

• HTTP semantics

• Productive and adaptable

• Readable resources behaviour

• wrap-trace middleware!

• Most-wanted features (or contributions :)

• Automatic content type negation for error responses

• Swagger integration

• OPTIONS support for self-describing resources

Page 32: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

Page 33: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

Sources

Page 34: Liberated APIs in ClojureLand - Paris Clojure User Group

All Images: Copyright © 2015 ustwo studio Ltd. All rights reserved.

• https://brehaut.net/blog/2011/ring_introduction

• http://www.lispcast.com/parts-of-ring

• https://github.com/basho/webmachine

• http://en.wikipedia.org/wiki/Finite-state_machine

• http://clojure-liberator.github.io/liberator

• https://github.com/Prismatic/schema

• http://12factor.net/logs

• https://github.com/cemerick/friend

• http://zacstewart.com/2012/04/14/http-options-method.html

• https://www.mnot.net/blog/2014/06/07/rfc2616_is_dead

• http://evertpot.com/http-11-updated

• https://scott.mn/2014/01/26/first_thoughts_on_liberator_clojure

• https://github.com/pedestal/pedestal

• https://github.com/Prismatic/fnhouse