Sök…


Anmärkningar

http.ServeMux tillhandahåller en multiplexer som anropar hanterare för HTTP-förfrågningar.

Alternativ till standardbiblioteksmultiplexern inkluderar:

HTTP Hello World med anpassad server och 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())
}

Tryck på Ctrl + C för att stoppa processen.

Hej världen

Det typiska sättet att börja skriva webbserver i golang är att använda standardbibliotekets net/http modul.

Det finns också en tutorial för det här .

Följande kod använder den också. Här är den enklaste implementeringen av HTTP-servern. Den svarar "Hello World" på alla HTTP-förfrågningar.

Spara följande kod i en server.go fil i arbetsytorna.

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

Du kan köra servern med:

$ go run server.go

Eller så kan du kompilera och springa.

$ go build server.go
$ ./server

Servern lyssnar på den angivna porten ( :8080 ). Du kan testa det med valfri HTTP-klient. Här är ett exempel med 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!

Tryck på Ctrl + C för att stoppa processen.

Använda en hanteringsfunktion

HandleFunc registrerar hanterarfunktionen för det givna mönstret i servermux (router).

Du kan passera definiera en anonym funktion, som vi har sett i det grundläggande Hello World- exemplet:

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

Men vi kan också passera en HandlerFunc typ. Med andra ord kan vi passera alla funktioner som respekterar följande signatur:

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

Vi kan skriva om det föregående exemplet och skicka referensen till ett tidigare definierat HandlerFunc . Här är det fullständiga exemplet:

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

Naturligtvis kan du definiera flera funktionshanterare för olika vägar.

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

Här är utgången med 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

Skapa en HTTPS-server

Generera ett certifikat

För att köra en HTTPS-server krävs ett certifikat. Generera ett openssl certifikat med openssl görs genom att utföra detta kommando:

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

Parametrarna är:

  • req Använd certifikatförfrågningsverktyget
  • x509 Skapar ett x509 certifikat
  • newkey rsa:4096 Skapar en ny nyckel och certifikat med RSA-algoritmer med 4096 bitars nyckellängd
  • sha256 SHA256-hashningsalgoritmer som stora webbläsare anser vara säkra (år 2017)
  • nodes Inaktiverar lösenordsskyddet för den privata nyckeln. Utan denna parameter var din server tvungen att be dig om lösenordet varje gång det startar.
  • keyout filen där nyckeln ska skrivas
  • out Namnger filen där certifikatet ska skrivas
  • subj Definierar det domännamn som detta certifikat är giltigt för
  • days Fow hur många dagar ska detta certifikat vara giltigt? 3650 är ungefär 10 år.

Obs: Ett självsignerat certifikat kan användas till exempel för interna projekt, felsökning, testning osv. Alla webbläsare där ute kommer att nämna att certifikatet inte är säkert. För att undvika detta måste certifikatet undertecknas av en certifieringsmyndighet. Oftast är detta inte tillgängligt gratis. Ett undantag är rörelsen "Låt oss kryptera": https://letsencrypt.org

Den nödvändiga Go-koden

Du kan hantera konfigurering av TLS för servern med följande kod. cert.pem och key.pem är ditt SSL-certifikat och nyckel, som genererades med kommandot ovan.

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

Svara på en HTTP-begäran med hjälp av mallar

Svar kan skrivas till en http.ResponseWriter hjälp av mallar i Go. Detta visar sig vara ett praktiskt verktyg om du vill skapa dynamiska sidor.

(För att lära dig hur mallar fungerar i Go, besök sidan med mallar för dokumentation .)

Fortsätter med ett enkelt exempel för att använda html/template att svara på en HTTP-begäran:

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

Var, innehållet i

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

Notera:

  1. Se till att .html filerna finns i rätt katalog.

  2. När http://localhost:8080/ kan besökas efter att servern startats.

  3. Som det kan ses efter att formuläret har skickats in, kunde strukturen som inte exporteras medborgarskap inte analyseras av mallpaketet, som förväntat.

Serverar innehåll med ServeMux

En enkel statisk filserver ser ut så här:

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

Hantering av http-metod, åtkomst till frågesträngar och förfrågningsorgan

Här är ett enkelt exempel på några vanliga uppgifter relaterade till att utveckla ett API, som skiljer mellan HTTP-metoden för begäran, åtkomst till frågesträngsvärden och åtkomst till förfrågningsorganet.

Resurser

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

Provkrullutgång:

$ 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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow