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

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

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

Status Codes

Matt Trask

@matthewtrask

200s - Success

Status Codes

Matt Trask

@matthewtrask

300s - Redirection

Status Codes

Matt Trask

@matthewtrask

400s - Client Errors

Status Codes

Matt Trask

@matthewtrask

500s - Server Error

Status Codes

Matt Trask

@matthewtrask

They aren't Pokemon, so you dont need to catch them all.

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

OpenAPI

Matt Trask

@matthewtrask

https://github.com/matthewtrask/national-parks-api/blob/main/contract/openapi.yml

OpenAPI

Matt Trask

@matthewtrask

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!

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