Żvilupp ta 'web server f'Golang - minn sempliċi għal kumpless
Ħames snin ilu bdejt tiżviluppa Gophish, dan ipprovda opportunità biex titgħallem Golang. Irrealizzajt li Go hija lingwa qawwija, ikkumplimentata minn ħafna libreriji. Go hija versatili: b'mod partikolari, tista 'tintuża biex tiżviluppa applikazzjonijiet fuq in-naħa tas-server mingħajr problemi.
Dan l-artikolu huwa dwar il-kitba ta 'server f'Go. Nibdew b'affarijiet sempliċi bħal "Hello world!" u nispiċċaw b'applikazzjoni bil-kapaċitajiet li ġejjin:
- Uża Let's Encrypt għal HTTPS.
— Jaħdem bħala router API.
— Ħidma mal-middleware.
— Ipproċessar ta' fajls statiċi.
— Tfiq korrett.
Infakkrukom:għall-qarrejja kollha ta '"Habr" - skont ta' 10 rublu meta tirreġistra fi kwalunkwe kors ta 'Skillbox billi tuża l-kodiċi promozzjonali "Habr".
Hello dinja!
Tista 'toħloq web server f'Go malajr ħafna. Hawn eżempju ta 'użu ta' handler li jirritorna l-"Hello, world!" mwiegħed hawn fuq.
Wara dan, jekk tmexxi l-applikazzjoni u tiftaħ il-paġna localhost, imbagħad immedjatament tara t-test "Hello, dinja!" (jekk kollox jaħdem sew, ovvjament).
Ser nużaw il-handler diversi drabi aktar tard, imma l-ewwel ejja nifhmu kif jaħdem kollox.
net/http
L-eżempju uża l-pakkett net/http, hija l-għodda primarja f'Go għall-iżvilupp kemm ta' servers kif ukoll ta' klijenti HTTP. Biex tifhem il-kodiċi, ejja nifhmu t-tifsira ta 'tliet elementi importanti: http.Handler, http.ServeMux u http.Server.
HTTP handlers
Meta nirċievu talba, il-handler janalizzaha u jiġġenera tweġiba. Handlers f'Go huma implimentati kif ġej:
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
L-ewwel eżempju juża l-funzjoni helper http.HandleFunc. Hija wraps funzjoni oħra, li mbagħad tieħu http.ResponseWriter u http.Request fis ServeHTTP.
Fi kliem ieħor, handlers f'Golang huma ppreżentati f'interface waħda, li tagħti ħafna għażliet lill-programmatur. Allura, pereżempju, middleware huwa implimentat bl-użu ta 'handler, fejn ServeHTTP l-ewwel jagħmel xi ħaġa u mbagħad isejjaħ il-metodu ServeHTTP ta' handler ieħor.
Kif imsemmi hawn fuq, handlers sempliċement jiġġeneraw tweġibiet għat-talbiet. Imma liema handler partikolari għandu jintuża f'punt partikolari fil-ħin?
Itlob Rotot
Biex tagħmel l-għażla t-tajba, uża multiplexer HTTP. F'numru ta 'libreriji huwa msejjaħ muxer jew router, iżda huma kollha l-istess ħaġa. Il-funzjoni tal-multiplexer hija li tanalizza l-mogħdija tat-talba u tagħżel l-immaniġġjar xieraq.
Jekk għandek bżonn appoġġ għal rotta kumplessa, allura huwa aħjar li tuża libreriji ta 'partijiet terzi. Uħud mill-aktar avvanzati - gorilla/mux и go-chi/chi, dawn il-libreriji jagħmluha possibbli li jiġi implimentat ipproċessar intermedju mingħajr problemi. Bl-għajnuna tagħhom, tista 'tikkonfigura r-routing wildcard u twettaq numru ta' kompiti oħra. Il-vantaġġ tagħhom huwa l-kompatibilità ma 'handlers HTTP standard. Bħala riżultat, tista 'tikteb kodiċi sempliċi li jista' jiġi modifikat fil-futur.
Il-ħidma ma' oqfsa kumplessi f'sitwazzjoni normali se teħtieġ soluzzjonijiet mhux standard, u dan jikkomplika b'mod sinifikanti l-użu ta 'handlers default. Biex tinħoloq il-maġġoranza l-kbira tal-applikazzjonijiet, taħlita tal-librerija default u router sempliċi tkun biżżejjed.
Ipproċessar tal-Mistoqsija
Barra minn hekk, neħtieġu komponent li "jisma" għall-konnessjonijiet deħlin u jidderieġi mill-ġdid it-talbiet kollha lill-handler korrett. http.Server jista 'faċilment jimmaniġġja dan il-kompitu.
Dan li ġej juri li s-server huwa responsabbli għall-kompiti kollha li huma relatati mal-ipproċessar tal-konnessjoni. Dan, pereżempju, jaħdem bl-użu tal-protokoll TLS. Biex timplimenta s-sejħa http.ListenAndServer, jintuża server HTTP standard.
Issa ejja nħarsu lejn eżempji aktar kumplessi.
Żieda Let's Encrypt
B'mod awtomatiku, l-applikazzjoni tagħna taħdem fuq il-protokoll HTTP, iżda huwa rakkomandat li tuża l-protokoll HTTPS. Dan jista' jsir mingħajr problemi f'Go. Jekk irċevejt ċertifikat u ċavetta privata, allura huwa biżżejjed li tirreġistra ListenAndServeTLS maċ-ċertifikat korrett u l-fajls taċ-ċavetta.
Let's Encrypt jipprovdi ċertifikati b'xejn b'tiġdid awtomatiku. Sabiex tuża s-servizz, għandek bżonn pakkett autocert.
L-eħfef mod biex jiġi kkonfigurat huwa li tuża l-metodu autocert.NewListener flimkien ma 'http.Serve. Il-metodu jippermettilek tikseb u taġġorna ċertifikati TLS waqt li s-server HTTP jipproċessa talbiet:
Jekk niftħu fil-browser example.com, se nirċievu tweġiba HTTPS "Hello, world!"
Jekk għandek bżonn konfigurazzjoni aktar dettaljata, allura għandek tuża l-maniġer autocert.Manager. Imbagħad noħolqu l-istanza http.Server tagħna stess (sa issa użajna b'mod awtomatiku) u żid il-maniġer mas-server TLSConfig:
Dan huwa mod faċli biex jiġi implimentat appoġġ HTTPS sħiħ bit-tiġdid awtomatiku taċ-ċertifikat.
Żieda ta 'rotot tad-dwana
Ir-router default inkluż fil-librerija standard huwa tajjeb, iżda huwa bażiku ħafna. Ħafna applikazzjonijiet jeħtieġu rotta aktar kumplessa, inklużi rotot nested u wildcard, jew proċedura għall-iffissar tal-mudelli u l-parametri tal-mogħdijiet.
F'dan il-każ ta 'min juża pakketti gorilla/mux и go-chi/chi. Aħna se nitgħallmu naħdmu ma 'dawn tal-aħħar - eżempju jidher hawn taħt.
Mogħti l-fajl api/v1/api.go li fih ir-rotot għall-API tagħna:
/ 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
}
Imbagħad nistgħu narmaw dan mar-router prinċipali tagħna taħt il-prefiss api/v1/ lura fl-applikazzjoni ewlenija tagħna:
// 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())
Il-faċilità ta' Go biex taħdem b'rotot kumplessi tagħmilha possibbli li tissimplifika l-istrutturar u l-manutenzjoni ta' applikazzjonijiet kbar u kumplessi.
Ħidma ma middleware
L-istadju jinvolvi t-tgeżwir ta 'handler HTTP wieħed ma' ieħor, li jagħmilha possibbli li jitwettqu malajr awtentikazzjoni, kompressjoni, illoggjar, u bosta funzjonijiet oħra.
Bħala eżempju, ejja nħarsu lejn l-interface http.Handler; aħna ser nużawha biex niktbu handler li jawtentika l-utenti tas-servizz.
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)
})
}
Hemm routers ta 'partijiet terzi, bħal chi, li jippermettulek testendi l-funzjonalità tal-middleware.
Ħidma ma 'fajls statiċi
Il-librerija standard Go tinkludi kapaċitajiet biex taħdem b'kontenut statiku, inklużi stampi, JavaScript u fajls CSS. Jistgħu jiġu aċċessati permezz tal-funzjoni http.FileServer. Jirritorna handler li jservi fajls minn direttorju speċifiku.
Żgur ta’ min jiftakar li http.Dir juri l-kontenut tad-direttorju jekk ma jkunx fih il-fajl index.html prinċipali. F'dan il-każ, biex tevita li d-direttorju jiġi kompromess, għandek tuża l-pakkett unindexed.
Tfiq korrett
Go għandu wkoll karatteristika msejħa għeluq graceful tas-server HTTP. Dan jista' jsir bl-użu tal-metodu Shutdown(). Is-server jinbeda f'goroutine, u mbagħad il-kanal jinstema' biex jirċievi sinjal ta 'interruzzjoni. Hekk kif is-sinjal jiġi riċevut, is-server jintefa, iżda mhux immedjatament, iżda wara ftit sekondi.
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)
Bħala konklużjoni
Go hija lingwa qawwija b'librerija standard kważi universali. Il-kapaċitajiet default tagħha huma wesgħin ħafna, u jistgħu jittejbu bl-użu ta' interfaces - dan jippermettilek tiżviluppa servers HTTP tassew affidabbli.