Zoeken…


Opmerkingen

http.ServeMux biedt een multiplexer die handlers aanroept voor HTTP-aanvragen.

Alternatieven voor de standaard bibliotheekmultiplexer zijn onder meer:

HTTP Hallo wereld met aangepaste server en 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())
}

Druk op Ctrl + C om het proces te stoppen.

Hallo Wereld

De typische manier om te beginnen met het schrijven van webservers in golang is door de standaard bibliotheek net/http module te gebruiken.

Er is ook een tutorial voor dit hier .

De volgende code gebruikt het ook. Hier is de eenvoudigst mogelijke HTTP-serverimplementatie. Het antwoordt "Hello World" op elk HTTP-verzoek.

Sla de volgende code op in een server.go bestand in uw werkruimten.

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))
}

U kunt de server gebruiken met:

$ go run server.go

Of u kunt compileren en uitvoeren.

$ go build server.go
$ ./server

De server luistert naar de opgegeven poort ( :8080 ). Je kunt het testen met elke HTTP-client. Hier is een voorbeeld met 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!

Druk op Ctrl + C om het proces te stoppen.

Een handlerfunctie gebruiken

HandleFunc registreert de handlerfunctie voor het gegeven patroon in de server mux (router).

U kunt passeren om een anonieme functie te definiëren, zoals we hebben gezien in het basis Hello World- voorbeeld:

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

Maar we kunnen ook een HandlerFunc type doorgeven. Met andere woorden, we kunnen elke functie doorgeven die de volgende handtekening respecteert:

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

We kunnen het vorige voorbeeld herschrijven en de verwijzing doorgeven aan een eerder gedefinieerde HandlerFunc . Hier is het volledige voorbeeld:

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))
}

Natuurlijk kunt u verschillende functiehandlers voor verschillende paden definiëren.

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))
}

Dit is de uitvoer met 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

Maak een HTTPS-server

Genereer een certificaat

Voor het uitvoeren van een HTTPS-server is een certificaat vereist. Het genereren van een zelfondertekend certificaat met openssl wordt gedaan door deze opdracht uit te voeren:

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

De parameters zijn:

  • req Gebruik de tool voor het aanvragen van certificaten
  • x509 Maakt een zelfondertekend certificaat
  • newkey rsa:4096 Maakt een nieuwe sleutel en certificaat met behulp van de RSA-algoritmen met een sleutellengte van 4096 bit
  • sha256 Forces de SHA256 hashing-algoritmen die grote browsers als veilig beschouwen (in het jaar 2017)
  • nodes Schakelt de wachtwoordbeveiliging voor de persoonlijke sleutel uit. Zonder deze parameter moest uw server u elke keer om het wachtwoord vragen.
  • keyout het bestand waar de sleutel moet worden geschreven
  • out Namen van het bestand waar het certificaat moet worden geschreven
  • subj Definieert de domeinnaam waarvoor dit certificaat geldig is
  • days Hoeveel dagen moet dit certificaat geldig zijn? 3650 zijn ca. 10 jaar.

Opmerking: een zelfondertekend certificaat kan bijvoorbeeld worden gebruikt voor interne projecten, debuggen, testen, enz. Elke browser zal vermelden dat dit certificaat niet veilig is. Om dit te voorkomen, moet het certificaat worden ondertekend door een certificeringsinstantie. Meestal is dit niet gratis beschikbaar. Een uitzondering is de beweging "Let's Encrypt": https://letsencrypt.org

De benodigde Go-code

U kunt TLS voor de server configureren met de volgende code. cert.pem en key.pem zijn uw SSL-certificaat en sleutel, die zijn gegenereerd met de bovenstaande opdracht.

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))
}

Reageren op een HTTP-verzoek met behulp van sjablonen

Antwoorden kunnen met behulp van sjablonen in Go naar een http.ResponseWriter worden geschreven. Dit is een handig hulpmiddel als u dynamische pagina's wilt maken.

(Ga naar de Go Templates Documentation- pagina voor meer informatie over hoe Sjablonen in Go werken.)

Doorgaan met een eenvoudig voorbeeld om de html/template om te reageren op een HTTP-aanvraag:

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)
    }
}

Waar, de inhoud van

  1. welcomeform.html zijn:
<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 zijn:
<head>
    <title> Greetings, {{.Name}} </title>
</head>
<body>
    Greetings, {{.Name}}.<br>
    We know you are a {{.nationality}}!
</body>

Notitie:

  1. Zorg ervoor dat de .html bestanden in de juiste map staan.

  2. Wanneer http://localhost:8080/ kan worden bezocht na het starten van de server.

  3. Zoals te zien is na het verzenden van het formulier, kon het niet-geëxporteerde nationaliteitsveld van de struct niet worden ontleed door het sjabloonpakket, zoals verwacht.

Inhoud presenteren met ServeMux

Een eenvoudige statische bestandsserver ziet er als volgt uit:

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)
}

Omgaan met http-methode, toegang krijgen tot queryreeksen en aanvraagtekst

Hier zijn een eenvoudig voorbeeld van enkele veelvoorkomende taken met betrekking tot het ontwikkelen van een API, waarbij onderscheid wordt gemaakt tussen de HTTP-methode van het verzoek, toegang krijgen tot de tekenreekswaarden en toegang krijgen tot de hoofdtekst van het verzoek.

Middelen

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))
}

Voorbeeld kruloutput:

$ 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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow