Suche…


Bemerkungen

http.ServeMux bietet einen Multiplexer, der Handler für HTTP-Anforderungen aufruft.

Alternativen zum Standard-Bibliotheksmultiplexer sind:

HTTP Hello World mit benutzerdefiniertem Server und 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())
}

Drücken Sie Strg + C , um den Vorgang zu stoppen.

Hallo Welt

Das Schreiben von Webservern in Golang beginnt in der Regel mit dem Standardmodul net/http .

Es gibt auch eine Anleitung dazu hier .

Der folgende Code verwendet es auch. Hier ist die einfachste mögliche HTTP-Server-Implementierung. Es antwortet "Hello World" auf jede HTTP-Anfrage.

Speichern Sie den folgenden Code in einer server.go Datei in Ihren Arbeitsbereichen.

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

Sie können den Server folgendermaßen ausführen:

$ go run server.go

Oder Sie können kompilieren und ausführen.

$ go build server.go
$ ./server

Der Server überwacht den angegebenen Port ( :8080 ). Sie können es mit jedem HTTP-Client testen. Hier ist ein Beispiel mit 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!

Drücken Sie Strg + C , um den Vorgang zu stoppen.

Verwenden einer Handlerfunktion

HandleFunc registriert die Handler-Funktion für das angegebene Muster im Server-Multiplexer (Router).

Sie können eine anonyme Funktion definieren, wie wir es im einfachen Hello World- Beispiel gesehen haben:

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

Wir können aber auch einen HandlerFunc Typ übergeben. Mit anderen Worten, wir können jede Funktion übergeben, die die folgende Signatur berücksichtigt:

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

Wir können das vorherige Beispiel neu schreiben, indem wir die Referenz an eine zuvor definierte HandlerFunc . Hier ist das vollständige Beispiel:

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

Natürlich können Sie mehrere Funktionshandler für verschiedene Pfade definieren.

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

Hier ist die Ausgabe mit 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

Erstellen Sie einen HTTPS-Server

Generieren Sie ein Zertifikat

Um einen HTTPS-Server betreiben zu können, ist ein Zertifikat erforderlich. Das Generieren eines selbstsignierten Zertifikats mit openssl erfolgt durch Ausführen dieses Befehls:

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

Die Parameter sind:

  • req Verwenden Sie das Zertifikatanforderungstool
  • x509 Erstellt ein selbstsigniertes Zertifikat
  • newkey rsa:4096 Erstellt einen neuen Schlüssel und ein neues Zertifikat unter Verwendung der RSA-Algorithmen mit einer Schlüssellänge von 4096 Bit
  • sha256 die SHA256-Hash-Algorithmen, die von großen Browsern als sicher eingestuft werden (Stand: 2017).
  • nodes Deaktiviert den Kennwortschutz für den privaten Schlüssel. Ohne diesen Parameter musste Ihr Server Sie bei jedem Start nach dem Kennwort fragen.
  • keyout die Datei an, wo der Schlüssel geschrieben werden soll
  • out Benennt die Datei, in die das Zertifikat geschrieben werden soll
  • subj Definiert den Domainnamen, für den dieses Zertifikat gültig ist
  • days Wie viele Tage sollte dieses Zertifikat gültig sein? 3650 sind ca. 10 Jahre.

Hinweis: Ein selbstsigniertes Zertifikat kann z. B. für interne Projekte, für das Debuggen, Testen usw. verwendet werden. In jedem Browser wird angegeben, dass dieses Zertifikat nicht sicher ist. Um dies zu vermeiden, muss das Zertifikat von einer Zertifizierungsstelle unterzeichnet werden. Meist ist dies nicht kostenlos verfügbar. Eine Ausnahme ist die Bewegung "Let's Encrypt": https://letsencrypt.org

Der notwendige Go-Code

Sie können die Konfiguration von TLS für den Server mit dem folgenden Code ausführen. cert.pem und key.pem sind Ihr SSL-Zertifikat und der Schlüssel, der mit dem obigen Befehl generiert wurde.

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

Antworten auf eine HTTP-Anforderung mithilfe von Vorlagen

Antworten können mithilfe von Vorlagen in Go in einen http.ResponseWriter werden. Dies ist ein praktisches Werkzeug, wenn Sie dynamische Seiten erstellen möchten.

(Informationen zur Funktionsweise von Vorlagen in Go finden Sie auf der Seite zur Dokumentation von Go-Vorlagen .)

Fahren Sie mit einem einfachen Beispiel fort, um die html/template zu verwenden, um auf eine HTTP-Anforderung zu antworten:

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

Wo, der Inhalt von

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

Hinweis:

  1. Stellen Sie sicher, dass sich die .html Dateien im richtigen Verzeichnis befinden.

  2. Wenn http://localhost:8080/ nach dem Start des Servers http://localhost:8080/ kann.

  3. Wie man nach dem Absenden des Formulars sehen kann, konnte das nicht exportierte Feld "Nationalität" der Struktur nicht wie erwartet vom Musterpaket analysiert werden.

Inhalte mit ServeMux bereitstellen

Ein einfacher statischer Dateiserver würde folgendermaßen aussehen:

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

Behandlung der http-Methode, Zugriff auf Abfragezeichenfolgen und Anfragetext

Im Folgenden finden Sie ein einfaches Beispiel für einige allgemeine Aufgaben, die sich auf die Entwicklung einer API beziehen, wobei zwischen der HTTP-Methode der Anforderung, dem Zugriff auf Abfragezeichenfolgen und dem Zugriff auf den Anfragetext unterschieden wird.

Ressourcen

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

Muster-Curl-Ausgabe:

$ 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
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow