Web zerbitzariaren garapena Golang-en - sinpletik konplexura

Web zerbitzariaren garapena Golang-en - sinpletik konplexura

Duela bost urte hasi nintzen garatu Gophish, honek Golang ikasteko aukera eman zuen. Go hizkuntza indartsua dela konturatu nintzen, liburutegi askorekin osatua. Go polifazetikoa da: bereziki, zerbitzariaren aldeko aplikazioak arazorik gabe garatzeko erabil daiteke.

Artikulu hau Go-n zerbitzari bat idazteari buruzkoa da. Has gaitezen "Kaixo mundua!" bezalako gauza sinpleekin eta amaitzeko gaitasun hauek dituen aplikazio batekin:

- Let's Encrypt erabiliz HTTPSrako.
β€” API bideratzaile gisa lan egitea.
β€” Middlewarearekin lan egitea.
β€” Fitxategi estatikoen tratamendua.
β€” Itzali zuzena.

Skillbox-ek gomendatzen du: Ikastaro praktikoa "Python garatzailea hutsetik".

Gogoratzen dugu: "Habr" irakurle guztientzat - 10 errubloko deskontua "Habr" promozio-kodea erabiliz Skillbox-eko edozein ikastarotan izena ematean.

Kaixo Mundua!

Go-n web zerbitzari bat sor dezakezu oso azkar. Hona hemen goian agindutako "Kaixo, mundua!" itzultzen duen kudeatzaile bat erabiltzearen adibide bat.

package main
 
import (
"fmt"
"net/http"
)
 
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello World!")
})
http.ListenAndServe(":80", nil)
}

Horren ondoren, aplikazioa exekutatu eta orria irekitzen baduzu localhost, orduan berehala ikusiko duzu "Kaixo, mundua!" (dena ondo funtzionatzen badu, noski).

Kudeatzailea hainbat aldiz erabiliko dugu geroago, baina lehenik uler dezagun dena nola funtzionatzen duen.

net/http

Adibideak paketea erabili zuen net/http, Go-ko tresna nagusia da zerbitzariak eta HTTP bezeroak garatzeko. Kodea ulertzeko, uler dezagun hiru elementu garrantzitsuren esanahia: http.Handler, http.ServeMux eta http.Server.

HTTP kudeatzaileak

Eskaera jasotzen dugunean, kudeatzaileak aztertu eta erantzun bat sortzen du. Go-n kudeatzaileak honela ezartzen dira:

type Handler interface {
        ServeHTTP(ResponseWriter, *Request)
}

Lehenengo adibideak http.HandleFunc funtzio laguntzailea erabiltzen du. Beste funtzio bat biltzen du, eta, aldi berean, http.ResponseWriter eta http.Request ServeHTTP sartzen ditu.

Beste era batera esanda, Golang-eko kudeatzaileak interfaze bakarrean aurkezten dira, eta horrek aukera asko ematen dizkio programatzaileari. Beraz, adibidez, middleware kudeatzaile bat erabiliz inplementatzen da, non ServeHTTP lehenik zerbait egiten duen eta gero beste kudeatzaile baten ServeHTTP metodoa deitzen duen.

Goian esan bezala, kudeatzaileek eskaeren erantzunak besterik ez dituzte sortzen. Baina zein kudeatzaile zehatz erabili behar da une jakin batean?

Eskatu bideratzea

Aukera egokia egiteko, erabili HTTP multiplexera. Zenbait liburutegitan muxer edo router deitzen da, baina denak gauza bera dira. Multiplexatzailearen funtzioa eskaeraren bidea aztertzea eta kudeatzaile egokia hautatzea da.

Bideratze konplexurako laguntza behar baduzu, hobe da hirugarrenen liburutegiak erabiltzea. Aurreratuenetako batzuk - gorila/mux ΠΈ go-chi/chi, liburutegi hauek tarteko prozesamendua arazorik gabe ezartzea ahalbidetzen dute. Haien laguntzarekin, komodinen bideratzea konfigura dezakezu eta beste hainbat zeregin egin ditzakezu. Haien abantaila HTTP kudeatzaile estandarrekin bateragarria da. Ondorioz, etorkizunean alda daitekeen kode sinplea idatz dezakezu.

Egoera normal batean esparru konplexuekin lan egiteak soluzio ez-estandarrak beharko ditu, eta horrek kudeatzaile lehenetsien erabilera nabarmen zailtzen du. Aplikazio gehienak sortzeko, lehenetsitako liburutegia eta bideratzaile soil bat konbinatzea nahikoa izango da.

Kontsulten tratamendua

Horrez gain, sarrerako konexioak "entzuteko" eta eskaera guztiak kudeatzaile egokira birbideratuko dituen osagai bat behar dugu. http.Server-ek erraz kudeatu dezake zeregin hau.

Jarraian, zerbitzaria konexio-prozesatzearekin zerikusia duten zeregin guztien arduraduna dela erakusten du. Honek, adibidez, TLS protokoloa erabiliz funtzionatzen du. http.ListenAndServer deia ezartzeko, HTTP zerbitzari estandarra erabiltzen da.

Orain ikus ditzagun adibide konplexuagoak.

Let's Encrypt gehitzea

Lehenespenez, gure aplikazioa HTTP protokoloaren gainean exekutatzen da, baina HTTPS protokoloa erabiltzea gomendatzen da. Hau arazorik gabe egin daiteke Go-n. Ziurtagiria eta gako pribatua jaso badituzu, nahikoa da ListenAndServeTLS ziurtagiri eta gako fitxategi egokiekin erregistratzea.

http.ListenAndServeTLS(":443", "cert.pem", "key.pem", nil)

Beti egin dezakezu hobeto.

Enkriptatu dezagun berritze automatikoko doako ziurtagiriak eskaintzen ditu. Zerbitzua erabiltzeko, pakete bat behar duzu autocert.

Konfiguratzeko modurik errazena autocert.NewListener metodoa erabiltzea da http.Serve-rekin batera. Metodoak TLS ziurtagiriak lortzeko eta eguneratzeko aukera ematen du HTTP zerbitzariak eskaerak prozesatzen dituen bitartean:

http.Serve(autocert.NewListener("example.com"), nil)

Nabigatzailean irekitzen badugu example.com, HTTPS erantzuna jasoko dugu "Kaixo, mundua!"

Konfigurazio zehatzagoa behar baduzu, autocert.Manager kudeatzailea erabili beharko zenuke. Ondoren, gure http.Server instantzia sortuko dugu (orain arte lehenespenez erabiltzen genuen) eta kudeatzailea TLSConfig zerbitzarian gehitzen dugu:

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("", "")

Hau HTTPS laguntza osoa ezartzeko modu erraza da ziurtagiriaren berritze automatikoarekin.

Ibilbide pertsonalizatuak gehitzea

Liburutegi estandarrean sartutako bideratzaile lehenetsia ona da, baina oso oinarrizkoa da. Aplikazio gehienek bideratze konplexuagoa behar dute, habiaratuak eta komodinak barne, edo bide-ereduak eta parametroak ezartzeko prozedura bat.

Kasu honetan merezi du paketeak erabiltzea gorila/mux ΠΈ go-chi/chi. Azken honekin lan egiten ikasiko dugu - behean adibide bat erakusten da.

Gure APIrako ibilbideak dituen api/v1/api.go fitxategia ematen da:

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

Ibilbideetarako api/vq aurrizkia ezarri dugu fitxategi nagusian.

Ondoren, hau gure bideratzaile nagusian munta dezakegu api/v1/ aurrizkiaren azpian berriro gure aplikazio nagusian:

// 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-k ibilbide konplexuekin lan egiteko erraztasunak ahalbidetzen du aplikazio handi eta konplexuen egituraketa eta mantentze-lanak erraztea.

Middlewarearekin lan egitea

Eszenaratzeak HTTP kudeatzaile bat beste batekin biltzea dakar, autentifikazioa, konpresioa, erregistroa eta beste hainbat funtzio azkar egitea ahalbidetuz.

Adibide gisa, ikus dezagun http.Handler interfazea; zerbitzuen erabiltzaileak autentifikatzen dituen kudeatzaile bat idazteko erabiliko dugu.

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

Hirugarrenen bideratzaileak daude, hala nola chi, middlewarearen funtzionaltasuna zabaltzeko aukera ematen dutenak.

Fitxategi estatikoekin lan egitea

Go liburutegi estandarrak eduki estatikoarekin lan egiteko gaitasunak biltzen ditu, irudiak, JavaScript eta CSS fitxategiak barne. http.FileServer funtzioaren bidez sar daitezke. Direktorio zehatz bateko fitxategiak zerbitzatzen dituen kudeatzailea itzultzen du.

func NewRouter() http.Handler {
    router := chi.NewRouter()
    r.Get("/{name}", HelloName)
 
// Настройка Ρ€Π°Π·Π΄Π°Ρ‡ΠΈ статичСских Ρ„Π°ΠΉΠ»ΠΎΠ²
staticPath, _ := filepath.Abs("../../static/")
fs := http.FileServer(http.Dir(staticPath))
    router.Handle("/*", fs)
    
    return r

Zalantzarik gabe, merezi du gogoratzea http.Dir-ek direktorioaren edukia bistaratzen duela index.html fitxategi nagusia ez badu. Kasu honetan, direktorioa arriskuan egon ez dadin, paketea erabili beharko zenuke unindexed.

Itzali zuzena

Go-k HTTP zerbitzariaren itzaltze dotorea izeneko funtzio bat ere badu. Hau Shutdown() metodoa erabiliz egin daiteke. Zerbitzaria goroutine batean abiarazten da, eta gero kanala entzuten da eten seinale bat jasotzeko. Seinalea jaso bezain laster, zerbitzaria itzaltzen da, baina ez berehala, segundo batzuen buruan baizik.

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)

Ondorio gisa

Go hizkuntza indartsua da, liburutegi estandar ia unibertsala duena. Bere gaitasun lehenetsiak oso zabalak dira, eta interfazeak erabiliz hobetu daitezke; honek HTTP zerbitzari benetan fidagarriak garatzeko aukera ematen du.

Skillbox-ek gomendatzen du:

Iturria: www.habr.com

Gehitu iruzkin berria