Matthew Clemente
REpresentational State Transfer
HyperText Transfer Protocol
Adam Tuttle, REST Assured: A Pragmatic Approach to API Design, 2019
hyper
A CFML HTTP Builder
box install hyper
api-wrapper-template
A CommandBox tool for scaffolding CFML API Clients
box install api-wrapper-template
apiWrapper scaffold --wizard
apiName* | Name of the API this library will wrap, i.e. Stripe |
apiEndpointUrl* | Base endpoint URL for API calls, i.e. https://api.stripe.com/v1 |
apiAuthentication | Type of authentication used [None, Basic, Apikey, Other] |
apiDocUrl | URL of the API documentation homepage |
name | Name for the wrapper [i.e. StripeCFC] |
description | A short description of the wrapper. |
author | Name of the author of the wrapper. |
package | Create a box.json - for use as a Forgebox package (yes/no) |
apiwrapper scaffold
apiName = "The Cat API"
apiEndpointUrl = "https://api.thecatapi.com/v1"
apiAuthentication = "apikey"
apiDocUrl = "https://docs.thecatapi.com/"
name = "CFCat"
description = "Some people are dog people. Others are
cat people. This wrapper will provide
the latter with cats on demand."
package = "true"
Make sure there's a method to your madness
CRUD | HTTP Verb | Method |
---|---|---|
Create | POST |
createItem(data) |
Read | GET |
getItem(id) listItems() |
Update | PUT/PATCH |
updateItem(id) |
Delete | DELETE |
deleteItem(id) |
catapi = new cfcat.catapi();
catGif = catapi.getRandomGif().data;
writeOutput( '<img src="#catGif.url#">' );
RequestBin / Hookbin / Mockbin
catapi = new cfcat.catapi( includeRaw = true );
data = {
"size": "full",
"breed_id": "raga",
"limit": 1
};
writeDump( catapi.search( data ) );
Authentication typically involves providing credentials via Headers
No Authentication | This is easy! You don't need to do anything! |
Basic Authentication | Base64 encoded username:password in Authorization header |
API Key Authentication | Unique identifiers passed via headers (less frequently, via query params or the body) |
Open Authorization (OAuth) | Access Token used, following authentication and permission |
How do we handle it in our CFML API clients?
No Authentication | This is easy! You don't need to do anything! |
Basic Authentication | cfhttp username and password attributes |
API Key Authentication |
cfhttpparam( type="header", name="api-key", value=value ); |
Open Authorization (OAuth) | https://github.com/coldfumonkeh/oauth2 |
Keeping credentials in environment variables
provides practical and security benefits
// Get access to the system class.
system = createObject( "java", "java.lang.System" );
// Get a specific environment variable
value1 = system.getenv( 'key' );
// Get a specific system property
value2 = system.getProperty( 'key' )
// Get a struct of env vars or system props
environment = system.getenv();
properties = system.getProperties();
Handled automatically in api-wrapper-template
apiwrapper scaffold
apiName = "Aylien"
apiEndpointUrl = "https://api.aylien.com/api/v1"
apiAuthentication = "apikey"
apiDocUrl = "http://docs.aylien.com/textapi/"
name = "ayliencfc"
description = "Access Aylien's Natural Language
Processing (NLP) API to extract meaning
and insight from textual content."
package = "true"
aylien = new aylien.aylien();
entities = aylien.entities( url = 'http://bit.ly/cfsummit2019' ).data;
writeDump( entities );
aylien = new aylien.aylien();
entities = aylien.entities( url = 'http://bit.ly/cfsummit2019' );
writeDump( entities );
aylien = new aylien.aylien();
entities = aylien.entities( url = 'I am not a URL!' );
writeDump( entities );
entities = aylien.entities( 'http://bit.ly/cfsummit2019' ).data;
apiwrapper scaffold
apiName = "Lob"
apiEndpointUrl = "https://api.lob.com/v1"
apiAuthentication = "basic"
apiDocUrl = "https://lob.com/docs"
name = "lobcfc"
description = "Wrap the Lob API to verify
addresses and send physical
mail programmatically."
package = "true"
lob = new lob.lob( forceTestMode = true );
//etc etc
result = lob.createPostcard( postcard );
Pass all parameters as a struct
Helper components with fluent interfaces
/helpers/address.cfc
/helpers/address.cfc
(Because don't you prefer well documented repositories)
🧐📖
Matthew Clemente