building sustainable restful services
TRANSCRIPT
Building Scalable RESTFul Services
Luis Majano@lmajano @ortussolutions
WHO AM I?
• Luis Majano - Computer Engineer
• Imported from El Salvador ————>
• Computer Engineer
• Adobe Community Professional
• CEO of Ortus Solutions
www.ortussolutions.com@ortussolutions
@lmajano
PROFESSIONAL OPEN SOURCE
• ContentBox Modular CMS, ColdBox MVC, CommandBox Package Manager
• Ortus University
• Support & Mentoring Plans
• Architecture & Design
• Infrastructure Design & Setup
• Code Reviews & Sanity Checks
• Application Development
[email protected]@ortussolutions
What are APIsWhat is REST
BenefitsPrinciples
Good DesignTooling
• We live in a mobile world• APIs are what powers our mobile world• Growth is exponential• Provides new ways to do business• Evolve or you will be left behind
WHY APIS ARE IMPORTANT
API GROWTH
MOTIVATIONAL QUOTES
“APIs are how we are going to build software in the future, we are just going to glue it together.”
- John Musser, founder of ProgrammableWeb
“The secret of change is to focus all of your energy, not on fighting the old, but on building the new”
- Socrates
REST = Representational State Transfer
• An architectural style (2000)• Standard for web + mobile apps• Adhere to best practices• Low ceremony web services • Leverage the HTTP/S Protocol• Resource Oriented not RPC Oriented
LOW CEREMONY
SOAP - XML
VS
REST - JSON(HTTP/S)
Headers
Params
Body
Method+URI
SOAP vs REST
/user/:usernameResource
AbstractedCanbeNestedCanpointtoanyinternalRPCcallCanbelayeredFlexible
getUser(‘lmajano’)RemoteProcedureCall
CouplingStaticRefactoringProblemsInflexible
RESOURCE VS RPC
RESTFUL BENEFITS
• Abstractions
• Easier to scale
• Easy to refactor
• Easier to layer
• Much Less bandwidth
RESTFUL PRINCIPLES
• Protocol -> HTTP/S
• Addressability
• Protocol Uniformity
• Model Representations
• Stateless
Addressability - ResourcesObjects/Resources can be addressable via a URI
/api/user/luis/api/user/tweets
RESTFUL PRINCIPLES
RESTFUL PRINCIPLES
Protocol UniformityLeveraging HTTP Verbs + HTTP Headers
Model RepresentationsModels in different formats: json, xml, rss, pdf, etc
200 OKContent-Type: application/json+userdb{ "users": [ { "id": 1, "name": "Emil", "country: "Sweden", "links": [ { "href": "/user/1", "rel": "self", "method": "GET" }, { "href": "/user/1", "rel": "edit", "method": "PUT" }, { "href": "/user/1", "rel": "delete", "method": "DELETE" } ] }, { "id": 2, "name": "Adam", "country: "Scotland", "links": [ { "href": "/user/2", "rel": "self",
RESTFUL PRINCIPLES
RESTFUL PRINCIPLES
StatelessPerformance, reliability, and ability to scale
LET’S APPLY THESE PRINCIPLES
10 STEPS TO GREATNESS
1. Resource Naming2. HTTP Verb Usage3. Meaningful Status Codes4. Modeling + Documentation 5. Uniformity 6. Security7. Versioning (Modularity)8. Performance9. Testability10.Tools
1. RESOURCE NAMING
1. URI Centric2. Use nouns, avoid verbs (HTTP Verbs)3. Deeper you go in the resource the more detail4. URL Params (Options)5. Headers (Auth+Options)6. This is where a modeling tool can help
/customers Get - List customers Post - Create new customer
/customer/:id Get - Show customer Put - Update customer Delete - Delete customer
/customer/:id/invoices Get - All invoices Post - Create invoice
/customer/:id/invoice/:invoiceID Get - Show invoice Put - Update invoice Delete -Delete invoice
2. HTTP VERB USAGE
Operation Verb
Create POST
Read GET
Update PUT
Single item update PATCH
Delete DELETE
Info/Metadata HEAD
Resource Doc OPTIONS
3. MEANINGFUL STATUS CODES
Code Description
200 OK, usually a representation
201 New resource, check headers for URI
202 Accepted (ASYNC), check headers or response for tokens
203 Non-authoritative (Usually a cached response)
204 No Content, but processed
205 Reset Content
206 Partial Results (Usually pagination)
Code Description
400 Bad Request
401 Unauthorized
402 Payment Required
403 Forbidden
404 Not Found
405 Method not allowed
406 Not acceptable (Validation, invalid data)
408 Request Timeout
410 Resource Gone
429 Too Many Requests
500 Server Error
4. MODELING + DOCUMENTATION
4. MODELING + DOCUMENTATION
• Swagger Standard (swagger.io)• YML or JSON
• Swagger based tool: ColdBox Relax• Model RESTFul Services• Scaffold MVC Routes• Documentation Exporter (HTML,PDF,etc)• Tester• Swagger Import/Export
boxinstallrelax—saveDev
SWAGGER JSON{swagger:"2.0",info:{description:"ThisisasampleserverPetstoreserver.YoucanfindoutmoreaboutSwaggerat[http://swagger.io](http://swagger.io)oron[irc.freenode.net,#swagger](http://swagger.io/irc/).Forthissample,youcanusetheapikey`special-key`totesttheauthorizationfilters.",version:"1.0.0",title:"SwaggerPetstore",termsOfService:"http://swagger.io/terms/",contact:{email:"[email protected]"},license:{name:"Apache2.0",url:"http://www.apache.org/licenses/LICENSE-2.0.html"}},host:"petstore.swagger.io",basePath:"/v2",tags:[{name:"pet",description:"EverythingaboutyourPets",externalDocs:{description:"Findoutmore",url:"http://swagger.io"}},{name:"store",description:"AccesstoPetstoreorders"},{
RELAX MODELfunctionconfigure(){ //ThisiswherewedefineourRESTfulservice,thisisusually //ourfirstplacebeforeevenbuildingit,wespecitout. this.relax={ //ServiceTitle title="ForgeBoxIO", //ServiceDescription description="ThisAPIpowersForgeBox", //Serviceentrypoint,canbeasinglestringornamevaluepairstodenotetiers //entryPoint="http://www.myapi.com", entryPoint={ dev ="http://localhost:9095/api/v1", stg ="http://forgebox.stg.ortussolutions.com/api/v1", prd ="http://forgebox.io/api/v1" }, //DoesithaveextensiondetectionviaColdBox extensionDetection=true, //Validformatextensions validExtensions="json", //Doesitthrowexceptionswheninvalidextensionsaredetected throwOnInvalidExtension=false }; //GlobalAPIHeaders //globalHeader(name="x-app-token",description="Thesecretapplicationtoken",required=true,type="string");
//ECHO
5. UNIFORMITY
• Common Response object• Common Controller (MVC)• HTTP Verb Security• Access Security• Error Handling Uniformity• Response Uniformity
Error!
Security
WhereFrameworksWillHelp!
RESPONSE OBJECT/***HTTPResponsemodelfortheAPI*/componentaccessors="true"{
propertyname="format" type="string" default="json"; propertyname="data" type="any" default=""; propertyname="error" type="boolean" default="false"; propertyname="binary" type="boolean" default="false"; propertyname="messages" type="array"; propertyname="location" type="string" default=""; propertyname="jsonCallback" type="string" default=""; propertyname="jsonQueryFormat"type="string" default="query";
propertyname="contentType" type="string" default=""; propertyname="statusCode" type="numeric" default="200"; propertyname="statusText" type="string" default="OK"; propertyname="errorCode" type="numeric" default="0"; propertyname="responsetime" type="numeric" default="0"; propertyname="cachedResponse" type="boolean" default="false"; propertyname="headers" type="array";
/** *Constructor */ Responsefunctioninit(){
BASE CONTROLLER/***Aroundhandlerforallfunctions*/functionaroundHandler(event,rc,prc,targetAction,eventArguments){ try{ varstime=getTickCount(); //prepareourresponseobject prc.response=getModel("Response@core"); //Scopetheincominguserrequest prc.oCurrentUser=securityService.getUserSession();
//prepareargumentexecution varargs={event=arguments.event,rc=arguments.rc,prc=arguments.prc}; structAppend(args,arguments.eventArguments); //Securethecall if(isAuthorized(event,rc,prc,targetAction)){ //Executeaction varsimpleResults=arguments.targetAction(argumentCollection=args); } }catch(Anye){ //LogLocally log.error("Errorcalling#event.getCurrentEvent()#:#e.message##e.detail#",e); //LogtoBugLogHQ sendToBugLog(e);
6. SECURITY
SSL is a MUST! HTTP Verb Security Request Throttling Client API Keys or Tokens (Headers/Params) API Key + Secret Encryption Keys (Like Amazon) Basic Authentication (At least its something!) IP Based Filtering/Tagging (Programmatic/Firewall/Etc) oAuth Third Party API Managers (Adobe API Manager, Kong)
• Upgrade/Downgrade Paths
• Scale with Ease
• No more monoliths
• Implementations:
• Frameworks
• API Manager
• Both
7. VERSIONING (MODULARITY)
8. PERFORMANCE• Web Server (Nginx)
• Gzip Compression• Resource Caching• HTTP2• SSL Keep-Alive Connections• Throttling
• Distributed Caching• Couchbase• Redis
• Adobe API Manager• Create a Caching Strategy• Cache Invalidation
Looks familiar?
9. TESTABILITY
WHY PEOPLE DON’T TEST
COMFORT
WHY PEOPLE DON’T TEST
New MethodologyNew Learned Behavior
It is a leap….
BIGGEST LIE IN SOFTWARE DEV
Don’t worry, we will create the
tests and refactor it later!
• Just do it!
• You will get dirty
• It can hurt (a little)
• Learned behavior
NO MORE EXCUSES
IT WILL ACCELERATE YOUR DEVELOPMENT
BDD TESTING
10. TOOLS
1. Modeling/Documentation/Testing1. Relax, Postman, Swagger, Gelato, SwaggerHub
2. API Management1. Adobe, Mulesoft, Kong
3. Load Testing1. JMeter, Paessler
4. Modular Frameworks1. ColdBox for ColdFusion/CFML2. Laravel, Kohana for PHP
10. ADOBE API MANAGER1. Tons of Features:
1. Rate Limiting2. SLAs3. Swagger Support4. Caching5. Versioning6. Security7. Analytics8. SOAP Tools9. Notifications
http://www.adobe.com/products/coldfusion-enterprise/api-management-platform.html
TECHNOLOGY STACK
REST
Stack ColdBox MVC
Relax
cbSwagger
RollbarCouchbase
Nginx
AdobeAPI
10 STEPS TO GREATNESS
1. Resource Naming2. HTTP Verb Usage3. Meaningful Status Codes4. Modeling + Documentation 5. Uniformity 6. Security7. Versioning (Modularity)8. Performance9. Testability10.Tools
RESOURCES
• Adobe API Manager: www.adobe.com/products/coldfusion-enterprise/api-management-platform.html
• Swagger SDK: github.com/coldbox-modules/swagger-sdk
• cbSwagger Module: github.com/coldbox-modules/cbSwagger
• ColdBox : ortussolutions.com/products/coldbox
• TestBox : ortussolutions.com/products/testbox
• CommandBox: ortussolutions.com/products/commandbox
• Slack: boxteam.herokuapp.com
RESOURCES
• Docker - https://www.docker.com/
• Portainer - portainer.io
• Kong - https://getkong.org/
• Postman - https://www.getpostman.com/
• Gelato - https://gelato.io/
• Swagger - https://swagger.io/tools/
• Paessler - http://www.paessler.com/webstress
• JMeter - http://jmeter.apache.org/