Upgrade to Pro — share decks privately, control downloads, hide ads and more …

REST API's: Easier Than You Imagined

REST API's: Easier Than You Imagined

Taffy has changed a fair amount, and for the better, since its release 2.5 years ago. It's also now used in production on Adobe ColdFusion and Railo every day of the year. It's baked into Slatwall, the open source eCommerce plugin for Mura. It's used by an augmented reality iPhone application to send data and photos between phones and servers.

And still, it's the easiest, fastest way to get the job done from a CFML platform; and I'd like to help you get started writing API's today.

This session will teach you the basics of REST, as well as everything you need to know to get started writing REST API's with Taffy. From "what's an HTTP verb?" to Dependency Injection, to Uploading Files, and everywhere in between. We'll also cover adding an API to an existing application because as we all know, starting from scratch is not often a privilege of which we get the pleasure.

Adam Tuttle

May 17, 2013
Tweet

More Decks by Adam Tuttle

Other Decks in Technology

Transcript

  1. Agenda • REST 101 • Creating REST APIs with ColdFusion*

    • Adding an API to an existing app • Best Practices, Patterns, Anti-patterns
  2. Agenda • REST 101 • Creating REST APIs with ColdFusion*

    • Adding an API to an existing app • Best Practices, Patterns, Anti-patterns *Using Taffy
  3. • Created May 2010 • #6 most watched ColdFusion project

    on GitHub • 8+ people contributing • Syntax doesn’t suck I made Taffy
  4. HTTP Verbs GET Read POST Insert PUT Update DELETE Delete

    OPTIONS Allowed Verbs HEAD Headers Only
  5. HTTP Verbs GET Read POST Insert PUT Update DELETE Delete

    OPTIONS Allowed Verbs HEAD Headers Only Safe Unsafe Idempotent
  6. HTTP Status Codes • 2xx = Success • 3xx =

    Redirect • 4xx = Client Error • 5xx = Server Error
  7. Raw Request $ telnet www.google.com 80 Trying 173.194.73.104... Connected to

    www.google.com. Escape character is '^]'. GET /index.html HTTP/1.1 Host: www.google.com {blank line}
  8. Raw Response HTTP/1.1 200 OK Date: Sat, 11 May 2013

    18:29:45 GMT [...] X-XSS-Protection: 1; mode=block X-Frame-Options: SAMEORIGIN Transfer-Encoding: chunked <!doctype html><html.......... }Response Headers
  9. Raw Request POST /api/v1/tweets HTTP/1.1 Host: twitter.com Content-Type: application/json Accept:

    application/json, */*;q=0.9 User-Agent: MyTwitterApp { “username”: “AdamTuttle”, “tweet”: “Hello, #CFObjective!” } [blank line]
  10. Why I (still) <3 Taffy • Simplest, Most-concise syntax •

    Easily extended (security layer, etc) • Doesn’t require access to CFAdmin • Portable (Railo, CF8+ supported) • Plays fine with any app framework • ONLY Convention-over-Config option (CF10?) • Open Source
  11. Resources • Live in /resources subfolder • Each resource defines

    its own URI • Only implemented verbs are allowed • Collections vs. Members
  12. Tokens & Query Params • Mapped by name to method

    args • Tokens are the same for every method in a resource CFC and always required (otherwise 404) • Query Params are optional; also passed by name
  13. Simple Input component extends=”taffy.core.resource” taffy_uri=”/foo/{fooId}” { function get(fooId, optional string

    city){ //... } } <cfargument name=”city” required=”false” /> /api/index.cfm/foo/17?city=Philadelphia
  14. Simple Input component extends=”taffy.core.resource” taffy_uri=”/foo/{fooId}” { function get(fooId, optional string

    city){ //... } } <cfargument name=”city” required=”false” /> /api/index.cfm/foo/17?city=Philadelphia
  15. Simple Input component extends=”taffy.core.resource” taffy_uri=”/foo/{fooId}” { function get(fooId, optional string

    city){ //... } } <cfargument name=”city” required=”false” /> /api/index.cfm/foo/17?city=Philadelphia
  16. Simple Input component extends=”taffy.core.resource” taffy_uri=”/foo/{fooId}” { function get(fooId, optional string

    city){ //... } } <cfargument name=”city” required=”false” /> /api/index.cfm/foo/17?city=Philadelphia
  17. Simple Input component extends=”taffy.core.resource” taffy_uri=”/foo/{fooId}” { function get(fooId, optional string

    city){ //... } } <cfargument name=”city” required=”false” /> /api/index.cfm/foo/17?city=Philadelphia
  18. Request Body Input Taffy Supports JSON and Form-encoded bodies as

    long as you set the Content-Type header {“foo”:”bar baz”,”baz”:true} foo=bar%20baz&baz=true
  19. Returning Data representationOf method abstracts serialization component extends=”taffy.core.resource” taffy_uri=”/foo” {

    public function get(){ var querySvc = new Query(); //... return representationOf( someQuery ); } }
  20. Returning Data representationOf method abstracts serialization component extends=”taffy.core.resource” taffy_uri=”/foo” {

    public function get(){ var querySvc = new Query(); //... return representationOf( myStruct ); } }
  21. Returning Data representationOf method abstracts serialization component extends=”taffy.core.resource” taffy_uri=”/foo” {

    public function get(){ var querySvc = new Query(); //... return representationOf( myArray ); } }
  22. ColdFusion serializes queries ... abnormally. {"COLUMNS":["COL1","COL2","COL3"], "DATA":[[3,3,true]]} Taffy’s queryToArray() helper

    converts queries to an array of structures [ {"CoL1":3,"col2":3,"col3":true}, {"CoL1":4,"col2":4,"col3":false} ] queryToArray()
  23. Dependency Injection /resources/FooService.cfc /resources/FooCollection.cfc component { function doStuff(){...}; } component

    extends=”taffy.core.resource” ...{ property name=”FooService”; function get(){ local.foo = this.FooService.doStuff(); //... } }
  24. • Custom Token Regex • Intercept requests w/ onTaffyRequest •

    3rd Party Bean Factories • Verb:Method mapping w/ metadata • Custom result serializers • Environment specific config • ETags for result caching • ... much, much, much more
  25. Shared State • Subfolder supported, not required • Enable by

    using the same Application Name • Shared variables* *with great power comes great responsibility