
Viis aastat tagasi alustasin , see andis võimaluse Golangi õppimiseks. Mõistsin, et Go on võimas keel, mille võimalusi täiendavad mitmed teegid. Go on universaalne: selle abil on lihtne arendada serverirakendusi.
See artikkel on pühendatud Go-s serveri kirjutamisele. Alustame lihtsatest asjadest, nagu "Tere maailm!", ja lõpetame rakendusega, millel on järgmised võimalused:
— Let’s Encrypti kasutamine HTTPS-i jaoks.
— Töö API marsruutijana.
— Töö middleware’iga.
— Statiliste failide töötlemine.
— Korralik lõpetamine.
Skillbox soovitab: Praktiline kursus .
Tuletame meelde: kõigile «Habra» lugejatele — 10 000 rubla soodustus, kui registreerite end Skillboxi mis tahes kursusele promokoodi «Habr» abil.
Tere, maailm!
Veebiserveri loomine Go-s on väga kiire. Siin on näide töötlejast, mis naaseb lubatud "Tere, maailm!".
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Tere maailm!")
})
http.ListenAndServe(":80", nil)
}Pärast seda, kui rakendus käivitada ja lehte avada , näete kohe teksti "Tere, maailm!" (loomulikult, kui kõik töötab õigesti).
Edasi kavatseme töötlejat mitu korda kasutada, kuid esmalt mõistame, kuidas kõik on üles seatud.
net/http
Näites kasutati paketti , mis on Go-s peamine vahend serverite ja HTTP-kliendi arendamiseks. Koodi parema mõistmise nimel tutvume kolme olulise elemendi tähendusega: http.Handler, http.ServeMux ja http.Server.
HTTP töötlejad
Kui saame päringu, analüüsib töötleja selle ja vormib vastuse. Go-s on töötlejad rakendatud järgmiselt:
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}Esimeses näites kasutatakse abifunktsiooni http.HandleFunc. See ümbritseb teise funktsiooni, mis omakorda võtab vastu http.ResponseWriter ja http.Request funktsioonis ServeHTTP.
Teisiti öeldes, on töötlejad Golangis esitatud ühtse liidesena, mis annab programmeerijale palju võimalusi. Näiteks rakendatakse middleware töötleja kaudu, kus ServeHTTP teeb kõigepealt midagi ja seejärel kutsub teise töötleja ServeHTTP meetodi.
Nagu juba mainitud, kujundavad töötlejad lihtsalt vastuseid päringutele. Kuid millist töötlejat on konkreetsel hetkel vaja kasutada?
Päringute marsruutimine
Õige valiku tegemiseks kasutage HTTP-multiplexerit. Mitmes raamatukogus nimetatakse seda muxeriks või ruuteriks, kuid tõepoolest on need kõik ühesugused. Multiplexer'i funktsioon on analüüsida päringu teed ja valida vastav töötleja.
Kui on vajalik keeruka marsruutimise tugi, siis on parem kasutada kolmandate osapoolte raamatukogusid. Üks kõige arenenumatest on ja , need raamatukogud võimaldavad hõlpsasti rakendada vahepealse töötlemise lahendusi. Nende abil saate seadistada wildcard-marsruutimise ja teisi ülesandeid. Nende eeliseks on ühilduvus standardsete HTTP-töötlejatega. Tulemusena saate kirjutada lihtsa koodi, millel on võimalus seda tulevikus kohandada.
Töötamine keerukate raamistikudega tavapärases olukorras nõuab mitte väga standardseid lahendusi, mis oluliselt raskendab vaikimisi töötlejate kasutamist. Enamik rakendusi saavad hakkama vaikimisi raamatukogu ja lihtsa ruuteriga.
Päringute töötlemine
Lisaks vajame komponenti, mis "kuulab" sisse tulevaid ühendusi ja suunab kõik päringud õige töötleja juurde. Selle ülesande täidab probleemideta http.Server.
Allpool on näidatud, et server vastutab kõigi ülesannete eest, mis on seotud ühenduste töötlemisega. Näiteks toimub siin TLS-protokolli töötlemine. http.ListenAndServeri rakendamiseks kasutatakse standardset HTTP-serverit.
Nüüd vaatame keerulisemaid näiteid.
Lisamine Let’s Encrypt
Vaikimisi töötab meie rakendus HTTP-protokolli kaudu, kuid on soovitatav kasutada HTTPS-protokolli. Go-s on see lihtne. Kui olete saanud sertifikaadi ja privaatvõtme, piisab, kui kutsuda esile ListenAndServeTLS, osutades õigele sertifikaadi ja võtme failile.
http.ListenAndServeTLS(":443", "cert.pem", "key.pem", nil)Alati on võimalik paremini teha.
pakub tasuta sertifikaate automaatse uuendamise võimalusega. Teenuse kasutamiseks on vajalik pakett autocert.
Lihtsaim viis selle seadistamiseks on kasutada autocert.NewListener meetodit koos http.Serve'iga. See meetod võimaldab hankida ja uuendada TLS-sertifikaate, samal ajal kui HTTP-server käsitleb päringuid:
http.Serve(autocert.NewListener("example.com"), nil)Kui avame brauseris , saame HTTPS-vastuse „Hello, world!”.
Kui vajame täiendavat seadistamist, on soovitatav kasutada autocert.Manager haldurit. Seejärel loome oma http.Server eksemplari (kuni siiamaani kasutasime vaikeversiooni) ja lisame halduri serveri TLSConfig'i:
m := &autocert.Manager{
Cache: autocert.DirCache("golang-autocert"),
Prompt: autocert.AcceptTOS,
HostPolicy: autocert.HostWhitelist("example.org", "www.example.org"),
}
server := &http.Server{
Addr: ":443",
TLSConfig: m.TLSConfig(),
}
server.ListenAndServeTLS("", "")See on lihtne viis täieliku HTTPS toe rakendamiseks koos automaatse sertifikaadi uuendamisega.
Kohandatud marsruutide lisamine
Standardteekide vaikemarsruuter, mis on kaasatud standardbiblioteeki, on hea, kuid väga lihtne. Enamikus rakendustes on vaja keerukamat marsruutimist, sealhulgas pesamarsruute ja wildcard-marsruute või samuti mallide ja marsruutide parameetrite määramist.
Selles olukorras on soovitatav kasutada pakette ja Meie viimane teema on see, kuidas töötada . Allpool on näide.
Antud on fail api/v1/api.go, mis sisaldab marsruute meie API-le:
/ 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
}Seadistame marsruutide eelprefiksiks api/vq peafailis.
Saame selle mountida meie peamise marsruudile api/v1/ prefiksi alla tagasi meie põhiäpis:
// 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())Go-s keeruliste marsruutidega töötamise lihtsus võimaldab lihtsustada suuremate keeruliste rakenduste haldamist.
Töötamine vahekihiga
Vahekihtide töötamisel ümbritsetakse ühte HTTP-käsitlejat teisega, mis võimaldab kiiresti teostada autentimist, tihendamist, logimist ja mõningaid muid funktsioone.
Näiteks vaatame http.Handler liidest, millega kirjutame HTTP-käsitleja, mis teostab teenuse kasutajate autentimist.
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
}
// Eeldades, et autentimine on läbitud, käivita algne käsitleja
next.ServeHTTP(w, r)
})
}On ka kolmandate osapoolte marsruuterid, nagu chi, mis võimaldavad laiendada vahekihitöötluse funktsionaalsust.
Töötamine staatiliste failidega
Go standardraamatukogus on olemas võimalused staatilise sisu töötlemiseks, sealhulgas piltide ning JavaScripti ja CSS-failide jaoks. Neile pääseb juurde funktsiooni http.FileServer kaudu, mis tagastab töötleja, mis jagab faile määratud kataloogist.
func NewRouter() http.Handler {
router := chi.NewRouter()
r.Get("/{name}", HelloName)
// Staatiliste failide jagamise seadistus
staticPath, _ := filepath.Abs("../../../static/")
fs := http.FileServer(http.Dir(staticPath))
router.Handle("/*", fs)
return rOluline on meeles pidada, et http.Dir kuvab katalooge ainult siis, kui seal ei ole põhifaili index.html. Sellisel juhul, et vältida katalooge riskimist, tuleks kasutada paketti .
Korrektselt töö lõpetamine
Go-s on olemas ka selline funktsioon nagu HTTP-serveri korrektselt töö lõpetamine. Seda saab teha meetodi Shutdown() abil. Server käivitatakse goroutine'is ning seejärel kuulatakse signaali katkestamise vastuvõtmiseks. Nii varsti kui signaal on saadud, lülitatakse server välja, kuid mitte kohe, vaid mõne sekundi pärast.
handler := server.NewRouter()
srv := &http.Server{
Handler: handler,
}
go func() {
srv.Serve(autocert.NewListener(domains...))
}()
// Oota katkestust
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
<-c
// Proovi korralikku sulgemist
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
srv.Shutdown(ctx)Kokkuvõtteks
Go — võimas keel, millel on praktiliselt universaalne standardraamatukogu. Selle vaikimisi võimalused on üsna laiad, ja neid saab tugevdada liideste abil — see võimaldab arendada tõeliselt usaldusväärseid HTTP-servereid.
Skillbox soovitab:
- Kaheaastane praktiline kursus .
- Hariduslik veebikursus .
- Praktiline aastakursus .
Allikas: habr.com
