Intro To REST
it doesnt mean napping :(
Ovia Innovation Day - 3/08/2023
What do we currently do?
Rest-ish with a mix of something called GraphQL
(we can save GraphQL for another time).
Example request
curl -H "Host: testapi.oviahealth.com" \
-H "accept: */*" \
-H "ovuline_mode: 3" \
-H "accept-language: en-US;q=1, es-US;q=0.9, en;q=0.8" \
-H "authorization: Bearer VEdQV29rYVN3ejFmanY3YVA1WTR5ZlNnYkFLWWlFZDJNT2VibG1GVA==" \
-H "user-agent: Pregnancy/20846 (iPhone; iOS 16.0; Scale/3.00)" \
-H "ovuline_user_type: 4" \
--compressed "https://testapi.oviahealth.com/v2/latest_value/1041,1042?&timezone=America/Chicago" | jq
The biggest issue with this is it isn't intuitive to know what 1041 and 1042 are requesting.
Example response
{
"type": 246949,
"value": "Videos series: Infant care",
"image": "https://s3.amazonaws.com/Ovuline/content_platform/34944/article_246949_InfantCare_600x600_5_Nails.jpg"
},
{
"type": 246950,
"value": "Videos series: Breastfeeding bootcamp",
"image": "https://s3.amazonaws.com/Ovuline/content_platform/34945/article_246950_BreastfeedingBootcamp_noplay_600x600_1_Benefits.jpg"
},
{
"type": 246951,
"value": "Videos series: Pregnancy by week",
"image": "https://www.oviahealth.com/images/article_images/article_20019_s_640_427.jpg"
},
{
"type": 246952,
"value": "Videos series: Moms at work",
"image": "https://s3.amazonaws.com/Ovuline/content_platform/27801/article_105868.jpg"
},
{
"type": 246977,
"value": "Video series: Bringing home baby",
"image": "https://s3.amazonaws.com/Ovuline/content_platform/35192/article_246977.jpg"
}
What are we discussing?
Matt Trask
@matthewtrask
Concepts
URIs
The Verbs
The Status Codes
The Headers
API Contracts and Tooling
But first... some background.
The REST Pyramid of Greatness
Matt Trask
@matthewtrask
![](https://s3.amazonaws.com/media-p.slid.es/uploads/392003/images/8362303/ssss.png)
REST-ish
Matt Trask
@matthewtrask
What do we mean by REST-ish?
Anything but full Hypermedia, which means no links giving directions to the next resource
REST-ish
Matt Trask
@matthewtrask
GET /characters
{
"action": "POST",
"data": {
"user": {
"id": 1,
"name": "Luke Skywalker",
"affilations": [
{
"Jedi",
"Rebels",
"Resistance"
}
]
}
}
}
REST-ish
Matt Trask
@matthewtrask
GET /star-wars-characters
{
"data": {
"user": {
{
"id": 1,
"name": "Luke Skywalker",
"affilations": [
{
"Jedi",
"Rebels",
"Resistance"
}
],
"roles": [
"star pilot",
"death star killer"
],
"weapon": "Lightsaber",
"friends": [
"Obi-Wan",
"Biggs Darklighter",
"Princess Leia",
"Chewie",
"Han Solo"
]
},
{
"id": 2,
"name": "Anakin Skywalker",
"affilations": [
{
"Jedi",
"Sith",
"Empire",
"Galatic Republic"
}
],
"roles": [
"general",
"star pilot",
"pod racing",
"youngling slayer"
],
"weapon": "Lightsaber",
"friends": [
"Obi-Wan",
"Palpatine",
"Ahsoka Tano",
"R2-D2",
"Captain Rex"
]
}
}
}
}
REST-ish
Matt Trask
@matthewtrask
GET /characters
200 OK
{
"error": "There were no characters to be found"
}
We want to avoid this.
What is REST?
Matt Trask
@matthewtrask
Representation State Transfer (REST)
What is REST?
Matt Trask
@matthewtrask
6 Architectural Constraints
1. Client Server Architecture
2. Statelessness
3. Cacheability
4. Layered System
5. Code On Demand (optional)
6. Uniform Interface
Theorized in a doctoral thesis by Roy Fielding in 2000.
What is REST?
Matt Trask
@matthewtrask
1. Client Server Architecture
Client and Server are independent of each other.
Allows for independent
client (iOS, Android, Web) implementations.
What is REST?
Matt Trask
@matthewtrask
2. Statelessness
Server maintains intrinsic (resource) state
Client maintains extrinsic state, and is responsible for passing state to server (filters, limits, etc)
What is REST?
Matt Trask
@matthewtrask
3. Cacheability
Clients and intermediaries can cache responses.
Responses must, implicitly or explicitly, define themselves as cacheable or non-cacheable.
What is REST?
Matt Trask
@matthewtrask
4. Layered System
Client can not discern whether it has connected to the server directly, or through an intermediary like a proxy or load balancer
What is REST?
Matt Trask
@matthewtrask
5. Code On Demand
Ability to send code on demand, such as some Javascript, to the client to be executed.
*Optional
What is REST?
Matt Trask
@matthewtrask
6. Uniform Interface
1.Resource Identification in requests
2. Resource Manipulation Through Representations
3. Self-descriptive messages
4. Hypermedia as the engine of application state
*Fundamental
Matt Trask
@matthewtrask
![](https://media1.giphy.com/media/bq6F8QYqBU7Yc/giphy.gif)
URIs
Matt Trask
@matthewtrask
The Entry Point to your API
Best Practices
Resource Based instead Action Based
Pluralized
Hyphened instead of underscored
URIs should describe relationships
URIs
Matt Trask
@matthewtrask
What does resource based mean?
Resource based means that by looking at the URI, I can reasonably determine what resource I am about to consume/manipulate/remove
Also allows you to manage relationships in the resource collection
URIs
Matt Trask
@matthewtrask
GOOD https://api.starwars.com/characters
BAD https://api.starwars.com/get_characters
GOOD https://api.starwars.com/characters/ac5b605a-661e-4083-857f-d65e30e3467a
tip: you dont need to use the full uuid
BAD https://api.starwars.com/characters/1
URIs
Matt Trask
@matthewtrask
GET https://api.fancypantsbank.com/accounts
GET https://api.fancypantsbank.com/accounts/checking-account
POST https://api.fancypantsbank.com/accounts/checking-account
PUT https://api.fancypantsbank.com/accounts/checking-account
DELETE https://api.fancypantsbank.com/accounts/checking-account
Verbs
Matt Trask
@matthewtrask
Get
Post
Put
Patch
Delete
Options
Verbs
Matt Trask
@matthewtrask
GET
requests a representation of the specified resource
No Request Body
Response will have body
Safe
Idempotent
Cacheable
Verbs
Matt Trask
@matthewtrask
GET /api/users
200 OK
Content-type: application/json
Etag: 0bba161a7165a211c7435c950ee78438
Cache-control: max-age=3600 // 1 hour
{
"data": [
{
"id": 1,
"name": "Luke Skywalker",
"links": {
"rel": "self",
"href": "/api/users/1",
"metbod": "GET"
}
},
{
"id": 2,
"name": "Anakin Skywalker",
"links": {
"rel": "self",
"href": "/api/users/2",
"method": "GET"
}
}
]
}
Verbs
Matt Trask
@matthewtrask
Post
send data to the server to create a resource
Request has body
Response may have body
Not Safe
Not Idempotent
Cacheable If Freshness Headers is provided
Verbs
Matt Trask
@matthewtrask
POST /api/users
{
"name": "Wedge Antilles",
"species": "Corellian",
"age": 26,
"affiliations": [
"rebels",
"resistance"
],
"callsign": "Red 2"
"ship": "X-Wing"
}
201 Created
Location: /api/users/3
Content-Location: /api/users/3
Last-Modified: Wed, 24 Mar 2021 12:00:00 GMT
Verbs
Matt Trask
@matthewtrask
Put
update or create data on the server
Request will have a body
Successful response will not have body
Not Safe
Idempotent
Not cacheable
Status Codes: 201, 204
Verbs
Matt Trask
@matthewtrask
PUT /api/users/3
{
"name": "Wedge Antilles",
"species": "Corellian",
"age": 30,
"affiliations": [
"rebels",
"resistance"
],
"callsign": "Red Leader"
"ship": "X-Wing"
}
200 OK
Location: /api/users/3
Content-Location: /api/users/3
Last-Modified: Mon, 15 Nov 2017 12:00:00 GMT
Verbs
Matt Trask
@matthewtrask
Patch
partial update of a resource on a server
Request will have a body
Response may have body
Not Safe
Not Idempotent
Cacheable If Freshness Data is provided
May be restricted via headers
Status Codes: 200, 204
Verbs
Matt Trask
@matthewtrask
PATCH /api/users/3
{
"callsign": "Red Leader"
}
204 No Content
Location: /api/users/3
Content-Location: /api/users/3
Last-Modified: Wed, 24 Mar 2021 12:01:00 GMT
Verbs
Matt Trask
@matthewtrask
Delete
complete removal of a resource on a server
Request may have body
Response may have body
Not Safe
Not Idempotent
Not Cacheable
Status Codes: 200, 202, 204
Verbs
Matt Trask
@matthewtrask
DELETE /api/users/3
{
"name": "Wedge Antilles",
"species": "Corellian",
"age": 30,
"affiliations": [
"rebels",
"resistance"
],
"callsign": "Red Leader"
"ship": "X-Wing"
}
204 No Content
200 OK
{
"message": "Resource deleted",
}
Verbs
Matt Trask
@matthewtrask
Options
requests permitted communication options for a given URL or server
Request will not have body
Response will have body
Safe
Idempotent
Not cacheable
Status Codes: 204
Verbs
Matt Trask
@matthewtrask
Non-CORS
OPTIOMS /api/users
HTTP/1.1 204 No Content
Allow: OPTIONS, GET, HEAD, POST
Cache-Control: max-age=604800
Date: Wed, 24 Mar 2021 11:45:00 GMT
Server: EOS (lax004/2813)
CORS
OPTIONS https://starwars.com/api/users/ HTTP/1.1
Host: bar.example
Accept: text/html,application/xhtml+xml,application/json,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive
Origin: https://starwars.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type
Status Codes
Matt Trask
@matthewtrask
Numbers and Phrases to give quick context for a request
// brew install httpie
http https://www.matthewtraskphotography.com
HTTP/1.1 200 OK
Status Codes
Matt Trask
@matthewtrask
100s - Informational
![](https://media3.giphy.com/media/WoWm8YzFQJg5i/giphy.gif)
Status Codes
Matt Trask
@matthewtrask
200s - Success
![](https://media3.giphy.com/media/xNBcChLQt7s9a/giphy.gif)
Status Codes
Matt Trask
@matthewtrask
300s - Redirection
![](https://media3.giphy.com/media/rDroB384ydCvK/giphy.gif)
Status Codes
Matt Trask
@matthewtrask
400s - Client Errors
![](https://media1.giphy.com/media/pLawT3Jf5LHeU/giphy.gif)
Status Codes
Matt Trask
@matthewtrask
500s - Server Error
![](https://media2.giphy.com/media/IYM94GKxUBgoU/giphy.gif)
Status Codes
Matt Trask
@matthewtrask
They aren't Pokemon, so you dont need to catch them all.
![](https://media2.giphy.com/media/fSvqyvXn1M3btN8sDh/giphy.gif)
Headers
Matt Trask
@matthewtrask
Information sent with the request and response
4 Types of Headers
General Headers
Request Headers
Response Headers
Entity Headers
Headers
Matt Trask
@matthewtrask
Accept | Content-type
# Request
Accept: application/json
Accept: application/vnd.github+json
Accept: application/xml
Accept: text/plain
Accept: text/csv
# Response
Content-type: application/json
Content-type: text/html
Content-type: text/csv
Content-type: application/vnd.github+json
These headers allow for content negotiation: where the server decides between the mime types which is best to send
Headers
Matt Trask
@matthewtrask
Authorization
# Request
Authorization: Bearer 5eb63bbbe01eeed093cb22bb8f5acdc3
Authorization: Basic a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
Headers
Matt Trask
@matthewtrask
Cache-Control
# Request
Cache-Control: max-age=<seconds>
Cache-Control: max-stale[=<seconds>]
Cache-Control: min-fresh=<seconds>
Cache-Control: no-cache
Cache-Control: no-store
Cache-Control: no-transform
Cache-Control: only-if-cached
# Response
Cache-Control: no-cache
Cache-Control: no-store
Cache-Control: no-transform
Cache-Control: public
Cache-Control: private
Cache-Control: proxy-revalidate
Cache-Control: max-age=<seconds>
Cache-Control: s-maxage=<seconds>
Headers
Matt Trask
@matthewtrask
Location
# Response
Content-Location: /api/characters/3
Location: /api/characters/3
Headers
Matt Trask
@matthewtrask
Etag | Age | Last-Modified
# Response
Etag: 5eb63bbbe01eeed093cb22bb8f5acdc3
Age: 60 // in seconds
Last-modified: Wed, 24 Mar 2021-03-24 12:00:00 GMT // “HTTP-date” format as defined by RFC 7231
Headers
Matt Trask
@matthewtrask
Content-length | Content-language | Expires
# Response
Content-length: 128 // represented by 8-bit bytes
Content-language: en
Expires: Tue, 29 Mar 2021 23:59:59 GMT
Headers
Matt Trask
@matthewtrask
CORS
Access-Control-Allow-Origin
Access-Control-Allow-Credentials
Access-Control-Expose-Headers
Access-Control-Max-Age
Access-Control-Allow-Methods
Access-Control-Allow-Headers
API Contracts
Matt Trask
@matthewtrask
API Contracts
OpenAPI
JSON Schema
Tooling
Resources
API Contracts
Matt Trask
@matthewtrask
What Is An API Contract?
It is something that both API provider and API consumer can agree upon, and get to work developing and delivering, and then integrating and consuming. An API contract is a shared understanding of what the capabilities of a digital interface are, allowing for applications to be programmed on top of.
OpenAPI
Matt Trask
@matthewtrask
A description language that allows for documentation generation, testing, SDK generation, and more.
The resulting file creates the "contract" that both the server and client can reliable consume.
The artist formerly known as Swagger
OpenAPI
Matt Trask
@matthewtrask
![](https://s3.amazonaws.com/media-p.slid.es/uploads/392003/images/5865064/OpenAPIDrivenDevelopment.png)
OpenAPI
Matt Trask
@matthewtrask
![](https://s3.amazonaws.com/media-p.slid.es/uploads/392003/images/8381681/Screen_Shot_2021-03-23_at_9.54.43_PM.png)
https://github.com/matthewtrask/national-parks-api/blob/main/contract/openapi.yml
OpenAPI
Matt Trask
@matthewtrask
![](https://s3.amazonaws.com/media-p.slid.es/uploads/392003/images/8381684/Screen_Shot_2021-03-23_at_9.55.48_PM.png)
JSON Schema
Matt Trask
@matthewtrask
JSON Schema is a vocabulary that allows you to annotate and validate JSON documents.
Matt Trask
@matthewtrask
{
"$id": "https://example.com/address.schema.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"description": "An address similar to http://microformats.org/wiki/h-card",
"type": "object",
"properties": {
"post-office-box": {
"type": "string"
},
"extended-address": {
"type": "string"
},
"street-address": {
"type": "string"
},
"locality": {
"type": "string"
},
"region": {
"type": "string"
},
"postal-code": {
"type": "string"
},
"country-name": {
"type": "string"
}
},
"required": [ "locality", "region", "country-name" ],
"dependentRequired": {
"post-office-box": [ "street-address" ],
"extended-address": [ "street-address" ]
}
}
OpenAPI vs JSON Schema
Matt Trask
@matthewtrask
OpenAPI 3.1 finally worked through some minor issues and now OpenAPI and JSON Schema play nice together!
![](https://media4.giphy.com/media/30ogPwml4Am2I/giphy.gif)
Tooling
Matt Trask
@matthewtrask
Postman - HTTP Testing
Paw (Mac Only) - HTTP Testing
HTTPie (CLI) - HTTP Testing
Insomnia - HTTP Testing
Postwoman - HTTP Testing
Stoplight Studio - Documentation
Stoplight Spectral - Linting
Dredd.io - Testing
jq - CLI JSON map/filter/slice
Intro To REST
By Matt Trask
Intro To REST
- 186