Démarrage de services web avec Go

Lancement d'un service web

  • http.ListenAndServe()
  • Premier paramètre : adresse réseau, si vide, écoute sur tous les interfaces réseau au port 80.
  • Deuxième paramètre : gestionnaire (handler), si nil, utilise DefaultServeMux.
  • DefaultServeMux est un multiplexeur (comparable à un routeur).
  • http.Server est une structure.
  • Champ Addr : adresse réseau, si vide, écoute sur tous les interfaces réseau au port 80.
  • Champ Handler : gestionnaire, si nil, utilise DefaultServeMux.
  • Fonction ListenAndServe()

Lancement du serveur se fait de deux façons possibles

  1. http.ListenAndServe() //HTTP
  2. http.ListenAndServeTLS() //HTTPS
  3. server.ListenAndServe() //HTTP
  4. server.ListenAndServeTLS() //HTTPS
// fonctions équivalentes s1 et s2
func demarrerServeur1() {
    serveur := http.Server{
        Addr:    "localhost:8080",
        Handler: nil,
    }
    serveur.ListenAndServe()
}
func demarrerServeur2() {
    http.ListenAndServe("localhost:8080", nil)
}

Gestion des requêtes

Gestionnaire (Handler)

  • Interface (interface)
  • Définit une méthode ServeHTTP()
  • http.ResponseWriter
  • *http.Request pointeur vers la structure Request
type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}

DefaultServeMux

  • Multiplexeur (comparable à un routeur)
  • Est également un gestionnaire (Handler)

Multiples gestionnaires

  • Ne spécifiez pas le champ Handler de la structure Server
  • Utilisez http.Handle pour attacher un gestionnaire à DefaultServeMux
  • Package http a une fonction Handle
  • Structure ServerMux a aussi une méthode Handle
  • Lorsque vous appelez http.Handle, vous appelez en réalité la méthode Handle de DefaultServeMux
  • DefaultServeMux est un pointeur vers une structure ServerMux
type gestionnairePrincipal struct{}
type gestionnaireAPropos struct{}
func (g *gestionnairePrincipal) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("Un beau jour"))
}
func (a *gestionnaireAPropos) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("À propos!"))
}
func configurerGestionnaires() {
    gp := gestionnairePrincipal{}
    serveur := http.Server{
        Addr:    "localhost:8080",
        Handler: &gp,
    }
    serveur.ListenAndServe()
}
func accueil(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("Bienvenue"))
}
func index(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("Index"))
}
func configurerGestionnairesAvances() {
    gp := gestionnairePrincipal{}
    ga := gestionnaireAPropos{}
    serveur := http.Server{
        Addr:    "localhost:8080",
        Handler: nil, // Utilise DefaultServeMux
    }
    http.Handle("/bonjour", &gp)
    http.Handle("/apropos", &ga)
    http.HandleFunc("/accueil", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("Accueil"))
    })
    http.Handle("/salutation", http.HandlerFunc(accueil))
    http.HandleFunc("/index", index)
    serveur.ListenAndServe()
}

Deux formes de gestion des requêtes

  1. http.Handle
  2. Deuxième paramètre : gestionnaire (Handler)
  3. http.HandleFunc
  4. Deuxième paramètre : fonction gestionnaire
  5. http.HandlerFunc permet de convertir une fonction gestionnaire en gestionnaire
  6. Apelle en interne http.Handle

Gestionnaires intégrés

404 Not Found

  • http.NotFoundHandler
  • Fonction qui retourne un gestionnaire qui répond par "404 page not found" à chaque requête

Redirection

  • http.RedirectHandler
  • Fonction qui retourne un gestionnaire qui redirige chaque requête vers une URL spécifiée avec un code d'état donné

Traitement de chemin

  • http.StripPrefix
  • Fonction qui retourne un gestionnaire qui supprime un préfixe spécifique de l'URL de la requête avant de la transmettre à un autre gestionnaire

Gestion du timeout

  • http.TimeoutHandler
  • Fonction qui retourne un gestionnaire qui exécute un autre gestionnaire dans un délai spécifié

Serveur de fichiers

  • http.FileServer
  • Fonction qui retourne un gestionnaire qui sert des fichiers à partir d'un système de fichiers spécifié
http.ListenAndServe(":8080", http.FileServer(http.Dir("racineWeb")))
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    http.ServeFile(w, r, "racineWeb"+r.URL.Path)
})
http.ListenAndServe(":8080", nil)

Requêtes HTTP

Message HTTP

  • Structure identique pour les requêtes et les réponses HTTP
  • Ligne de requête (ou réponse)
  • Zéro ou plusieurs en-têtes (headers)
  • Ligne vide
  • Corps du message (body) optionnel

Requête

  • Structure Request représente une requête HTTP envoyée par le client
  • Champs importants : URL, Header, Body, Form, PostForm, MultipartForm

URL de la requête

  • Structure URL : champs Scheme, Opaque, User, Host, Path, RawQuery, Fragment
  • Format général : scheme://[userinfo@]host/path[?query][#fragment]
  • RawQuery contient la chaîne de requête brute
  • r.URL.Query() retourne une carte correspondant aux paramètres de la requête
http.HandleFunc("/requete", func(w http.ResponseWriter, r *http.Request) {
    parametres := r.URL.Query()
    id := parametres["id"]
    log.Println(id)
    nom := parametres.Get("nom")
    log.Println(nom)
})
http.ListenAndServe("localhost:8080", nil)

En-têtes de la requête

  • En-têtes sont représentés par un type Header, qui est une carte des paires clé-valeur des en-têtes HTTP
  • Clés de type string, valeurs de type []string
http.HandleFunc("/entetes", func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, r.Header)
    fmt.Fprintln(w, r.Header["Accept-Encoding"])
    fmt.Fprintln(w, r.Header.Get("Accept-Encoding"))
})

Corps de la requête

  • Corps est représenté par le champ Body
  • Interface io.ReadCloser
  • Lire le corps avec la méthode Read
http.HandleFunc("/poster", func(w http.ResponseWriter, r *http.Request) {
    longueur := r.ContentLength
    corps := make([]byte, longueur)
    r.Body.Read(corps)
    fmt.Fprintln(w, string(corps))
})

Formulaires

  • Données envoyées par formulaire placées dans le corps de la requête POST
  • Format des données déterminé par l'attribut enctype du formulaire
  • Valeurs disponibles dans les champs Form, PostForm, MultipartForm
r.ParseForm()
fmt.Fprintln(w, r.Form)
r.ParseForm()
fmt.Fprintln(w, r.PostForm)
r.ParseMultipartForm(1024)
fmt.Fprintln(w, r.MultipartForm)
valeur := r.FormValue("cle")
fmt.Fprintln(w, valeur)

Fichiers téléversés
r.ParseMultipartForm(1024)
fichierHeader := r.MultipartForm.File["telecharge"][0]
fichier, err := fichierHeader.Open()
if err == nil {
    donnees, err := ioutil.ReadAll(fichier)
    if err == nil {
        fmt.Fprintln(w, string(donnees))
    }
}
fichier, _, err := r.FormFile("telecharge")
if err == nil {
    donnees, err := ioutil.ReadAll(fichier)
    if err == nil {
        fmt.Fprintln(w, string(donnees))
    }
}

Étiquettes: Go web serving handlers requests

Publié le 10 septembre à 13h21