Recherche…


Remarques

http.ServeMux fournit un multiplexeur qui appelle les gestionnaires pour les requêtes HTTP.

Les alternatives au multiplexeur de bibliothèque standard incluent:

HTTP Hello World avec serveur personnalisé et mux

package main

import (
    "log"
    "net/http"
)

func main() {

    // Create a mux for routing incoming requests
    m := http.NewServeMux()

    // All URLs will be handled by this function
    m.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("Hello, world!"))
    })

    // Create a server listening on port 8000
    s := &http.Server{
        Addr:    ":8000",
        Handler: m,
    }

    // Continue to process new requests until an error occurs
    log.Fatal(s.ListenAndServe())
}

Appuyez sur Ctrl + C pour arrêter le processus.

Bonjour le monde

La façon habituelle de commencer à écrire des serveurs Web dans golang consiste à utiliser le module net/http bibliothèque standard.

Il y a aussi un tutoriel pour cela ici .

Le code suivant l'utilise également. Voici l'implémentation de serveur HTTP la plus simple possible. Il répond "Hello World" à toute requête HTTP.

Enregistrez le code suivant dans un fichier server.go dans vos espaces de travail.

package main

import (
    "log"
    "net/http"
)

func main() {
    // All URLs will be handled by this function
    // http.HandleFunc uses the DefaultServeMux
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("Hello, world!"))
    })

    // Continue to process new requests until an error occurs
    log.Fatal(http.ListenAndServe(":8080", nil))
}

Vous pouvez exécuter le serveur en utilisant:

$ go run server.go

Ou vous pouvez compiler et exécuter.

$ go build server.go
$ ./server

Le serveur écoutera le port spécifié ( :8080 ). Vous pouvez le tester avec n'importe quel client HTTP. Voici un exemple avec cURL :

curl -i http://localhost:8080/
HTTP/1.1 200 OK
Date: Wed, 20 Jul 2016 18:04:46 GMT
Content-Length: 13
Content-Type: text/plain; charset=utf-8

Hello, world!

Appuyez sur Ctrl + C pour arrêter le processus.

Utiliser une fonction de gestionnaire

HandleFunc enregistre la fonction de gestionnaire pour le modèle donné dans le serveur mux (routeur).

Vous pouvez passer à définir une fonction anonyme, comme nous l'avons vu dans l'exemple de base de Hello World :

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "Hello, world!")
}

Mais on peut aussi passer un type HandlerFunc . En d'autres termes, nous pouvons passer toute fonction qui respecte la signature suivante:

func FunctionName(w http.ResponseWriter, req *http.Request)

Nous pouvons réécrire l'exemple précédent en passant la référence à un HandlerFunc précédemment défini. Voici l'exemple complet:

package main

import (
    "fmt"
    "net/http"
)

// A HandlerFunc function
// Notice the signature of the function
func RootHandler(w http.ResponseWriter, req *http.Request) {
    fmt.Fprintln(w, "Hello, world!")
}

func main() {
    // Here we pass the reference to the `RootHandler` handler function
    http.HandleFunc("/", RootHandler)
    panic(http.ListenAndServe(":8080", nil))
}

Bien entendu, vous pouvez définir plusieurs gestionnaires de fonctions pour différents chemins.

package main

import (
    "fmt"
    "log"
    "net/http"
)

func FooHandler(w http.ResponseWriter, req *http.Request) {
    fmt.Fprintln(w, "Hello from foo!")
}

func BarHandler(w http.ResponseWriter, req *http.Request) {
    fmt.Fprintln(w, "Hello from bar!")
}

func main() {
    http.HandleFunc("/foo", FooHandler)
    http.HandleFunc("/bar", BarHandler)

    log.Fatal(http.ListenAndServe(":8080", nil))
}

Voici la sortie en utilisant cURL :

➜  ~ curl -i localhost:8080/foo
HTTP/1.1 200 OK
Date: Wed, 20 Jul 2016 18:23:08 GMT
Content-Length: 16
Content-Type: text/plain; charset=utf-8

Hello from foo!

➜  ~ curl -i localhost:8080/bar
HTTP/1.1 200 OK
Date: Wed, 20 Jul 2016 18:23:10 GMT
Content-Length: 16
Content-Type: text/plain; charset=utf-8

Hello from bar!

➜  ~ curl -i localhost:8080/
HTTP/1.1 404 Not Found
Content-Type: text/plain; charset=utf-8
X-Content-Type-Options: nosniff
Date: Wed, 20 Jul 2016 18:23:13 GMT
Content-Length: 19

404 page not found

Créer un serveur HTTPS

Générer un certificat

Pour pouvoir exécuter un serveur HTTPS, un certificat est nécessaire. La génération d’un certificat auto-signé avec openssl se fait en exécutant cette commande:

openssl req -x509 -newkey rsa:4096 -sha256 -nodes -keyout key.pem -out cert.pem -subj "/CN=example.com" -days 3650`

Les paramètres sont:

  • req Utiliser l'outil de demande de certificat
  • x509 Crée un certificat auto-signé
  • newkey rsa:4096 Crée une nouvelle clé et un nouveau certificat en utilisant les algorithmes RSA avec une longueur de clé de 4096 bits.
  • sha256 Force les algorithmes de hachage SHA256 que les principaux navigateurs considèrent comme sécurisés (en 2017)
  • nodes Désactive la protection par mot de passe pour la clé privée. Sans ce paramètre, votre serveur doit vous demander le mot de passe à chaque démarrage.
  • keyout le fichier où écrire la clé
  • out Nomme le fichier où écrire le certificat
  • subj Définit le nom de domaine pour lequel ce certificat est valide
  • days Combien de jours faut-il pour que ce certificat soit valide? 3650 sont environ. 10 années.

Remarque: Un certificat auto-signé peut être utilisé, par exemple, pour des projets internes, le débogage, les tests, etc. Tout navigateur sur ce site mentionnera que ce certificat n'est pas sûr. Pour éviter cela, le certificat doit être signé par une autorité de certification. Surtout, ce n'est pas disponible gratuitement. Une exception est le mouvement "Let's Encrypt": https://letsencrypt.org

Le code nécessaire

Vous pouvez gérer la configuration TLS pour le serveur avec le code suivant. cert.pem et key.pem sont votre certificat et votre clé SSL, générés avec la commande ci-dessus.

package main

import (
    "log"
    "net/http"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("Hello, world!"))
    })

    log.Fatal(http.ListenAndServeTLS(":443","cert.pem","key.pem", nil))
}

Répondre à une demande HTTP à l'aide de modèles

Les réponses peuvent être écrites sur un http.ResponseWriter utilisant des modèles dans Go. Cela s'avère être un outil pratique si vous souhaitez créer des pages dynamiques.

(Pour savoir comment fonctionnent les modèles dans Go, visitez la page Documentation des modèles de version .)

Continuez avec un exemple simple pour utiliser le html/template pour répondre à une requête HTTP:

package main

import(
    "html/template"
    "net/http"
    "log"
)

func main(){
    http.HandleFunc("/",WelcomeHandler)
    http.ListenAndServe(":8080",nil)
}

type User struct{
    Name string
    nationality string //unexported field.
}

func check(err error){
    if err != nil{
        log.Fatal(err)
    }
}

func WelcomeHandler(w http.ResponseWriter, r *http.Request){
    if r.Method == "GET"{
        t,err := template.ParseFiles("welcomeform.html")
        check(err)
        t.Execute(w,nil)
    }else{
        r.ParseForm()
        myUser := User{}
        myUser.Name = r.Form.Get("entered_name")
        myUser.nationality = r.Form.Get("entered_nationality")
        t, err := template.ParseFiles("welcomeresponse.html")
        check(err)
        t.Execute(w,myUser)
    }
}

Où, le contenu de

  1. welcomeform.html sont:
<head>
    <title> Help us greet you </title>
</head>
<body>
    <form method="POST" action="/">
        Enter Name: <input type="text" name="entered_name">
        Enter Nationality: <input type="text" name="entered_nationality">
        <input type="submit" value="Greet me!">
    </form>
</body>
  1. welcomeresponse.html sont:
<head>
    <title> Greetings, {{.Name}} </title>
</head>
<body>
    Greetings, {{.Name}}.<br>
    We know you are a {{.nationality}}!
</body>

Remarque:

  1. Assurez-vous que les fichiers .html sont dans le bon répertoire.

  2. Lorsque http://localhost:8080/ peut être visité après le démarrage du serveur.

  3. Comme on peut le voir après avoir soumis le formulaire, le champ de nationalité non exporté de la structure n'a pas pu être analysé par le package de modèle, comme prévu.

Servir du contenu avec ServeMux

Un simple serveur de fichiers statique ressemblerait à ceci:

package main

import (
    "net/http"
)

func main() {
    muxer := http.NewServeMux()
    fileServerCss := http.FileServer(http.Dir("src/css"))
    fileServerJs := http.FileServer(http.Dir("src/js"))
    fileServerHtml := http.FileServer(http.Dir("content"))
    muxer.Handle("/", fileServerHtml)
    muxer.Handle("/css", fileServerCss)
    muxer.Handle("/js", fileServerJs)
    http.ListenAndServe(":8080", muxer)
}

Gestion de la méthode http, accès aux chaînes de requête et au corps de la requête

Voici un exemple simple de certaines tâches courantes liées au développement d'une API, en différenciant la méthode HTTP de la requête, en accédant aux valeurs de chaîne de requête et en accédant au corps de la requête.

Ressources

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
)

type customHandler struct{}

// ServeHTTP implements the http.Handler interface in the net/http package
func (h customHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {

    // ParseForm will parse query string values and make r.Form available
    r.ParseForm()

    // r.Form is map of query string parameters
    // its' type is url.Values, which in turn is a map[string][]string
    queryMap := r.Form

    switch r.Method {
    case http.MethodGet:
        // Handle GET requests
        w.WriteHeader(http.StatusOK)
        w.Write([]byte(fmt.Sprintf("Query string values: %s", queryMap)))
        return
    case http.MethodPost:
        // Handle POST requests
        body, err := ioutil.ReadAll(r.Body)
        if err != nil {
            // Error occurred while parsing request body
            w.WriteHeader(http.StatusBadRequest)
            return
        }
        w.WriteHeader(http.StatusOK)
        w.Write([]byte(fmt.Sprintf("Query string values: %s\nBody posted: %s", queryMap, body)))
        return
    }

    // Other HTTP methods (eg PUT, PATCH, etc) are not handled by the above
    // so inform the client with appropriate status code
    w.WriteHeader(http.StatusMethodNotAllowed)
}

func main() {
    // All URLs will be handled by this function
    // http.Handle, similarly to http.HandleFunc
    // uses the DefaultServeMux
    http.Handle("/", customHandler{})

    // Continue to process new requests until an error occurs
    log.Fatal(http.ListenAndServe(":8080", nil))
}

Échantillon curl sortie:

$ curl -i 'localhost:8080?city=Seattle&state=WA' -H 'Content-Type: text/plain' -X GET
HTTP/1.1 200 OK
Date: Fri, 02 Sep 2016 16:36:24 GMT
Content-Length: 51
Content-Type: text/plain; charset=utf-8

Query string values: map[city:[Seattle] state:[WA]]%

$ curl -i 'localhost:8080?city=Seattle&state=WA' -H 'Content-Type: text/plain' -X POST -d "some post data"
HTTP/1.1 200 OK
Date: Fri, 02 Sep 2016 16:36:35 GMT
Content-Length: 79
Content-Type: text/plain; charset=utf-8

Query string values: map[city:[Seattle] state:[WA]]
Body posted: some post data%

$ curl -i 'localhost:8080?city=Seattle&state=WA' -H 'Content-Type: text/plain' -X PUT
HTTP/1.1 405 Method Not Allowed
Date: Fri, 02 Sep 2016 16:36:41 GMT
Content-Length: 0
Content-Type: text/plain; charset=utf-8


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow