[drupalday2017] - rest in pieces
TRANSCRIPT
REST in piecesSemiserious comparison of modern approaches
~$ whoami ↩Paolo “Stick” Pustorino#stickgrinder (almost everywhere)
CEO / COO @ SparkFabrik Srl
DRUMMER @ A couple of metal bands \m/_
WIZARD @ Cormyr’s Royal Court
FATHER @ Casamia
ANCHE @ Basta
~$ ls -alh ↩
What makes a great API
Which tools are available
Use-cases showdown
~$ iostat ↩
Completeness
Fairness
Experience
Substance
Openness
Lolcatz
******************************
A cut above the REST
What makes you API really stand out?
(from my perspective)
~$ curl -i -X GET https://stick.says/api-rules/1 ↩
URI should be nouns, not verbs
Verbs are already hard-coded in HTTP (GET, POST, …) so help yourself with
sensible semantics.
/cars/users/books/{id}
/getAllCars/userRemove/books/{id}/remove
~$ curl -i -X GET https://stick.says/api-rules/2 ↩
Never alter the state by GETs
We are not talking quantum physics, so you can observe things without changing their status!
HTTP supports state-alteration verbs. Use ‘em!
POST /carsDELETE /users/{uid}PUT /books/{id}
GET /addCarGET /userRemoveGET /books/{id}/update
~$ curl -i -X GET https://stick.says/api-rules/3 ↩
Don’t mix plurals and singulars
Don’t try to exaggerate semantics expressivity, keep things simple and use plurals.
GET /usersDELETE /users/{id}POST /users/{id}/reviews
GET /users (right but inconsistent with the following)
DELETE /user/{id}POST /user/{id}/review
~$ curl -i -X GET https://stick.says/api-rules/4 ↩
Use sub-resources as relational maps
Resource relations can be seen as ownership: hierarchical mapping helps here.
GET /users/{uid}/reviewsPUT /users/{uid}/reviews/{rid}
GET /reviews?byUser={uid}PUT /userReviews/{rid}
~$ curl -i -X GET https://stick.says/api-rules/5 ↩
Specify formats in HTTP headers
Exchange format information in HTTP headers and leave other means alone to avoid confusion
and messing with priorities.
Content-Type : application/jsonAccept : text/xml
PUT /reviews.jsonGET /reviews?format=xml
~$ curl -i -X GET https://stick.says/api-rules/6 ↩
Caching is built-in HTTP
You can save traffic and help frontend applications deliver light-speed experience with HTTP
caching strategies. Server-to-server connections can benefit too.
EtagVaryCache-ControlProxy-Revalidate
max-age (not a silver bullet)
no-cache (implement proper invalidation instead)
~$ curl -i -X GET https://stick.says/api-rules/7 ↩
Collections should be filterable, sortable and pageable
That’s what query parameters are there for! Be creative and use powerful expressions.
GET /users?sort=-age,+nameGET /users/{uid}/reviews?rate>=3&published=1GET /books?format=[epub,mobi]
GET /users?sortAsc=name&sortDesc=ageGET /userReviews?uid={uid}&rate>=3GET /books?format=epub&format=mobi
~$ curl -i -X GET https://stick.says/api-rules/8 ↩
Version your API
Or kittens will die en-masse on a per-request basis!
Really, you can break outdated consumers if you don’t.
GET /v1/users?sort=-age,+namePOST api.v2.stick.says/users
GET /users?format=oldPOST /users?format=2017
~$ curl -i -X GET https://stick.says/api-rules/9 ↩
Return meaningful status codes
HTTP status codes are to machines what error payloads are to humans. Use both and don’t return
meaningless 200 OK all around.
401 UNAUTHORIZED
{ "errors": [ { "user_msg": "You shall nooot paaass!!!", "internal_msg": "Balrogs are not welcome", "code": 666, “info": "http://stick.says/docs/v1/errors/666" } ]}
200 OK
{ “status” : “error”, "user_msg": "You shall nooot paaass!!!", "internal_msg": "Balrogs are not welcome", "code": 666, “info": "http://stick.says/docs/v1/errors/666"}
~$ curl -i -X GET https://stick.says/api-rules/10 ↩
Support modern authorization methods
Allow apps and services to act on behalf of users with clear scopes and tough security. Remember
authentication and authorization are not the same!
Oauth2JWT-TokensClient credentials
Basic-Auth (acceptable for S2S)
Session handling
RESTassured
Which options are available?
The Drupal way
~$ cat DRUPAL_WAY.txt | grep “pros” ↩
Drupal is finally PHP
REST is almost built-in (REST UI module helps if you like admin UIs)
Pervasive HATEOAS support via HAL
Leverages Symfony’s HTTP exceptions
Resource editing backend comes free
Views are natively RESTful
~$ cat DRUPAL_WAY.txt | grep “cons” ↩
Role-based permissions are not handled by middleware (@FIXME)
No PUTs, just PATCHes (really…)
Can’t do without HATEOAS / HAL (bloated output)
Its endpoint mapping is not ideal
RESTful Views are naive
Heavy bootstrap times
Still hard to integrate continuously
Full-stack frameworks
~$ cat FULLSTACK_FW.txt | grep “pros” ↩
Tailored persistence layer
Complex logic is often easy to implement
Small footprint
Easier multi-environment workflow (you only depend on code)
Continuous integration is a gas
Great cross-framework packages and extensions
~$ cat FULLSTACK_FW.txt | grep “cons” ↩
You may have to implement authentication by yourself
No built-in backoffice for resource management
You have to write all by yourself (even CRUD)
Boilerplate / redundant code across projects
Codebase policies / opinionation is often up to you
~$ cat FULLSTACK_FW.txt | grep “opts” ↩
Laravel / Lumen
Symfony 2/3 / Silex
Lithium (yes, still a good option if you don’t mind getting your hands dirty)
Slim and the like
Dedicated frameworks
~$ cat DEDICATED_FW.txt | grep “pros” ↩
All the pros of full-stack frameworks
Highly opinionated approach
Out-of-the-box support for most REST-related aspects (auth/auth, status-code
mapping, rate-limiting, versioning, format negotiation, etc)
Automatic API documentation generation
~$ cat DEDICATED_FW.txt | grep “cons” ↩
Smaller userbase / community
Few contribution, rely heavily on the shoulder of single maintainers
Risk to end up drowned in a fish bowl
* not that true for Dingo and not that issue for PHP Platform
~$ cat DEDICATED_FW.txt | grep “opts” ↩
API Platform
Dingo API (awesome package for Laravel and Lumen)
Epiphany
Recess PHP
API generation platforms
~$ cat API_PLATFORMS.txt | grep “pros” ↩
Make creating basic (and complex) APIs a breeze
Accessible to non-developers (or better said, frontend developers)
Make you focus on frontend application
Provide basic content management features
Generates API documentation
Pretty easy to scale with native cloud-oriented mindset
(often) Generates client SDKs (even for a number of platforms)
~$ cat API_PLATFORMS.txt | grep “cons” ↩
Logic is in configuration, not code (much like Drupal)
Smaller communities than Drupal
Higher vendor lock-in
Hard to use in team (not friendly to multi-environment workflows)
Suboptimal deployment to production
Rely on older PHP/FW versions
~$ cat API_PLATFORMS.txt | grep “opts” ↩
DreamFactory API Automation Platform (written in Laravel)
Zend Apigility
FRAPI
deployd (it’s node.js, not PHP, but it’s really good!)
put yourself toREST
What to chose for you next API?
~$ diff use_cases..drupal_8 ↩
Use Drupal 8 when...
You are exposing actual content via REST API
Your business logic is already on Drupal and REST becomes a necessary addition
Some specific feature of Drupal, unrelated to REST makes it the best candidate for
your project (and you can bear with the… rest, er…)
~$ diff use_cases..fullstack_fw ↩
Use a full-stack framework when...
You need fluid teamwork, multi-env workflow, fast testing, etc.
You want hassle-free Continuous Integration and Deploy
Your application has lot of custom functions aside “editorial” content management
You want to swim in the ocean, not a bathtub
You must provide enterprise-class support on the long term
~$ diff use_cases..dedicated_fw ↩
Use a dedicated framework when...
You want to speed up development, leveraging good boilerplate code
You want hassle-free Continuous Integration and Deploy
Your application is bound to remain a REST API
You don’t mind getting your hand dirty (smaller community)
You can afford supporting yourself on the long term (yes, even forking the framework)
~$ diff use_cases..api_platforms ↩
Use an API platform when...
You want to speed up development, leveraging easy low-coding tools
Your focus is on thick frontend application
You are akin to pay for managed cloud services
Heavy teamwork on the backend is not in sight
You don’t mind locking to vendors
give it aREST!
Enough blah blah blah...
Wanna chat?
THANKS