Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Get cfml Into the Box 2018

79 views

Published on

Matthew Clemente

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Get cfml Into the Box 2018

  1. 1. GET /cfmlGET /cfml A Guide to Writing API WrappersA Guide to Writing API Wrappers Matthew Clemente @mjclemente @mjclemente84 blog.mattclemente.com @mjclemente View Slides Online
  2. 2. Also Called:Also Called:
  3. 3. APIs are awesome!APIs are awesome!
  4. 4. https://www.programmableweb.com/news/research­shows­interest­providing­apis­still­high/research/2018/02/23  Everything has an APIEverything has an API
  5. 5. github.com/toddmotto/public­apis API Landscape Everything has an APIEverything has an API Payments Email Search AI Natural Language Processing Physical Mail Maps APIs E-Commerce IoT SMS/Voice Accounting Books Calendars Cloud Storage Validation Dictionaries Weather Ticketing Music Recipes Image Recognition Beer Star Wars
  6. 6. Don’t Reinvent the WheelDon’t Reinvent the Wheel
  7. 7. How do we get started?How do we get started? ForgeBox.io Github.com CFML Slack Adobe ColdFusion Portal RIAForge.org Search Engines Step 1: Don't Write Anything!Step 1: Don't Write Anything!
  8. 8. How did I get here?How did I get here? https://github.com/jcberquist/stripecfc https://github.com/mjclemente/mailgun.cfc https://github.com/mjclemente/algolia.cfc https://github.com/mjclemente/sendgrid.cfc
  9. 9. Every API is differentEvery API is different All APIs are the sameAll APIs are the same and alsoand also
  10. 10. RESTRESTREpresentational State Transfer REST is CRUD over HTTP. Some exceptions to this rule are allowed as long as they don’t become the rule. -@atuttle REST Assured: A Pragmatic Approach to API Design Method + Host + Path + Query Params + Body + Headers Status Code + Status Text + Headers + Data
  11. 11. api­wrapper­template A CommandBox tool for scaffolding CFML API Clients Quickly create an API wrapper project Scaffold boilerplate HTTP request handling Structured to mirror API documentation Handle various response formats Provide additional information about request/response https://github.com/mjclemente/api­wrapper­template box install api-wrapper-template
  12. 12. Don’t Reinvent the WheelDon’t Reinvent the Wheel
  13. 13. Getting StartedGetting Started Read the documentation Authentication / Authorization Endpoint / Test Endpoint Rate limits Response Format Other limitations (size of request, etc.) Review other client libraries
  14. 14. The Cat APIThe Cat API
  15. 15. The Cat API WrapperThe Cat API Wrapper 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. quickStart Do you want to quickStart the project?
  16. 16. apiName Cat API apiEndpointUrl http://thecatapi.com/api apiAuthentication none apiDocUrl name CFCat description Some people are cat people. Some people are dog people. This wrapper will give the former random cats on demand.  https://thecatapi.com/docs.html The Cat API WrapperThe Cat API Wrapper apiwrapper scaffold apiName="Cat API" apiEndpointUrl="http://thecatapi.com/api" apiAuthentication="none" apiDocUrl="https://thecatapi.com/docs.html" name="CFCat" description="Some people are cat people. Some people are dog people. This wrapper will give the former random cats on demand." && cd catWrapper && server start openbrowser=false
  17. 17. The Cat API WrapperThe Cat API Wrapper
  18. 18. Read the documentation!Read the documentation!
  19. 19. Making the RequestMaking the Request
  20. 20. Building Your RequestsBuilding Your Requests
  21. 21. Making the RequestMaking the Request /** * http://thecatapi.com/docs.html#images-get * @hint List cats */
  22. 22. Naming Your MethodsNaming Your Methods Be Consistent Follow basic CRUD conventions Use language of documentation For non-CRUD operations, look to other clients createResource() getResource() listResources() updateResource() deleteResource() (Make sure there's a method to your madness)
  23. 23. The ResultThe Result of ourof our RequestRequest cat = new cat.cat(); catImage = cat.listCats().data; writeOutput( catImage );
  24. 24. API Responses > DataAPI Responses > Data cat = new cat.cat(); catImage = cat.listCats(); writeDump( catImage );
  25. 25. Make Debugging EasyMake Debugging Easy https://beeceptor.com RequestBin / Hookbin / Mockbin Being able to send your API wrappers requests to a different endpoint is helpful when debugging.
  26. 26. cat = new cat.cat( includeRaw = true ); catImage = cat.listCats(); writeDump( catImage ); Make Debugging EasyMake Debugging Easy
  27. 27. AuthenticationAuthentication Authentication typically involves providing credentials via Headers No Authentication This is easy! You don't need to do anything! Yay! Basic Authentication Base64 encoded username:password in Authorization header API Key Authentication Unique identifiers passed via headers ( or, less frequently, query params or in the body) Open Authorization (OAuth) Access Token used, following authentication and permission
  28. 28. AuthenticationAuthentication How do we handle it in our CFML API clients? No Authentication This is easy! You don't need to do anything! Yay! Basic Authentication cfhttp username and password attributes API Key Authentication cfhttpparam( type = "header" ... ) Handled via getBaseHttpHeaders() in the api­ wrapper­template Open Authorization (OAuth) https://github.com/coldfumonkeh/oauth2
  29. 29. Environment VariablesEnvironment Variables Keeping secrets in environment variables provides practical and security benefits   https://12factor.net/config  https://www.bennadel.com/blog/2838­reading­environment­variables­in­coldfusion.htm Environment variable handling in AWS­CFML API Wrapper // Get access to the system class. system = createObject( "java", "java.lang.System" ); value = system.getenv( 'key' ); // Calling getenv() without an argument returns a map / struct of all of the // keys available in the current environment (to the ColdFusion user). environment = system.getenv();
  30. 30. Environment VariablesEnvironment Variables Handled automatically in api­wrapper­template var secrets = { 'applicationId': 'AYLIEN_APPLICATION_ID', 'applicationKey': 'AYLIEN_APPLICATION_KEY' };
  31. 31. Aylien Text Analysis APIAylien Text Analysis API
  32. 32. Aylien Text Analysis APIAylien Text Analysis API
  33. 33. apiName Aylien apiEndpointUrl https://api.aylien.com/api/v1 apiAuthentication apikey apiDocUrl http://docs.aylien.com/textapi/#getting-started name ayliencfc description Access Aylien's Natural Language Processing (NLP) API to extract meaning and insight from textual content. Aylien Text Analysis APIAylien Text Analysis API apiwrapper scaffold apiName="Aylien" apiEndpointUrl="https://api.aylien.com/api/v1" apiAuthentication="apikey" apiDocUrl="http://docs.aylien.com/textapi/#getting-started" name="ayliencfc" description="Access Aylien's Natural Language Processing (NLP) API to extract meaning and insight from textual content." && cd aylienWrapper && server start openbrowser=false
  34. 34. Handling API KeysHandling API Keys public any function init( string applicationId = '', string applicationKey = '', string baseUrl = "https://api.aylien.com/api/v1", boolean includeRaw = false ) {
  35. 35. Handling API KeysHandling API Keys private struct function getBaseHttpHeaders() { return { 'Accept' : 'application/json', 'Content-Type' : 'application/json', 'X-AYLIEN-TextAPI-Application-Key' : variables.applicationKey, 'X-AYLIEN-TextAPI-Application-ID' : variables.applicationId, 'User-Agent' : 'ayliencfc/#variables._ayliencfc_version# (ColdFusion)' }; }
  36. 36. Making a RequestMaking a Request /** * https://docs.aylien.com/textapi/endpoints/#entity-extraction * @hint Extracts different types of notable entities from a document */
  37. 37. URL to AnalyzeURL to Analyze http://bit.ly/intb2018
  38. 38. aylien = new aylien.aylien(); entities = aylien.entities( url = 'http://bit.ly/intb2018' ).data; writeDump( entities ); Aylien Entity AnalysisAylien Entity Analysis
  39. 39. Aylien Response HeadersAylien Response Headers aylien = new aylien.aylien(); entities = aylien.entities( url = 'http://bit.ly/intb2018' ); writeDump( entities );
  40. 40. Shouldn't We Validate?Shouldn't We Validate? No...No...
  41. 41. Don’t Reinvent the WheelDon’t Reinvent the Wheel
  42. 42. Leave Validation to the APILeave Validation to the API aylien = new aylien.aylien(); entities = aylien.entities( url = 'I am not a URL!' ); writeDump( entities );
  43. 43. Your Users are DevelopersYour Users are Developers Make their lives easier by identifying pain points.Make their lives easier by identifying pain points. entities = aylien.entities( 'http://bit.ly/intb2018' ).data;
  44. 44. Developer-focused Refactor #1Developer-focused Refactor #1
  45. 45. Developer-focused Refactor #2Developer-focused Refactor #2
  46. 46. Lob API for PrintablesLob API for Printables
  47. 47. apiName Lob apiEndpointUrl https://api.lob.com/v1 apiAuthentication basic apiDocUrl https://lob.com/docs#intro name lobcfc description Wrap the Lob API to verify addresses and send physical mail programmatically. Lob API for PrintablesLob API for Printables apiwrapper scaffold apiName="Lob" apiEndpointUrl="https://api.lob.com/v1" apiAuthentication="basic" apiDocUrl="https://lob.com/docs#intro" name="lobcfc" description="Wrap the Lob API to verify addresses and send physical mail programmatically." && cd lobWrapper && server start openbrowser=false
  48. 48. Lob API for PrintablesLob API for Printables
  49. 49. Basic Auth & Test EndpointsBasic Auth & Test Endpoints public any function init( string apiKey = '', string testApiKey = '', boolean forceTestMode = false, string baseUrl = "https://api.lob.com/v1", boolean includeRaw = false ) { var secrets = { 'apiKey': 'LOB_LIVE_API_KEY', 'testApiKey': 'LOB_TEST_API_KEY' };
  50. 50. Basic Auth & Test EndpointsBasic Auth & Test Endpoints cfhttp( url = fullPath, method = httpMethod, username = !variables.forceTestMode ? variables.apik
  51. 51. Lob Test EndpointLob Test Endpoint lob = new lob.lob( forceTestMode = true ); //etc etc result = lob.createPostcard( postcard );
  52. 52. Getting Into ArgumentsGetting Into Arguments
  53. 53. How To Lose ArgumentsHow To Lose Arguments
  54. 54. How To Diffuse ArgumentsHow To Diffuse Arguments Easiest to implement Commonly used by official clients Preferable to listing arguments Puts burden on developer Data not reusable (The fast and easy approach)
  55. 55. How To Win ArgumentsHow To Win Arguments http://blog.mattclemente.com/2017/08/20/using­the­builder­pattern­in­ (Helper components with fluent interfaces) More initial work for you Significantly better developer experience Component reuse ensures consistent data
  56. 56. Helper Component PropsHelper Component Props /helpers/address.cfc /** * lobcfc * Copyright 2018 Matthew J * Licensed under MIT (https
  57. 57. Chaining MethodsChaining Methods /helpers/address.cfc lob = new lob.lob(); address = new lob.helpers.address() description( 'Into The Box 2018 Demo' ) /** * https://lob.com/docs#addresses_create * @hint Create an address * @address this should be an instance of the `
  58. 58. Something is Wrong HereSomething is Wrong Here
  59. 59. Document Your WrapperDocument Your Wrapper (Because don't you prefer well documented repositories) Docs shouldn't be an afterthought Add a function, add it to the docs Link to official docs Provide a quick start guide/example Describe the install procedure List the functions you provide Model a repo you admire https://rowanmanning.com/posts/writing­a­friendly­readme/
  60. 60. Share Your API Wrappers!Share Your API Wrappers!
  61. 61. Don’t Reinvent the WheelDon’t Reinvent the Wheel
  62. 62. View Slides Online

×