- 0 - Setup
- 1 - Hello World
- 2 - Abuser des bonnes choses
- 3 - Toujours penser au scaling
- 4 - Tester vos routes
- 5 - Qui utilise du texte brut ?
- 6 - Un peu de logique 🤯
- 7 - Les bodyguards des serveurs
- À la racine du répo d'hier, créez un dossier Day2
- Initialisez un module
SoftwareGoDay2
Afin de créer notre web server, nous allons utilisé le framework Gin.
Le but de cet exercice est de mettre en place un server qui expose une route /hello
qui retourne world
.
- Créer un package
routes
qui va contenir votre Router & vos controllers. - Créer une route GET
/hello
renvoyantStatusOK
&world
.
Voici un example de comment organiser vos routes
package router
import (
"github.com/gin-gonic/gin"
)
func world(c *gin.Context) {
}
func ApplyRoutes(r *gin.Engine) {
//r.HttpMethod(route, controller)
}
- Créer un package
server
avec:- Une structure
Server
(qui contient votre app gin). - Une fonction
NewServer()
qui va instancier un nouveau server.
- Une structure
- Créer un main pour lancer votre server.
Une pratique basique lorsque vous lancer un serveur est d'afficher un message avec l'addresse du server afin de pouvoir y accéder facilement.
ex:
Server running here: http://localhost:8080/
En HTTP, les paramètres de votre demande peuvent être exprimés à différents endroits:
body
, parameter
, query
, cookie
& header
- Créez 5 routes qui prendront un
message
dans l'endroit que traite la route & le renverront:- GET
/repeat-my-query
- GET
/repeat-my-param/:message
- POST
/repeat-my-body
- GET
/repeat-my-header
- GET
/repeat-my-cookie
- GET
Pour chacune des routes, si le
message
n'est pas présent renvoyez un StatusBadRequest.
Pour ceux qui ne connaitraient pas, les variables d'environnement sont utilisées par votre système d'exploitation ainsi que de nombreux framework & app. Elles sont utilisées lorsque vous déployez une application en production pour sécuriser des mots de passes et identifiants privés. Il est donc essentiel de savoir comment les utiliser dans votre code.
Pour cela, nous allons utiliser le package dotenv qui permet de charger automatiquement des variables d'environnement depuis un fichier.
go get github.com/joho/godotenv
- Créez un fichier
.env
qui définira les variables suivantes:PORT=8080
HELLO_MESSAGE=world
- Adaptez votre code pour chargez l'env au démarrage.
Il est commun dans une API d'avoir un fichier spécifique à la configuration, il permet de garder une architecture propre.
- Adaptez votre route
/hello
pour utiliserHELLO_MESSAGE
.
Si la variable est absente renvoyez StatusNotFound &
no message defined
Si votre
.env
contient des variables privées, il est impératif de ne pas le push sur un repo en temps normal. Une bonne pratique est de créer unexample.env
contenant les variables sans leurs valeurs.
Il est important de penser depuis le début à l'intégration de votre serveur dans une architecture Web en plaçant le maximum de variables susceptibles de changer dans l'environnement.
Les tests sont partout et le web n'y échappe pas. Il est primordial de tester vos routes avant de déployer en production.
- Créer une collection Postman testant les routes précédentes.
- Créer une route GET '/health' qui renvoie tout le temps le statut
200
.
Elle permet de savoir immédiatement si le server est up.
Avoir des formats de données communs & génériques est obligatoire pour faciliter l'utilisation d'une API!. Vous pouvez renvoyer des informations sous diverses formes. La plus commune étant un tableau d'objet (JSON).
- Créez une route GET
/repeat-all-my-queries
qui renvoie un tableau sous ce format:
[
{
"Key": "...", // nom d'une query
"Value": ["..."] // valeurs d'une query
},
...
]
Le retour étant un tableau d'objets, créer une
structure
peut s'avérer adapté.
Formatter les données c'est bien, travailler avec c'est mieux!
- Créez une route POST
/are-these-palindromes
.- Elle prend un tableau JSON de string dans le body.
- Elle renvoie un tableau d'objets de la forme suivante :
[
{
"Input": "",
"Result": true
},
...
]
En web, il est important de savoir quel type de donnée sont envoyés à votre API. Cela vous permet d'avoir un code stable et sécurisé.
Essayer d'envoyer un body vide à la route précédente, vous devriez obtenir une erreur en retour. Ce genre d'erreur n'est pas acceptable pour une API
Pour assurer la sécurité d'une API, il existe un système que l'on appelle Middleware
.
Les Middleware peut également servir à mettre en place un logger, une gestion des permissions ect...
Nous allons utiliser les middlewares intégrés dans gin !
Voici la structure d'un middleware dans gin :
func Logger() gin.HandlerFunc {
return func(c *gin.Context) {
// before request
t := time.Now()
// Set example variable
c.Set("example", "12345")
c.Next() // Fonction suivante à executer dans la route
// after request
latency := time.Since(t)
log.Print(latency)
// access the status we are sending
status := c.Writer.Status()
log.Println(status)
}
}
- Dans un package
middlewares
, créezCheckPalindrome
Si le body est invalide, renvoyer un StatusBadRequest et la raison du refus.
- Ajoutez à la route
/are-these-palindrome
.