Web serveru izstrÄde GolangÄ - no vienkÄrÅ”as lÄ«dz sarežģītai
Pirms pieciem gadiem es sÄku izstrÄdÄt Gophish, tas sniedza iespÄju apgÅ«t Golangu. Es sapratu, ka Go ir spÄcÄ«ga valoda, ko papildina daudzas bibliotÄkas. Go ir daudzpusÄ«gs: jo Ä«paÅ”i to var izmantot, lai bez problÄmÄm izstrÄdÄtu servera puses lietojumprogrammas.
Å is raksts ir par servera rakstÄ«Å”anu programmÄ Go. SÄksim ar vienkÄrÅ”Äm lietÄm, piemÄram, "Sveika pasaule!", un beigsim ar lietojumprogrammu ar Å”ÄdÄm iespÄjÄm:
- Izmantojot Let's Encrypt HTTPS.
ā Darbs kÄ API marÅ”rutÄtÄjs.
ā Darbs ar starpprogrammatÅ«ru.
ā Statisko failu apstrÄde.
ā Pareiza izslÄgÅ”ana.
ProgrammÄ Go varat izveidot tÄ«mekļa serveri ļoti Ätri. Å eit ir piemÄrs, kÄ izmantot apdarinÄtÄju, kas atgriež iepriekÅ” apsolÄ«to āSveika, pasaule!ā.
PÄc tam, ja palaižat lietojumprogrammu un atverat lapu localhost, tad uzreiz redzÄsit tekstu āSveika, pasaule!ā (ja viss darbojas pareizi, protams).
VÄlÄk mÄs izmantosim apdarinÄtÄju vairÄkas reizes, taÄu vispirms sapratÄ«sim, kÄ viss darbojas.
net/http
PiemÄrÄ izmantota pakotne net/http, tas ir galvenais Go rÄ«ks gan serveru, gan HTTP klientu izstrÄdei. Lai saprastu kodu, sapratÄ«sim trÄ«s svarÄ«gu elementu nozÄ«mi: http.Handler, http.ServeMux un http.Server.
HTTP apstrÄdÄtÄji
Kad mÄs saÅemam pieprasÄ«jumu, apstrÄdÄtÄjs to analizÄ un Ä£enerÄ atbildi. ApdarinÄtÄji pakalpojumÄ Go tiek ieviesti Å”Ädi:
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
PirmajÄ piemÄrÄ tiek izmantota http.HandleFunc palÄ«ga funkcija. Tas ietver citu funkciju, kas savukÄrt pÄrÅem http.ResponseWriter un http.Request pakalpojumÄ ServeHTTP.
Citiem vÄrdiem sakot, Golang apstrÄdÄtÄji tiek parÄdÄ«ti vienÄ saskarnÄ, kas programmÄtÄjam sniedz daudz iespÄju. TÄ, piemÄram, starpprogrammatÅ«ra tiek ieviesta, izmantojot apdarinÄtÄju, kur ServeHTTP vispirms kaut ko dara un pÄc tam izsauc cita apdarinÄtÄja ServeHTTP metodi.
KÄ minÄts iepriekÅ”, apstrÄdÄtÄji vienkÄrÅ”i Ä£enerÄ atbildes uz pieprasÄ«jumiem. Bet kurÅ” konkrÄts apdarinÄtÄjs bÅ«tu jÄizmanto konkrÄtÄ brÄ«dÄ«?
PieprasÄ«t marÅ”rutÄÅ”anu
Lai izdarÄ«tu pareizo izvÄli, izmantojiet HTTP multipleksoru. DaudzÄs bibliotÄkÄs to sauc par muxer vai router, taÄu tie visi ir viens un tas pats. Multipleksera funkcija ir analizÄt pieprasÄ«juma ceļu un izvÄlÄties atbilstoÅ”o apstrÄdÄtÄju.
Ja jums ir nepiecieÅ”ams atbalsts sarežģītai marÅ”rutÄÅ”anai, labÄk ir izmantot treÅ”o puÅ”u bibliotÄkas. Daži no vismodernÄkajiem - gorilla/mux Šø go-chi/chi, Ŕīs bibliotÄkas ļauj bez problÄmÄm Ä«stenot starpapstrÄdi. Ar viÅu palÄ«dzÄ«bu jÅ«s varat konfigurÄt aizstÄjÄjzÄ«mju marÅ”rutÄÅ”anu un veikt vairÄkus citus uzdevumus. To priekÅ”rocÄ«ba ir saderÄ«ba ar standarta HTTP apstrÄdÄtÄjiem. RezultÄtÄ jÅ«s varat uzrakstÄ«t vienkÄrÅ”u kodu, ko nÄkotnÄ var mainÄ«t.
StrÄdÄjot ar sarežģītiem ietvariem normÄlÄ situÄcijÄ, bÅ«s nepiecieÅ”ami nestandarta risinÄjumi, un tas bÅ«tiski apgrÅ«tina noklusÄjuma apstrÄdÄtÄju izmantoÅ”anu. Lai izveidotu lielÄko daļu lietojumprogrammu, pietiks ar noklusÄjuma bibliotÄkas un vienkÄrÅ”a marÅ”rutÄtÄja kombinÄciju.
VaicÄjumu apstrÄde
TurklÄt mums ir nepiecieÅ”ams komponents, kas ānoklausÄ«siesā ienÄkoÅ”os savienojumus un novirzÄ«s visus pieprasÄ«jumus uz pareizo apstrÄdÄtÄju. http.Serveris var viegli tikt galÄ ar Å”o uzdevumu.
TÄlÄk redzams, ka serveris ir atbildÄ«gs par visiem uzdevumiem, kas saistÄ«ti ar savienojuma apstrÄdi. Tas, piemÄram, darbojas, izmantojot TLS protokolu. Lai ieviestu http.ListenAndServer izsaukumu, tiek izmantots standarta HTTP serveris.
Tagad apskatÄ«sim sarežģītÄkus piemÄrus.
Pievienojot Let's Encrypt
PÄc noklusÄjuma mÅ«su lietojumprogramma darbojas, izmantojot HTTP protokolu, taÄu ieteicams izmantot HTTPS protokolu. To var izdarÄ«t bez problÄmÄm Go. Ja esat saÅÄmis sertifikÄtu un privÄto atslÄgu, tad pietiek reÄ£istrÄt ListenAndServeTLS ar pareizajiem sertifikÄta un atslÄgu failiem.
Let's Encrypt nodroÅ”ina bezmaksas sertifikÄtus ar automÄtisku atjaunoÅ”anu. Lai izmantotu pakalpojumu, nepiecieÅ”ama pakete autocert.
VienkÄrÅ”Äkais veids, kÄ to konfigurÄt, ir izmantot autocert.NewListener metodi kombinÄcijÄ ar http.Serve. Å Ä« metode ļauj iegÅ«t un atjauninÄt TLS sertifikÄtus, kamÄr HTTP serveris apstrÄdÄ pieprasÄ«jumus:
Ja atveram pÄrlÅ«kprogrammÄ example.com, mÄs saÅemsim HTTPS atbildi "Sveika, pasaule!"
Ja nepiecieÅ”ama detalizÄtÄka konfigurÄcija, tad jÄizmanto autocert.Manager pÄrvaldnieks. PÄc tam mÄs izveidojam savu http.Server instanci (lÄ«dz Å”im mÄs to izmantojÄm pÄc noklusÄjuma) un pievienojam pÄrvaldnieku TLSConfig serverim:
Tas ir vienkÄrÅ”s veids, kÄ ieviest pilnu HTTPS atbalstu ar automÄtisku sertifikÄtu atjaunoÅ”anu.
PielÄgotu marÅ”rutu pievienoÅ”ana
Standarta bibliotÄkÄ iekļautais noklusÄjuma marÅ”rutÄtÄjs ir labs, taÄu tas ir ļoti vienkÄrÅ”s. LielÄkajai daļai lietojumprogrammu ir nepiecieÅ”ama sarežģītÄka marÅ”rutÄÅ”ana, tostarp ligzdoti un aizstÄjÄjzÄ«mju marÅ”ruti, vai procedÅ«ra ceļu modeļu un parametru iestatÄ«Å”anai.
Å ajÄ gadÄ«jumÄ ir vÄrts izmantot paketes gorilla/mux Šø go-chi/chi. MÄs uzzinÄsim, kÄ strÄdÄt ar pÄdÄjo - piemÄrs ir parÄdÄ«ts zemÄk.
Ir dots fails api/v1/api.go, kurÄ ir mÅ«su API marÅ”ruti:
/ 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
}
PÄc tam mÄs to varam pievienot mÅ«su galvenajam marÅ”rutÄtÄjam ar prefiksu api/v1/ atpakaļ mÅ«su galvenajÄ lietojumprogrammÄ:
// 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 vienkÄrÅ”ais darbs ar sarežģītiem marÅ”rutiem ļauj vienkÄrÅ”ot lielu, sarežģītu lietojumu strukturÄÅ”anu un uzturÄÅ”anu.
Darbs ar starpprogrammatūru
UzstÄdÄ«Å”ana ietver viena HTTP apdarinÄtÄja iesaiÅoÅ”anu ar citu, ļaujot Ätri veikt autentifikÄciju, saspieÅ”anu, reÄ£istrÄÅ”anu un vairÄkas citas funkcijas.
PiemÄram, aplÅ«kosim http.Handler saskarni; mÄs to izmantosim, lai uzrakstÄ«tu apdarinÄtÄju, kas autentificÄ pakalpojuma lietotÄjus.
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)
})
}
Ir treÅ”o puÅ”u marÅ”rutÄtÄji, piemÄram, chi, kas ļauj paplaÅ”inÄt starpprogrammatÅ«ras funkcionalitÄti.
Darbs ar statiskiem failiem
Go standarta bibliotÄkÄ ir iekļautas iespÄjas darbam ar statisku saturu, tostarp attÄliem, JavaScript un CSS failiem. Tiem var piekļūt, izmantojot funkciju http.FileServer. Tas atgriež apstrÄdÄtÄju, kas apkalpo failus no noteikta direktorija.
Noteikti der atcerÄties, ka http.Dir parÄda direktorijas saturu, ja tajÄ nav galvenÄ index.html faila. Å ajÄ gadÄ«jumÄ, lai novÄrstu direktorija uzlauzÅ”anu, jums vajadzÄtu izmantot pakotni unindexed.
Pareiza izslÄgÅ”ana
Go ir arÄ« funkcija, ko sauc par HTTP servera graciozu izslÄgÅ”anu. To var izdarÄ«t, izmantojot Shutdown() metodi. Serveris tiek palaists gorutÄ«nÄ, un pÄc tam tiek klausÄ«ts kanÄls, lai saÅemtu pÄrtraukuma signÄlu. TiklÄ«dz tiek saÅemts signÄls, serveris izslÄdzas, bet ne uzreiz, bet pÄc dažÄm sekundÄm.
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)
KÄ secinÄjums
Go ir spÄcÄ«ga valoda ar gandrÄ«z universÄlu standarta bibliotÄku. TÄ noklusÄjuma iespÄjas ir ļoti plaÅ”as, un tÄs var uzlabot, izmantojot saskarnes ā tas ļauj izstrÄdÄt patiesi uzticamus HTTP serverus.