REST architecture

REpresentational State Transfer

REST architecture

REST (REpresentational State Transfer) is an architectural style Defined by HTTP 1.0 & 1.1 author (Roy Fielding).
It is not a protocol, nor a standard, but a set of constraints aiming at designing APIs that are centered around the notion of resources.
It leverages the HTTP protocol to provide a uniform interface to access resources.
A common standard in the industry is to design RESTful, Business oriented & Open Ready APIs

REST architecture: Pros & Cons

  • Simple: Leverages HTTP Protocol
    • Well known, widely deployed
    • Use HTTP verbs
    • Use URI as a global identifier for resources
  • Readable: Uniform Interface
    • Consistant interface accross all APIs.
    • Easy to read and understand by a human
  • Portable & Flexible : Adapts very well to different platform and use cases
  • Scalable: Statelessness -> Easy horizontal scaling
  • Independence: Separation between client and server, allow for autonomous development accross sections of a project.

REST architecture: Set of constraints

When given a name, a coordinated set of architectural constraints becomes an architectural style

  • Client-Server
  • Uniform Interface
  • Stateless
  • Cacheable
  • Layered System
  • Code on Demand

REST constraints: Client-Server (1/6)

  • A Client is someone who is requesting resources and are not concerned with data storage, which remains internal to each server
  • Server is someone who holds the resources and are not concerned with the user interface or user state
  • Allow components to evolve independently.

REST constraints: Uniform Interface (2/6)

  • Identification of resources: each resource is uniquely identified in requests
  • Manipulation of resources through representations: each resource has one or more representations
  • Self-descriptive message: message is not only data but everything necessary for the message to be processed
  • Hypermedia as the engine for application state (HATEOAS): the server must give the client the needed information to navigate the service

REST constraints: Stateless (3/6)

  • The server will not store anything about the latest HTTP request the client made
  • Request contains all necessary information
  • No session
  • No history
  • The client is responsible for managing the state of the application.

REST constraints: Cacheable (4/6)

  • Responses include whether the response is cacheable or not
  • If cached, Client will return data from cache without the need to send the request again to the server
  • Improves performance
  • ⚠️ Risks of stale data

REST constraints: Layered System (5/6)

  • Client has no idea about the end server or intermediates processing the requests, only the immediate layer with wich it interacts with
  • Intermediary servers may improve system availability by enabling load-balancing and by providing shared caches
  • The disadvantage is that they add overhead to the processing of data, which could reduce performance

REST constraints: Code on Demand (Optional) (6/6)

  • Client are extendable by downloading executable code

Rules of RESTful API

REST Rules (1/7)

Identification of resources

  • Should prefer naming resource with noun instead of verbs (!= RPC)
  • Plural: /dogs
  • Use Javascript naming convention
  • Prefer hyphens (-) to underscores(_) for readability
  • User lowercase

DO

/medical-units

DON'T

/MedicalUnit

REST Rules (2/7)

CRUD / HTTP Verbs

Implements CRUD using HTTP Methods

  • POST = Create
  • GET = Read
  • PUT = Update
  • DELETE = Delete

Status code

Should rely on standard HTTP status codes. For example:

  • The requested medical unit does not exist: 404 Not Found
  • The request is incoherent: 400 Bad Request
  • An unexpected exception was raised: 500 Internal Server Error

REST Rules (3/7)

Collections

  • 2 base URLs per resource
    • Collection
    • Element
GET /medical-units        # List all medical units
GET /medical-units/{id}   # Get a specific medical unit by ID

REST Rules (4/7)

Hierarchical structure

Use / to indicate hierarchical relationships

GET /hospitals
GET /hospitals/{id}
GET /hospitals/{id}/medical-units
GET /hospitals/{id}/medical-units/{id}

REST Rules (5/7)

Query strings

Allows to filter, sort, paginate, get partial responses, …

GET /hospitals/{id}/medical-units?type=cardiology                 # Filter
GET /hospitals/{id}/medical-units?page=2&per_page=50              # Pagination
GET /hospitals/{id}/medical-units?fields=name,location,capacity   # Partial responses

Custom verbs

GET /hospitals/{id}/medical-units/search?query=toto
GET /hospitals/count

REST Rules (6/7)

Internationalization (I18N)

  • Use ISO 8601 standard for Date/Time/Timestamp
    • 2022-11-28 15:00:00.000
    • 2022-11-28
  • Add support for different languages
    • Accept-Language: fr-CA, fr-FR
    • Not ?language=fr

REST Rules (7/7)

Content Negotiation

  • Client asks for resources format type, in Accept header in order of preference
    • Accept: application/json, text/plain
    • Default is JSON

HATEOAS (Not mandatory, Nice to have)

  • Use RFC5988 link notation to implement HATEOAS
{
    "dog": {
        "id": 243
        "name": "Wan",
        "race": "Golden Retriever",
        "owner": "John",
        "age": 5
    },
    "_links": [
        {
            "href": "https://example.org/api/v1/owners/135",
            "rel": "owner",
        }
    ]
}

Versioning

  • Implementation can change, but not the interface. It is a contract between the client and the server.
  • If the contract must be broken(introducing a breaking change), you should create a new API while temporarily keeping the old one, for retro-compatibility
PATCH /api/v1/hospitals/{id} '{"name": "HPP"}'
PATCH /api/v2/hospitals/{id} '{"label": "HPP"}'

JavaScript Object Notation (JSON)

  • Lightweight standard for data-interchange format
  • Developer-friendly
    • Easy for humans to read/write
    • Efficient to parse/generate
  • Open, not only Javascript

JSON Types

  • Number: 12 2.45
  • String: "hello" 'hello'
  • Boolean: true false
  • Empty value: null
  • Array: ordered values: [1, "apple", true, {...}]
  • Object: unordered key/value pairs: {"title": Game of Thrones", "season": 1}

API First

  • Start by defining the contract (define the API) before starting any development
  • Use standard and normalized format (OpenAPI)
  • Allow development teams to work in parallel
  • Allow to discuss and validate the contract with the consumer before starting the development

Practical Work

Design an API using Apicurio

  • Go to https://studio.apicur.io
  • Create an account
  • Create a new API and use the Pet Store Example Template
  • Explore the "Preview Documentation"
  • Explore the "Edit API", note how the example is designed and the raw definition (Source)

Assignment

  • Using the pet store example as a base, we will design a new API.
  • Create a new API Patient
  • The patient resource should have the following attributes:
    • ID
    • Name
    • Birthdate
    • Sex
    • Social security number
  • Design RESTful API endpoints giving the following capabilities:
    • List patients
    • Retrieve a specific patient information
    • Add a new patient
    • Delete a patient
    • Update a patient
    • Search patient by Social security number
      NB: The Patient resource is given as an example, if you want to design another resource, for your project for example, feel free to do so.

Push your work to Gitlab

  • Push your OpenAPI specification to the Gitlab repository we created in the HTTP assignment.
  • You can either
    • Export the spec, commit and push it to your Gitlab repository
    • Link your Apicurio account to your Gitlab's and use Apicurio "publish" feature to directly commit it in your Gitlab Repository

IDs are preferaby functional Unicity of IDs is requiered

Hypermedia as the Engine of Application State