SlideShare a Scribd company logo
API MANAGEMENT WITH TAFFY 

AND API BLUEPRINT
KAI KOENIG (@AGENTK)
AGENDA
▸ What is Taffy?
▸ REST in a nutshell
▸ But is it “RESTful ENOUGH”?
▸ Taffy setup and basic flow
▸ Advanced configuration
▸ API Blueprint and other tools
WHAT IS TAFFY?
WHAT IS TAFFY?
TAFFY
▸ TLDR version: Taffy is a framework to build REST-based APIs in CFML
▸ Developed by Adam Tuttle
▸ Currently in version 3.1, incepted around 2011 (MIT license)
▸ Very stable, very powerful
▸ Allows the creation of REST-based APIs in CFML independent of any vendor
implementation - works with Lucee and ACF
▸ Can be integrated with other frameworks
WHAT IS TAFFY?
WHY TAFFY?
“But hey, both Lucee and Adobe CF have their own implementation of REST-
API handling and it’s SO EASY to use and it has SELF-DOCUMENTATION!
That’s great, ey?”
▸ At first glance it might seem like a great idea for getting started. But:
▸ Various issues (created URL structures, JSON handling, clunky syntax)
▸ Significantly lock-in to a vendor’s implementation
▸ Overall developer-unfriendly approaches
WHAT IS TAFFY?
BENEFITS OF TAFFY
▸ This is not a talk about the deficiencies of REST in ACF or Lucee
▸ This is why Taffy is great:
▸ Developer-friendly and easy to get started with
▸ Backwards-compatible to ACF 8
▸ Convention over configuration
▸ Hardly any boilerplate code
REST IN A NUTSHELL
https://www.flickr.com/photos/kikasz/2891113802/
REST IN A NUTSHELL
WHAT IS REST?
▸ REpresentational State Transfer - a method to communicate over a network
▸ Mostly used over HTTP, technically protocol-independent
▸ 2 phases:
▸ Request - noun, verb, MIME type, headers, data
▸ Response - status code, status text, headers, data
REST IN A NUTSHELL
THE REQUEST (I)
▸ Nouns - identifier of the data we want to work with, e.g. /users or /users/232
▸ Main verbs:
▸ POST: creating a new record (unsafe)
▸ PUT: updating existing record (idempotent)
▸ GET: retrieving existing record (safe)
▸ DELETE: deleting record (idempotent)
REST IN A NUTSHELL
THE REQUEST (II)
▸ Less commonly used verbs:
▸ HEAD: similar to GET, but only returns headers (safe)
▸ OPTIONS: used to check which verbs are available (safe)
▸ PATCH: similar to PUT, updating individual properties (idempotent)
▸ MIME type:
▸ Client and API server agree on the data types for exchange, e.g. text/html,
application/xml etc
REST IN A NUTSHELL
THE REQUEST (III)
▸ Headers - supply metadata with the request (Accept, Content-Type)
▸ Data - the data sent from the client to the server
▸ Can conceptually be of any format
▸ Most common: JSON
REST IN A NUTSHELL
THE RESPONSE
▸ Status code & Status text:
▸ “200 OK”
▸ “404 Not Found”
▸ “500 Server Error” …
▸ There are a lot more specific status codes, such as 201, 301, 302, 400, 401
etc.
▸ Headers and Data
REST IN A NUTSHELL
WHY DO PEOPLE LIKE AND USE REST?
▸ Works naturally with the HTTP protocol
▸ Other alternatives:
▸ SOAP-XML: very enterprise-y, bloated and complex
▸ XML-RPC: similar to REST, but ignores the power of the verb
RESTFUL ENOUGH?
https://www.flickr.com/photos/kikasz/2891113802/https://xkcd.com/386/
BUT IS IT RESTFUL ENOUGH?
THE REALITY IS MORE COMPLEX
▸ Roy Fielding’s 2000 dissertation about what we today know as REST
▸ Followed up by a series of blog posts from ~2008 about HATEOAS
(Hypermedia As The Engine Of Application State)
▸ prescribing additional requirements and behaviours
▸ often considered as ideal, but impractical in a lot of ways
▸ Leads to a lot of discussion what REST is and how one has to use it
BUT IS IT RESTFUL ENOUGH?
MORE MATURE?
▸ Plain JSON





▸ HATEOAS
{
"name" : “iPhone 7"
}
{
"name": “iPhone 7",
"links": [ {
"rel": "self",
"href": "http://localhost:8080/product/1"
} ]
}
BUT IS IT RESTFUL ENOUGH?
HATEOAS
{
"content": [ {
"price": 499.00,
"name": "iPad",
"links": [ {
"rel": "self",
"href": "http://localhost:8080/product/1"
} ],
"attributes": {
"connector": "socket"
}
}, {
"price": 49.00,
"name": "Dock",
"links": [ {
"rel": "self",
"href": "http://localhost:8080/product/3"
} ],
"attributes": {
"connector": "plug"
}
} ],
"links": [ {
"rel": "product.search",
"href": "http://localhost:8080/product/search"
} ]
}
BUT IS IT RESTFUL ENOUGH?
RICHARDSON MATURITY LEVEL
http://martinfowler.com/articles/richardsonMaturityModel.html
TAFFY SETUP AND
BASIC FLOW
https://www.flickr.com/photos/joanna_young/
4515399787/
TAFFY SETUP AND BASIC FLOW
INSTALLATION
▸ Download .zip-file from Github or taffy.io
▸ Installation options:
▸ Global mapping /taffy
▸ /taffy physically in webroot
▸ Installation in sub-directory of site (needs application-specific mappings)
TAFFY SETUP AND BASIC FLOW
DRIVEN BY APPLICATION.CFC
▸ Extends taffy.core.api
▸ Needs to call onApplicationStart() and
onRequestStart() on the parent CFC
▸ Earlier versions of Taffy had their own
Application.cfc events - it was
recommended to actually not implement
onApplicationStart() etc
▸ That’s gone since Taffy 2.0
component extends="taffy.core.api"
{
this.name = "TaffyDemo";
function onApplicationStart()
{
application.productList = [
{ "id":1, "name":"iPhone 7" },
{ "id":2, "name":"iPhone 7+" },
{ "id":3, "name":"iPad Pro 9.7inch" }
];
return super.onApplicationStart();
}
function onRequestStart()
{
return super.onRequestStart();
}
}
TAFFY SETUP AND BASIC FLOW
CONVENTION OVER CONFIGURATION
▸ Taffy tries to NOT be in your way
▸ Examples:
▸ Default function names for resources are get(), post(), put(), delete()
▸ Looks for resources in a /resources directory
▸ Lots of things are just fine and work out of the box naturally because of
sensible conventions
TAFFY SETUP AND BASIC FLOW
MINIMAL LAYOUT
TAFFY SETUP AND BASIC FLOW
RESOURCES (I)
▸ Extend taffy.core.resource
▸ Live in the /resources directory or a /resources mapping
▸ Can be changed - requires dropping the default bean factory
▸ Good practice:
▸ Have a CFC for a “thing” and for a “collection of things” each
▸ My convention: “SomeThing” and “SomeThingCollection”
▸ A resource should at least implement one verb function
TAFFY SETUP AND BASIC FLOW
RESOURCES (II)
▸ taffy_uri defines the public URL of your resource
▸ representationOf() triggers the default serialiser
▸ withStatus() sets the HTTP status of the response (defaults to “200 OK”)
component extends="taffy.core.resource" taffy_uri="/product"
{
public function get(){
return representationOf(application.productList).withStatus(200);
}
}
TAFFY SETUP AND BASIC FLOW
RESOURCES (III)
▸ Passing {productId} token into the resource’s URL
▸ Returning 404 if there’s no record found
component extends="taffy.core.resource" taffy_uri="/product/{productId}"
{
public function get(numeric productId){
for (var product in application.productList) {
if (product["id"] == arguments.productId) {
return representationOf(product).withStatus(200, "OK");
}
}
return noData().withStatus(404, "Not Found");
}
}
TAFFY SETUP AND BASIC FLOW
RESOURCES (IV)
▸ If a verb is not implemented in a resource, Taffy will return “405 Not Allowed”
▸ Tokens will automatically become part of the arguments scope
▸ Tokens support regular expressions: /product/{pId:d{4}} - /product/{pId:[A-Za-z]+}
▸ Query string parameters will ALSO automatically become part of the arguments scope
▸ Use .noData() if the intention is to not return data
▸ Similar to .withStatus(…), it’s possible to chain .withHeaders(…) to the return
statement
TAFFY SETUP AND BASIC FLOW
TAFFY DASHBOARD
TAFFY SETUP AND BASIC FLOW
TAFFY DASHBOARD
▸ Dashboard allows to:
▸ execute requests (incl. Query Params, Headers and Basic Auth)
▸ inspect the response
▸ see a limited amount of documentation
▸ Should (usually) be switched off in production
▸ Default: caches API, needs explicit reloads
TAFFY SETUP AND BASIC FLOW
CHANGING DATA - WHERE TO PUT POST?
▸ If the POST method was in Product.cfc - we’d have an issue.
▸ The URL route requires us to use /product/{productId}
▸ POST therefore has to life in ProductCollection.cfc
▸ PUT however (updating existing data) can happily go into Product.cfc
▸ URL matching: /product/search will match before /product/{productId}
TAFFY SETUP AND BASIC FLOW
GOOD PRACTICES FOR PUT AND POST
▸ If you created a record with POST:
▸ return “201 Created” with the created data
▸ potentially return x-inserted-id in the header
▸ If you updated a record with PUT:
▸ return “200 OK” with the updated data
▸ if the record to be updated didn’t exist, create it (see above)
ADVANCED TASKS AND
CONFIG
ADVANCED TASKS AND CONFIG
BREAKING AWAY FROM THE CONVENTIONS
▸ Metadata:
▸ Annotate functions to be triggered by a specific verb: taffy_verb=“<VERB>”
▸ Necessary for extended verbs like OPTIONS, HEAD, PATCH. Optional for
standard verbs.
▸ There’s more metadata in serialisers (later)
ADVANCED TASKS AND CONFIG
BREAKING AWAY FROM THE CONVENTIONS
▸ Configuration: variables.framework struct in Taffy’s Application.cfc
▸ reloadKey/reloadPassword vs. reloadOnEveryRequest
▸ serializer/deserializer (later)
▸ disableDashboard
▸ jsonp/allowCrossDomain
▸ beanFactory - allows hooking into Coldspring, DI/1 etc…
ADVANCED TASKS AND CONFIG
AUTHENTICATION AND SECURITY
▸ Firstly - what do you want to achieve?
▸ Requiring an API Token?
▸ Fine-grain security?
▸ oAuth
▸ HTTP Basic Auth
▸ SSL
ADVANCED TASKS AND CONFIG
API TOKEN (I)
▸ Best place to start is onTaffyRequest(…)
▸ Return true to continue processing the request
▸ Return a representation object to abort the request
▸ Two common options for passing token:
▸ URI parameters and/or as part of the data
▸ In the header
ADVANCED TASKS AND CONFIG
API TOKEN (II)
function onTaffyRequest(verb, cfc, requestArguments, mimeExt,
headers, methodMetadata, matchedURI) {
if (not structKeyExists(arguments.requestArguments, "apiKey") ||
!Len(arguments.requestArguments["apiKey"])) {
return noData().withStatus(401, "Unauthorized");
}
if (!arrayFind(application.validAPIKeys,
arguments.requestArguments["apiKey"])) {
return noData().withStatus(403, "Forbidden");
}
return true;
}
ADVANCED TASKS AND CONFIG
CUSTOM SERIALISERS (I)
▸ Default serialiser is JSON (CFML-server built-in)
▸ Extend from taffy.core.baseRepresentation
▸ Implement getAsX functions
▸ getAsXML, getAsJSON, getAsYML etc
ADVANCED TASKS AND CONFIG
CUSTOM SERIALISERS (II)
component extends="taffy.core.baseSerializer"
{
variables.anythingToXML = application.anythingToXML;
variables.jsonUtil = application.jsonUtil;
function getAsXML() output="false" taffy_mime="application/xml" taffy_default="false" {
return variables.anythingToXML.toXml(variables.data);
}
function getAsJSON() output="false" taffy_mime="application/json" taffy_default="true" {
return variables.jsonUtil.serialize(variables.data);
}
}
ADVANCED TASKS AND CONFIG
RATE LIMITS
▸ In a nutshell:
▸ manage access log (api key & time) in DB or key/value storage
▸ onTaffyRequest logs requests and check if limits are exceeded
▸ if not exceeded, process incoming request
▸ if exceeded, return status code “429 Too Many Requests”
ADVANCED TASKS AND CONFIG
API VERSIONING
▸ Multiple schools of thought:
▸ URI vs header
▸ Make sure you version from day 0!
▸ I tend to use /v1/product, /v2/product etc.
▸ Maps nicely on directory structures in /resources
▸ Update version when breaking compatibility
▸ Consider SemVer (Semantic Versioning) if your API is changing a lot
API BLUEPRINT AND
OTHER TOOLS
https://www.flickr.com/photos/cardoso/2196726835/
API BLUEPRINT
WHAT IS IT?
▸ Description and specification language for web APIs (http://apiblueprint.org)
▸ From Apiary.io - but can be used independently from that
▸ Language spec: https://github.com/apiaryio/api-blueprint
▸ Offers platform-neutral documentation and additional tooling
▸ Aglio
▸ API-Mock
API BLUEPRINT
DOCUMENTATION WITH AGLIO
▸ Very simple markup language
▸ npm install -g aglio (https://www.npmjs.com/package/aglio)
▸ aglio -i documentation.md -o documentation.html
▸ MD structure:
▸ # Group
▸ ## Resource
▸ ### Action
API BLUEPRINT
MOCK SERVER WITH API-MOCK
▸ Creates a mock server for your API (https://github.com/localmed/api-mock)
▸ npm install -g api-mock
▸ api-mock ./documentation.md
▸ Defaults to port 3000
API BLUEPRINT
PAW
▸ REST API test and management tool on OS X
▸ Recording/Playback/Testing etc
▸ Has API Blueprint support through extensions
FINAL THOUGHTS
https://www.flickr.com/photos/brickset/16099265973/
FINAL THOUGHTS
WHAT DID WE COVER?
▸ Taffy - what is it?
▸ How to setup and the foundations
▸ Discussed some advanced topics in more detail
▸ High-level overview of API Blueprint
FINAL THOUGHTS
GET IN TOUCH
Kai Koenig
Email: kai@ventego-creative.co.nz
Twitter: @AgentK

More Related Content

Viewers also liked

Viewers also liked (13)

Divusi dan inovasi reni
Divusi dan inovasi reniDivusi dan inovasi reni
Divusi dan inovasi reni
 
Erik
ErikErik
Erik
 
Extinción de los Actos Administrativos en Venezuela
Extinción de los Actos Administrativos en VenezuelaExtinción de los Actos Administrativos en Venezuela
Extinción de los Actos Administrativos en Venezuela
 
Entrega taller
Entrega tallerEntrega taller
Entrega taller
 
Avances tecnologicos
Avances tecnologicosAvances tecnologicos
Avances tecnologicos
 
Lección 3 - Doctrina y vida de la Iglesia
Lección 3 - Doctrina y vida de la IglesiaLección 3 - Doctrina y vida de la Iglesia
Lección 3 - Doctrina y vida de la Iglesia
 
Acct20-Chapter12
Acct20-Chapter12Acct20-Chapter12
Acct20-Chapter12
 
AdWords Academy 谷歌广告节假日专题-电商欧美市场营销策略
AdWords Academy 谷歌广告节假日专题-电商欧美市场营销策略AdWords Academy 谷歌广告节假日专题-电商欧美市场营销策略
AdWords Academy 谷歌广告节假日专题-电商欧美市场营销策略
 
谷歌广告学院 AdWords APP 广告面面观
谷歌广告学院 AdWords APP 广告面面观谷歌广告学院 AdWords APP 广告面面观
谷歌广告学院 AdWords APP 广告面面观
 
API Athens Meetup - API standards 22.03.2016
API Athens Meetup - API standards 22.03.2016API Athens Meetup - API standards 22.03.2016
API Athens Meetup - API standards 22.03.2016
 
Introduction to philosophy
Introduction to philosophyIntroduction to philosophy
Introduction to philosophy
 
Kamailio World 2016: Update your SIP!
Kamailio World 2016: Update your SIP!Kamailio World 2016: Update your SIP!
Kamailio World 2016: Update your SIP!
 
Mi estudio de caso carlos moreno
Mi estudio de caso carlos morenoMi estudio de caso carlos moreno
Mi estudio de caso carlos moreno
 

Similar to API management with Taffy and API Blueprint

12 core technologies you should learn, love, and hate to be a 'real' technocrat
12 core technologies you should learn, love, and hate to be a 'real' technocrat12 core technologies you should learn, love, and hate to be a 'real' technocrat
12 core technologies you should learn, love, and hate to be a 'real' technocrat
Jonathan Linowes
 

Similar to API management with Taffy and API Blueprint (20)

REST with Eve and Python
REST with Eve and PythonREST with Eve and Python
REST with Eve and Python
 
Faster PHP apps using Queues and Workers
Faster PHP apps using Queues and WorkersFaster PHP apps using Queues and Workers
Faster PHP apps using Queues and Workers
 
12 core technologies you should learn, love, and hate to be a 'real' technocrat
12 core technologies you should learn, love, and hate to be a 'real' technocrat12 core technologies you should learn, love, and hate to be a 'real' technocrat
12 core technologies you should learn, love, and hate to be a 'real' technocrat
 
Python tools for testing web services over HTTP
Python tools for testing web services over HTTPPython tools for testing web services over HTTP
Python tools for testing web services over HTTP
 
Elegant Rest Design Webinar
Elegant Rest Design WebinarElegant Rest Design Webinar
Elegant Rest Design Webinar
 
Big Data Web applications for Interactive Hadoop by ENRICO BERTI at Big Data...
 Big Data Web applications for Interactive Hadoop by ENRICO BERTI at Big Data... Big Data Web applications for Interactive Hadoop by ENRICO BERTI at Big Data...
Big Data Web applications for Interactive Hadoop by ENRICO BERTI at Big Data...
 
Introduction to REST and Hypermedia
Introduction to REST and HypermediaIntroduction to REST and Hypermedia
Introduction to REST and Hypermedia
 
Hue: Big Data Web applications for Interactive Hadoop at Big Data Spain 2014
Hue: Big Data Web applications for Interactive Hadoop at Big Data Spain 2014Hue: Big Data Web applications for Interactive Hadoop at Big Data Spain 2014
Hue: Big Data Web applications for Interactive Hadoop at Big Data Spain 2014
 
Power of Simplicity in FW/1
Power of Simplicity in FW/1Power of Simplicity in FW/1
Power of Simplicity in FW/1
 
Play framework productivity formula
Play framework   productivity formula Play framework   productivity formula
Play framework productivity formula
 
Room with a Vue - Introduction to Vue.js
Room with a Vue - Introduction to Vue.jsRoom with a Vue - Introduction to Vue.js
Room with a Vue - Introduction to Vue.js
 
Rapid Application Development with SwiftUI and Firebase
Rapid Application Development with SwiftUI and FirebaseRapid Application Development with SwiftUI and Firebase
Rapid Application Development with SwiftUI and Firebase
 
Best Practices for Architecting a Pragmatic Web API.
Best Practices for Architecting a Pragmatic Web API.Best Practices for Architecting a Pragmatic Web API.
Best Practices for Architecting a Pragmatic Web API.
 
Monitoring OSGi Applications with the Web Console
Monitoring OSGi Applications with the Web ConsoleMonitoring OSGi Applications with the Web Console
Monitoring OSGi Applications with the Web Console
 
Monitoring OSGi Applications with the Web Console
Monitoring OSGi Applications with the Web ConsoleMonitoring OSGi Applications with the Web Console
Monitoring OSGi Applications with the Web Console
 
Monitoring OSGi Applications with the Web Console - Carsten Ziegeler
Monitoring OSGi Applications with the Web Console - Carsten ZiegelerMonitoring OSGi Applications with the Web Console - Carsten Ziegeler
Monitoring OSGi Applications with the Web Console - Carsten Ziegeler
 
WebGUI Developers Workshop
WebGUI Developers WorkshopWebGUI Developers Workshop
WebGUI Developers Workshop
 
CodeIgniter PHP MVC Framework
CodeIgniter PHP MVC FrameworkCodeIgniter PHP MVC Framework
CodeIgniter PHP MVC Framework
 
The Big Picture and How to Get Started
The Big Picture and How to Get StartedThe Big Picture and How to Get Started
The Big Picture and How to Get Started
 
Building a Cloud Native Stack with EMR Spark, Alluxio, and S3
Building a Cloud Native Stack with EMR Spark, Alluxio, and S3Building a Cloud Native Stack with EMR Spark, Alluxio, and S3
Building a Cloud Native Stack with EMR Spark, Alluxio, and S3
 

More from Kai Koenig

AngularJS for designers and developers
AngularJS for designers and developersAngularJS for designers and developers
AngularJS for designers and developers
Kai Koenig
 

More from Kai Koenig (20)

Why a whole country skipped a day - Fun with Timezones
Why a whole country skipped a day - Fun with Timezones Why a whole country skipped a day - Fun with Timezones
Why a whole country skipped a day - Fun with Timezones
 
Android 103 - Firebase and Architecture Components
Android 103 - Firebase and Architecture ComponentsAndroid 103 - Firebase and Architecture Components
Android 103 - Firebase and Architecture Components
 
Android 102 - Flow, Layouts and other things
Android 102 - Flow, Layouts and other thingsAndroid 102 - Flow, Layouts and other things
Android 102 - Flow, Layouts and other things
 
Android 101 - Building a simple app with Kotlin in 90 minutes
Android 101 - Building a simple app with Kotlin in 90 minutesAndroid 101 - Building a simple app with Kotlin in 90 minutes
Android 101 - Building a simple app with Kotlin in 90 minutes
 
Kotlin Coroutines and Android sitting in a tree - 2018 version
Kotlin Coroutines and Android sitting in a tree - 2018 versionKotlin Coroutines and Android sitting in a tree - 2018 version
Kotlin Coroutines and Android sitting in a tree - 2018 version
 
Kotlin Coroutines and Android sitting in a tree
Kotlin Coroutines and Android sitting in a treeKotlin Coroutines and Android sitting in a tree
Kotlin Coroutines and Android sitting in a tree
 
Improving your CFML code quality
Improving your CFML code qualityImproving your CFML code quality
Improving your CFML code quality
 
Summer of Tech 2017 - Kotlin/Android bootcamp
Summer of Tech 2017 - Kotlin/Android bootcampSummer of Tech 2017 - Kotlin/Android bootcamp
Summer of Tech 2017 - Kotlin/Android bootcamp
 
2017: Kotlin - now more than ever
2017: Kotlin - now more than ever2017: Kotlin - now more than ever
2017: Kotlin - now more than ever
 
Anko - The Ultimate Ninja of Kotlin Libraries?
Anko - The Ultimate Ninja of Kotlin Libraries?Anko - The Ultimate Ninja of Kotlin Libraries?
Anko - The Ultimate Ninja of Kotlin Libraries?
 
Coding for Android on steroids with Kotlin
Coding for Android on steroids with KotlinCoding for Android on steroids with Kotlin
Coding for Android on steroids with Kotlin
 
Little Helpers for Android Development with Kotlin
Little Helpers for Android Development with KotlinLittle Helpers for Android Development with Kotlin
Little Helpers for Android Development with Kotlin
 
Introduction to Data Mining
Introduction to Data MiningIntroduction to Data Mining
Introduction to Data Mining
 
Garbage First and you
Garbage First and youGarbage First and you
Garbage First and you
 
Real World Lessons in jQuery Mobile
Real World Lessons in jQuery MobileReal World Lessons in jQuery Mobile
Real World Lessons in jQuery Mobile
 
The JVM is your friend
The JVM is your friendThe JVM is your friend
The JVM is your friend
 
Regular Expressions 101
Regular Expressions 101Regular Expressions 101
Regular Expressions 101
 
There's a time and a place
There's a time and a placeThere's a time and a place
There's a time and a place
 
Clojure - an introduction (and some CFML)
Clojure - an introduction (and some CFML)Clojure - an introduction (and some CFML)
Clojure - an introduction (and some CFML)
 
AngularJS for designers and developers
AngularJS for designers and developersAngularJS for designers and developers
AngularJS for designers and developers
 

Recently uploaded

Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
Globus
 

Recently uploaded (20)

Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
 
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBrokerSOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBroker
 
De mooiste recreatieve routes ontdekken met RouteYou en FME
De mooiste recreatieve routes ontdekken met RouteYou en FMEDe mooiste recreatieve routes ontdekken met RouteYou en FME
De mooiste recreatieve routes ontdekken met RouteYou en FME
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
 
Facemoji Keyboard released its 2023 State of Emoji report, outlining the most...
Facemoji Keyboard released its 2023 State of Emoji report, outlining the most...Facemoji Keyboard released its 2023 State of Emoji report, outlining the most...
Facemoji Keyboard released its 2023 State of Emoji report, outlining the most...
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
 
Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024
 
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024
 
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
 
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume MontevideoVitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume Montevideo
 
Large Language Models and the End of Programming
Large Language Models and the End of ProgrammingLarge Language Models and the End of Programming
Large Language Models and the End of Programming
 
Agnieszka Andrzejewska - BIM School Course in Kraków
Agnieszka Andrzejewska - BIM School Course in KrakówAgnieszka Andrzejewska - BIM School Course in Kraków
Agnieszka Andrzejewska - BIM School Course in Kraków
 
AI/ML Infra Meetup | ML explainability in Michelangelo
AI/ML Infra Meetup | ML explainability in MichelangeloAI/ML Infra Meetup | ML explainability in Michelangelo
AI/ML Infra Meetup | ML explainability in Michelangelo
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
 
Studiovity film pre-production and screenwriting software
Studiovity film pre-production and screenwriting softwareStudiovity film pre-production and screenwriting software
Studiovity film pre-production and screenwriting software
 
top nidhi software solution freedownload
top nidhi software solution freedownloadtop nidhi software solution freedownload
top nidhi software solution freedownload
 

API management with Taffy and API Blueprint

  • 1. API MANAGEMENT WITH TAFFY 
 AND API BLUEPRINT KAI KOENIG (@AGENTK)
  • 2. AGENDA ▸ What is Taffy? ▸ REST in a nutshell ▸ But is it “RESTful ENOUGH”? ▸ Taffy setup and basic flow ▸ Advanced configuration ▸ API Blueprint and other tools
  • 4. WHAT IS TAFFY? TAFFY ▸ TLDR version: Taffy is a framework to build REST-based APIs in CFML ▸ Developed by Adam Tuttle ▸ Currently in version 3.1, incepted around 2011 (MIT license) ▸ Very stable, very powerful ▸ Allows the creation of REST-based APIs in CFML independent of any vendor implementation - works with Lucee and ACF ▸ Can be integrated with other frameworks
  • 5. WHAT IS TAFFY? WHY TAFFY? “But hey, both Lucee and Adobe CF have their own implementation of REST- API handling and it’s SO EASY to use and it has SELF-DOCUMENTATION! That’s great, ey?” ▸ At first glance it might seem like a great idea for getting started. But: ▸ Various issues (created URL structures, JSON handling, clunky syntax) ▸ Significantly lock-in to a vendor’s implementation ▸ Overall developer-unfriendly approaches
  • 6. WHAT IS TAFFY? BENEFITS OF TAFFY ▸ This is not a talk about the deficiencies of REST in ACF or Lucee ▸ This is why Taffy is great: ▸ Developer-friendly and easy to get started with ▸ Backwards-compatible to ACF 8 ▸ Convention over configuration ▸ Hardly any boilerplate code
  • 7. REST IN A NUTSHELL https://www.flickr.com/photos/kikasz/2891113802/
  • 8. REST IN A NUTSHELL WHAT IS REST? ▸ REpresentational State Transfer - a method to communicate over a network ▸ Mostly used over HTTP, technically protocol-independent ▸ 2 phases: ▸ Request - noun, verb, MIME type, headers, data ▸ Response - status code, status text, headers, data
  • 9. REST IN A NUTSHELL THE REQUEST (I) ▸ Nouns - identifier of the data we want to work with, e.g. /users or /users/232 ▸ Main verbs: ▸ POST: creating a new record (unsafe) ▸ PUT: updating existing record (idempotent) ▸ GET: retrieving existing record (safe) ▸ DELETE: deleting record (idempotent)
  • 10. REST IN A NUTSHELL THE REQUEST (II) ▸ Less commonly used verbs: ▸ HEAD: similar to GET, but only returns headers (safe) ▸ OPTIONS: used to check which verbs are available (safe) ▸ PATCH: similar to PUT, updating individual properties (idempotent) ▸ MIME type: ▸ Client and API server agree on the data types for exchange, e.g. text/html, application/xml etc
  • 11. REST IN A NUTSHELL THE REQUEST (III) ▸ Headers - supply metadata with the request (Accept, Content-Type) ▸ Data - the data sent from the client to the server ▸ Can conceptually be of any format ▸ Most common: JSON
  • 12. REST IN A NUTSHELL THE RESPONSE ▸ Status code & Status text: ▸ “200 OK” ▸ “404 Not Found” ▸ “500 Server Error” … ▸ There are a lot more specific status codes, such as 201, 301, 302, 400, 401 etc. ▸ Headers and Data
  • 13. REST IN A NUTSHELL WHY DO PEOPLE LIKE AND USE REST? ▸ Works naturally with the HTTP protocol ▸ Other alternatives: ▸ SOAP-XML: very enterprise-y, bloated and complex ▸ XML-RPC: similar to REST, but ignores the power of the verb
  • 15. BUT IS IT RESTFUL ENOUGH? THE REALITY IS MORE COMPLEX ▸ Roy Fielding’s 2000 dissertation about what we today know as REST ▸ Followed up by a series of blog posts from ~2008 about HATEOAS (Hypermedia As The Engine Of Application State) ▸ prescribing additional requirements and behaviours ▸ often considered as ideal, but impractical in a lot of ways ▸ Leads to a lot of discussion what REST is and how one has to use it
  • 16. BUT IS IT RESTFUL ENOUGH? MORE MATURE? ▸ Plain JSON
 
 
 ▸ HATEOAS { "name" : “iPhone 7" } { "name": “iPhone 7", "links": [ { "rel": "self", "href": "http://localhost:8080/product/1" } ] }
  • 17. BUT IS IT RESTFUL ENOUGH? HATEOAS { "content": [ { "price": 499.00, "name": "iPad", "links": [ { "rel": "self", "href": "http://localhost:8080/product/1" } ], "attributes": { "connector": "socket" } }, { "price": 49.00, "name": "Dock", "links": [ { "rel": "self", "href": "http://localhost:8080/product/3" } ], "attributes": { "connector": "plug" } } ], "links": [ { "rel": "product.search", "href": "http://localhost:8080/product/search" } ] }
  • 18. BUT IS IT RESTFUL ENOUGH? RICHARDSON MATURITY LEVEL http://martinfowler.com/articles/richardsonMaturityModel.html
  • 19. TAFFY SETUP AND BASIC FLOW https://www.flickr.com/photos/joanna_young/ 4515399787/
  • 20. TAFFY SETUP AND BASIC FLOW INSTALLATION ▸ Download .zip-file from Github or taffy.io ▸ Installation options: ▸ Global mapping /taffy ▸ /taffy physically in webroot ▸ Installation in sub-directory of site (needs application-specific mappings)
  • 21. TAFFY SETUP AND BASIC FLOW DRIVEN BY APPLICATION.CFC ▸ Extends taffy.core.api ▸ Needs to call onApplicationStart() and onRequestStart() on the parent CFC ▸ Earlier versions of Taffy had their own Application.cfc events - it was recommended to actually not implement onApplicationStart() etc ▸ That’s gone since Taffy 2.0 component extends="taffy.core.api" { this.name = "TaffyDemo"; function onApplicationStart() { application.productList = [ { "id":1, "name":"iPhone 7" }, { "id":2, "name":"iPhone 7+" }, { "id":3, "name":"iPad Pro 9.7inch" } ]; return super.onApplicationStart(); } function onRequestStart() { return super.onRequestStart(); } }
  • 22. TAFFY SETUP AND BASIC FLOW CONVENTION OVER CONFIGURATION ▸ Taffy tries to NOT be in your way ▸ Examples: ▸ Default function names for resources are get(), post(), put(), delete() ▸ Looks for resources in a /resources directory ▸ Lots of things are just fine and work out of the box naturally because of sensible conventions
  • 23. TAFFY SETUP AND BASIC FLOW MINIMAL LAYOUT
  • 24. TAFFY SETUP AND BASIC FLOW RESOURCES (I) ▸ Extend taffy.core.resource ▸ Live in the /resources directory or a /resources mapping ▸ Can be changed - requires dropping the default bean factory ▸ Good practice: ▸ Have a CFC for a “thing” and for a “collection of things” each ▸ My convention: “SomeThing” and “SomeThingCollection” ▸ A resource should at least implement one verb function
  • 25. TAFFY SETUP AND BASIC FLOW RESOURCES (II) ▸ taffy_uri defines the public URL of your resource ▸ representationOf() triggers the default serialiser ▸ withStatus() sets the HTTP status of the response (defaults to “200 OK”) component extends="taffy.core.resource" taffy_uri="/product" { public function get(){ return representationOf(application.productList).withStatus(200); } }
  • 26. TAFFY SETUP AND BASIC FLOW RESOURCES (III) ▸ Passing {productId} token into the resource’s URL ▸ Returning 404 if there’s no record found component extends="taffy.core.resource" taffy_uri="/product/{productId}" { public function get(numeric productId){ for (var product in application.productList) { if (product["id"] == arguments.productId) { return representationOf(product).withStatus(200, "OK"); } } return noData().withStatus(404, "Not Found"); } }
  • 27. TAFFY SETUP AND BASIC FLOW RESOURCES (IV) ▸ If a verb is not implemented in a resource, Taffy will return “405 Not Allowed” ▸ Tokens will automatically become part of the arguments scope ▸ Tokens support regular expressions: /product/{pId:d{4}} - /product/{pId:[A-Za-z]+} ▸ Query string parameters will ALSO automatically become part of the arguments scope ▸ Use .noData() if the intention is to not return data ▸ Similar to .withStatus(…), it’s possible to chain .withHeaders(…) to the return statement
  • 28. TAFFY SETUP AND BASIC FLOW TAFFY DASHBOARD
  • 29. TAFFY SETUP AND BASIC FLOW TAFFY DASHBOARD ▸ Dashboard allows to: ▸ execute requests (incl. Query Params, Headers and Basic Auth) ▸ inspect the response ▸ see a limited amount of documentation ▸ Should (usually) be switched off in production ▸ Default: caches API, needs explicit reloads
  • 30. TAFFY SETUP AND BASIC FLOW CHANGING DATA - WHERE TO PUT POST? ▸ If the POST method was in Product.cfc - we’d have an issue. ▸ The URL route requires us to use /product/{productId} ▸ POST therefore has to life in ProductCollection.cfc ▸ PUT however (updating existing data) can happily go into Product.cfc ▸ URL matching: /product/search will match before /product/{productId}
  • 31. TAFFY SETUP AND BASIC FLOW GOOD PRACTICES FOR PUT AND POST ▸ If you created a record with POST: ▸ return “201 Created” with the created data ▸ potentially return x-inserted-id in the header ▸ If you updated a record with PUT: ▸ return “200 OK” with the updated data ▸ if the record to be updated didn’t exist, create it (see above)
  • 33. ADVANCED TASKS AND CONFIG BREAKING AWAY FROM THE CONVENTIONS ▸ Metadata: ▸ Annotate functions to be triggered by a specific verb: taffy_verb=“<VERB>” ▸ Necessary for extended verbs like OPTIONS, HEAD, PATCH. Optional for standard verbs. ▸ There’s more metadata in serialisers (later)
  • 34. ADVANCED TASKS AND CONFIG BREAKING AWAY FROM THE CONVENTIONS ▸ Configuration: variables.framework struct in Taffy’s Application.cfc ▸ reloadKey/reloadPassword vs. reloadOnEveryRequest ▸ serializer/deserializer (later) ▸ disableDashboard ▸ jsonp/allowCrossDomain ▸ beanFactory - allows hooking into Coldspring, DI/1 etc…
  • 35. ADVANCED TASKS AND CONFIG AUTHENTICATION AND SECURITY ▸ Firstly - what do you want to achieve? ▸ Requiring an API Token? ▸ Fine-grain security? ▸ oAuth ▸ HTTP Basic Auth ▸ SSL
  • 36. ADVANCED TASKS AND CONFIG API TOKEN (I) ▸ Best place to start is onTaffyRequest(…) ▸ Return true to continue processing the request ▸ Return a representation object to abort the request ▸ Two common options for passing token: ▸ URI parameters and/or as part of the data ▸ In the header
  • 37. ADVANCED TASKS AND CONFIG API TOKEN (II) function onTaffyRequest(verb, cfc, requestArguments, mimeExt, headers, methodMetadata, matchedURI) { if (not structKeyExists(arguments.requestArguments, "apiKey") || !Len(arguments.requestArguments["apiKey"])) { return noData().withStatus(401, "Unauthorized"); } if (!arrayFind(application.validAPIKeys, arguments.requestArguments["apiKey"])) { return noData().withStatus(403, "Forbidden"); } return true; }
  • 38. ADVANCED TASKS AND CONFIG CUSTOM SERIALISERS (I) ▸ Default serialiser is JSON (CFML-server built-in) ▸ Extend from taffy.core.baseRepresentation ▸ Implement getAsX functions ▸ getAsXML, getAsJSON, getAsYML etc
  • 39. ADVANCED TASKS AND CONFIG CUSTOM SERIALISERS (II) component extends="taffy.core.baseSerializer" { variables.anythingToXML = application.anythingToXML; variables.jsonUtil = application.jsonUtil; function getAsXML() output="false" taffy_mime="application/xml" taffy_default="false" { return variables.anythingToXML.toXml(variables.data); } function getAsJSON() output="false" taffy_mime="application/json" taffy_default="true" { return variables.jsonUtil.serialize(variables.data); } }
  • 40. ADVANCED TASKS AND CONFIG RATE LIMITS ▸ In a nutshell: ▸ manage access log (api key & time) in DB or key/value storage ▸ onTaffyRequest logs requests and check if limits are exceeded ▸ if not exceeded, process incoming request ▸ if exceeded, return status code “429 Too Many Requests”
  • 41. ADVANCED TASKS AND CONFIG API VERSIONING ▸ Multiple schools of thought: ▸ URI vs header ▸ Make sure you version from day 0! ▸ I tend to use /v1/product, /v2/product etc. ▸ Maps nicely on directory structures in /resources ▸ Update version when breaking compatibility ▸ Consider SemVer (Semantic Versioning) if your API is changing a lot
  • 42. API BLUEPRINT AND OTHER TOOLS https://www.flickr.com/photos/cardoso/2196726835/
  • 43. API BLUEPRINT WHAT IS IT? ▸ Description and specification language for web APIs (http://apiblueprint.org) ▸ From Apiary.io - but can be used independently from that ▸ Language spec: https://github.com/apiaryio/api-blueprint ▸ Offers platform-neutral documentation and additional tooling ▸ Aglio ▸ API-Mock
  • 44. API BLUEPRINT DOCUMENTATION WITH AGLIO ▸ Very simple markup language ▸ npm install -g aglio (https://www.npmjs.com/package/aglio) ▸ aglio -i documentation.md -o documentation.html ▸ MD structure: ▸ # Group ▸ ## Resource ▸ ### Action
  • 45. API BLUEPRINT MOCK SERVER WITH API-MOCK ▸ Creates a mock server for your API (https://github.com/localmed/api-mock) ▸ npm install -g api-mock ▸ api-mock ./documentation.md ▸ Defaults to port 3000
  • 46. API BLUEPRINT PAW ▸ REST API test and management tool on OS X ▸ Recording/Playback/Testing etc ▸ Has API Blueprint support through extensions
  • 48. FINAL THOUGHTS WHAT DID WE COVER? ▸ Taffy - what is it? ▸ How to setup and the foundations ▸ Discussed some advanced topics in more detail ▸ High-level overview of API Blueprint
  • 49. FINAL THOUGHTS GET IN TOUCH Kai Koenig Email: kai@ventego-creative.co.nz Twitter: @AgentK