ProHoster > Blog > Uprava > Razvoj spletnih strežnikov v Golangu - od enostavnega do kompleksnega
Razvoj spletnih strežnikov v Golangu - od enostavnega do kompleksnega
Pred petimi leti sem začel razviti Gophish, je to ponudilo priložnost za učenje golanga. Spoznal sem, da je Go močan jezik, ki ga dopolnjujejo številne knjižnice. Go je vsestranski: zlasti ga je mogoče brez težav uporabljati za razvoj aplikacij na strani strežnika.
Ta članek govori o pisanju strežnika v Go. Začnimo s preprostimi stvarmi, kot je "Hello world!" in končajmo z aplikacijo z naslednjimi zmogljivostmi:
- Uporaba Let's Encrypt za HTTPS.
— Delo kot usmerjevalnik API.
— Delo z vmesno programsko opremo.
— Obdelava statičnih datotek.
— Pravilna zaustavitev.
Po tem, če zaženete aplikacijo in odprete stran localhost, potem boste takoj videli besedilo "Pozdravljen, svet!" (če seveda vse deluje pravilno).
Pozneje bomo upravljalnik večkrat uporabili, a najprej razumemo, kako vse deluje.
net/http
Primer je uporabil paket net/http, je primarno orodje v Go za razvoj strežnikov in odjemalcev HTTP. Da bi razumeli kodo, poglejmo pomen treh pomembnih elementov: http.Handler, http.ServeMux in http.Server.
HTTP obdelovalci
Ko prejmemo zahtevo, jo upravljavec analizira in ustvari odgovor. Obdelovalci v Go so implementirani na naslednji način:
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
Prvi primer uporablja pomočno funkcijo http.HandleFunc. Ovije drugo funkcijo, ki prevzame http.ResponseWriter in http.Request v ServeHTTP.
Z drugimi besedami, obdelovalci v Golangu so predstavljeni v enem vmesniku, ki daje programerju veliko možnosti. Tako je na primer vmesna programska oprema implementirana z uporabo obdelovalca, kjer ServeHTTP najprej naredi nekaj, nato pa pokliče metodo ServeHTTP drugega obdelovalca.
Kot je navedeno zgoraj, upravljavci preprosto ustvarijo odgovore na zahteve. Toda kateri določen vodnik naj se uporabi v določenem trenutku?
Usmerjanje zahtev
Za pravo izbiro uporabite HTTP multiplekser. V številnih knjižnicah se imenuje muxer ali usmerjevalnik, vendar so vsi enaki. Funkcija multiplekserja je analizirati pot zahteve in izbrati ustrezen upravljavec.
Če potrebujete podporo za zapleteno usmerjanje, je bolje uporabiti knjižnice tretjih oseb. Nekaj najnaprednejših - gorila/mux и go-chi/chi, te knjižnice omogočajo brez težav izvajanje vmesne obdelave. Z njihovo pomočjo lahko konfigurirate usmerjanje z nadomestnimi znaki in izvajate številne druge naloge. Njihova prednost je združljivost s standardnimi obdelovalniki HTTP. Posledično lahko napišete preprosto kodo, ki jo lahko v prihodnosti spremenite.
Delo s kompleksnimi okviri v normalnih razmerah bo zahtevalo nestandardne rešitve, kar znatno oteži uporabo privzetih obdelovalcev. Za ustvarjanje velike večine aplikacij bo zadostovala kombinacija privzete knjižnice in preprostega usmerjevalnika.
Obdelava poizvedbe
Poleg tega potrebujemo komponento, ki bo "poslušala" dohodne povezave in preusmerila vse zahteve k pravilnemu upravljavcu. http.Server se zlahka spopade s to nalogo.
Naslednje prikazuje, da je strežnik odgovoren za vsa opravila, ki so povezana z obdelavo povezave. To na primer deluje s protokolom TLS. Za izvedbo klica http.ListenAndServer se uporablja standardni strežnik HTTP.
Zdaj pa poglejmo bolj zapletene primere.
Dodajanje Let's Encrypt
Naša aplikacija privzeto deluje po protokolu HTTP, vendar je priporočljiva uporaba protokola HTTPS. To lahko storite brez težav v Go. Če ste prejeli potrdilo in zasebni ključ, potem je dovolj, da registrirate ListenAndServeTLS s pravilnim potrdilom in datotekami ključev.
Let's Encrypt ponuja brezplačne certifikate s samodejnim obnavljanjem. Za uporabo storitve potrebujete paket autocert.
Najlažji način za konfiguracijo je uporaba metode autocert.NewListener v kombinaciji s http.Serve. Metoda vam omogoča pridobivanje in posodabljanje potrdil TLS, medtem ko strežnik HTTP obdeluje zahteve:
Če odpremo v brskalniku example.com, bomo prejeli odgovor HTTPS »Pozdravljen, svet!«
Če potrebujete podrobnejšo konfiguracijo, uporabite upravitelja autocert.Manager. Nato ustvarimo svoj primerek http.Server (do zdaj smo ga uporabljali privzeto) in dodamo upravitelja strežniku TLSConfig:
To je preprost način za implementacijo popolne podpore HTTPS s samodejnim obnavljanjem potrdila.
Dodajanje poti po meri
Privzeti usmerjevalnik, ki je vključen v standardno knjižnico, je dober, vendar je zelo osnovni. Večina aplikacij zahteva bolj zapleteno usmerjanje, vključno z ugnezdenimi in nadomestnimi potmi, ali postopek za nastavitev vzorcev poti in parametrov.
V tem primeru je vredno uporabiti pakete gorila/mux и go-chi/chi. S slednjim se bomo naučili delati – primer je prikazan spodaj.
Podana je datoteka api/v1/api.go, ki vsebuje poti za naš API:
/ HelloResponse is the JSON representation for a customized message
type HelloResponse struct {
Message string `json:"message"`
}
// HelloName returns a personalized JSON message
func HelloName(w http.ResponseWriter, r *http.Request) {
name := chi.URLParam(r, "name")
response := HelloResponse{
Message: fmt.Sprintf("Hello %s!", name),
}
jsonResponse(w, response, http.StatusOK)
}
// NewRouter returns an HTTP handler that implements the routes for the API
func NewRouter() http.Handler {
r := chi.NewRouter()
r.Get("/{name}", HelloName)
return r
}
V glavni datoteki nastavimo predpono api/vq za poti.
Nato lahko to namestimo na naš glavni usmerjevalnik pod predpono api/v1/ nazaj v naši glavni aplikaciji:
// NewRouter returns a new HTTP handler that implements the main server routes
func NewRouter() http.Handler {
router := chi.NewRouter()
router.Mount("/api/v1/", v1.NewRouter())
return router
}
http.Serve(autocert.NewListener("example.com"), NewRouter())
Enostavnost Go-jevega dela s kompleksnimi potmi omogoča poenostavitev strukturiranja in vzdrževanja velikih, kompleksnih aplikacij.
Delo z vmesno programsko opremo
Staging vključuje ovijanje enega upravljalnika HTTP z drugim, kar omogoča hitro izvajanje preverjanja pristnosti, stiskanja, beleženja in več drugih funkcij.
Kot primer si poglejmo vmesnik http.Handler; uporabili ga bomo za pisanje upravljalnika, ki overja uporabnike storitev.
func RequireAuthentication(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !isAuthenticated(r) {
http.Redirect(w, r, "/login", http.StatusTemporaryRedirect)
return
}
// Assuming authentication passed, run the original handler
next.ServeHTTP(w, r)
})
}
Obstajajo usmerjevalniki tretjih oseb, kot je chi, ki vam omogočajo razširitev funkcionalnosti vmesne programske opreme.
Delo s statičnimi datotekami
Standardna knjižnica Go vključuje zmožnosti za delo s statično vsebino, vključno s slikami, datotekami JavaScript in CSS. Do njih lahko dostopate prek funkcije http.FileServer. Vrne rokovalnik, ki služi datotekam iz določenega imenika.
Vsekakor si velja zapomniti, da http.Dir prikaže vsebino imenika, če ta ne vsebuje glavne datoteke index.html. V tem primeru uporabite paket, da preprečite ogrožanje imenika unindexed.
Pravilna zaustavitev
Go ima tudi funkcijo, imenovano elegantna zaustavitev strežnika HTTP. To lahko storite z metodo Shutdown(). Strežnik se zažene v goroutini, nato pa se kanal posluša, da prejme prekinitveni signal. Takoj ko je signal prejet, se strežnik izklopi, vendar ne takoj, ampak po nekaj sekundah.
handler := server.NewRouter()
srv := &http.Server{
Handler: handler,
}
go func() {
srv.Serve(autocert.NewListener(domains...))
}()
// Wait for an interrupt
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
<-c
// Attempt a graceful shutdown
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
srv.Shutdown(ctx)
Kot zaključek
Go je zmogljiv jezik s skoraj univerzalno standardno knjižnico. Njegove privzete zmogljivosti so zelo široke in jih je mogoče izboljšati z uporabo vmesnikov - to vam omogoča razvoj resnično zanesljivih strežnikov HTTP.