REST propose une architecture standard pour l'élaboration d'application serveur
Le protocole HTTP offre plusieurs mécanismes permettant de respecter les principes REST en développant un service web respecter les principes REST en développant un service web
La structure des URLs permet d'identifier clairement et de manière uniforme les ressources accessible via le service web.
/products
/products?brand=keychron&sort=price-asc
/products/B09NLTWKGP
/semesters
/semesters/A2020
/semesters/A2020/courses
/semesters/A2020/courses/420-0Q7-SW
/semesters/A2020/courses/420-0Q7-SW/groups
/semesters/A2020/courses/420-0Q7-SW/groups/2
/orders/202201012314
/orders/202201012314/invoice
Les verbes HTTP permettent de rendre explicite l'action à appliquer sur une ressource
GET /conversations
GET /conversations/9812
GET /conversations/9812/messages
POST /conversations/9812/messages
{ "text": ... }
PATCH /messages/987123654
{ "text" : ... }
PATCH /messages/987123654
{ "reaction" : ... }
DELETE /messages/456192837
ATTENTION
Il est aussi possible de TOUJOURS retourner un code 200 et d'indiquer l'erreur dans le body de la réponse.
Les headers permettent d'ajouter des informations complémentaires à la communication HTTP, requête ou réponse, identifiés par la structure Clé: Valeur
Content-Length: 742
Content-Type: application/json
Content-Type: text/html
Content-Disposition: attachment; filename="cat.jpg"
Accept: /
Accept: image/*
Accept: text/html
Le mécanisme principal de transfert de données en HTTP est le body des requêtes et réponses. Outre les fichiers bruts (images, zip, etc.), il est judicieux d'uniformiser le format de donnée utilisé.
# BUCKET LISTS
GET /lists
POST /list-add
voyages
POST /list-edit
voyages
destinations
POST /list-delete
nourriture
# ITEMS D'UNE LISTE
GET /lists-items?list=...
GET /lists-items
destinations
POST /lists-items?list=...
nouvel item
POST /lists-items
destinations=allemagne
POST /list-items-delete
_ITEM ID_
# BUCKET LISTS
GET /lists
POST /lists
{ name: _NAME_ }
PATCH /lists/_NAME_
{ name: _NEW NAME_ }
DELETE /lists/_NAME_
# ITEMS D'UNE LISTE
GET /lists/_LIST NAME_/items
? GET /lists/items?list=_LIST NAME_
POST /lists/_NAME_/items
{ item: ... }
? POST /lists/items?list=_LIST NAME_
{ item: ... }
DELETE /lists/_NAME_/items/_ID_
DELETE /items/_ID_
Et les réponses?
require "bundler/inline"
gemfile do
source "http://rubygems.org"
gem "sinatra-contrib"
gem "rackup"
gem "webrick"
end
require "sinatra/base"
require "sinatra/reloader"
class MySinatraApp < Sinatra::Base
configure :development do
register Sinatra::Reloader
end
#
# VERBE
#
get "/" do
return "Bonjour à tous!"
end
# Une route est identifiee par le VERBE + CHEMIN
# GET / est different de DELETE /
delete "/" do
return "Ceci est une action DELETE"
end
#
# Parametre de chemin
#
get "/greetings/admin" do
return "Bonjour cher admin!"
end
# ATTENTION, l'ordre de declaration des routes est important
# /greetings/admin
# /greetings/james
get "/greetings/:name" do
# On peut preciser un parametre dans le chemin
return "Bonjour à #{params["name"]}!"
end
#
# Réponse: Status et Headers
#
# An Array with three elements: [status (Integer), headers (Hash), response body (responds to #each)]
# An Array with two elements: [status (Integer), response body (responds to #each)]
# An object that responds to #each and passes nothing but strings to the given block
# A Integer representing the status code
get "/status" do
return 204
end
get "/status/body" do
return [200, "Code 200, Tout est OK!"]
end
get "/status/body/headers" do
data = { name: "James Hoffman", title: "Enseignant", age: 42 }
headers = {
"Content-Type"=> "application/json"
}
return [
200,
headers,
data.to_json
]
end
#
# Requête: Headers
#
post "/headers" do
# Les headers sont formatés selon les règles suivantes
# - Nom en MAJUSCULE
# - Les tirets - deviennent des barres de soulignement _
# - Préfix HTTP_
# Exemple:
# Accept devient HTTP_ACCEPT
# User-Agent devient HTTP_USER_AGENT
#
# EXCEPTIONS
# CONTENT_LENGTH, CONTENT_TYPE
# Les données complémentaires de la requête
# sont disponible dans le Hash request.env
# Plusieurs helpers simplifient l'accès
# https://www.rubydoc.info/github/rack/rack/Rack/Request/Helpers
return [
request.content_type,
request.user_agent,
request.accept?("application/json").to_s,
request.has_header?("CONTENT_TYPE").to_s,
request.get_header("CONTENT_TYPE"),
request.get_header("HTTP_MY_HEADER"),
request.env.to_s,
request.env["HTTP_MY_HEADER"],
].join("\n\n\n\n")
end
run! if app_file == $0
end
require "bundler/inline"
gemfile do
source "http://rubygems.org"
gem "faraday"
end
require "faraday"
server = Faraday.new "http://localhost:4567"
def show(response)
puts response.status
puts "---"
puts response.headers
puts "---"
puts response.body
puts "\n\n"
end
show server.get("/")
show server.delete("/")
show server.get("/greetings/admin")
show server.get("/greetings/james")
show server.get("/status")
show server.get("/status/body")
show server.get("/status/body/headers")
headers = {
"Content-Type" => "custom/james",
"Accept" => "text/html",
"My-Header" => "ahoy!"
}
show server.post("/headers", nil, headers)