Pangwangunan server wéb di Golang - ti anu sederhana dugi ka kompleks

Pangwangunan server wéb di Golang - ti anu sederhana dugi ka kompleks

Lima taun ka tukang kuring ngamimitian ngamekarkeun Gophish, ieu nyadiakeun kasempetan pikeun diajar Golang. Kuring sadar yén Go mangrupikeun basa anu kuat, dilengkepan ku seueur perpustakaan. Go mangrupikeun serbaguna: khususna, éta tiasa dianggo pikeun ngembangkeun aplikasi sisi server tanpa aya masalah.

Artikel ieu ngeunaan nulis server di Go. Hayu urang mimitian ku hal-hal sederhana sapertos "Halo dunya!" sareng ditungtungan ku aplikasi anu gaduh kamampuan ieu:

- Ngagunakeun Hayu urang Encrypt pikeun HTTPS.
- Gawé salaku router API.
- Gawe sareng middleware.
- Ngolah file statik.
- Pareum anu leres.

Skillbox nyarankeun: Kursus praktis "Pamekar Python ti mimiti".

Kami ngingetan: pikeun sakabéh pamiarsa "Habr" - diskon 10 rubles nalika enrolling dina sagala Tangtu Skillbox ngagunakeun "Habr" kode promosi.

Halo Dunya!

Anjeun tiasa nyiptakeun pangladén wéb dina Go gancang pisan. Ieu conto ngagunakeun pawang anu ngabalikeun "Halo, dunya!" jangji di luhur.

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

Saatos ieu, upami anjeun ngajalankeun aplikasi sareng muka halamanna localhost, teras anjeun bakal langsung ningali téks "Halo, dunya!" (lamun sagalana jalan leres, tangtosna).

Urang bakal ngagunakeun pawang sababaraha kali engké, tapi mimitina hayu urang ngartos kumaha sagalana jalan.

net / http

Contona dipaké iket net/http, éta alat primér dina Go pikeun ngembangkeun duanana server na HTTP klien. Pikeun ngartos kode, hayu urang ngartos harti tilu elemen penting: http.Handler, http.ServeMux na http.Server.

panangan HTTP

Nalika kami nampi pamundut, pawang nganalisa sareng ngahasilkeun tanggapan. Pawang di Go dilaksanakeun sapertos kieu:

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

Conto kahiji ngagunakeun fungsi helper http.HandleFunc. Ieu wraps fungsi sejen, anu dina gilirannana nyokot http.ResponseWriter na http.Request kana ServeHTTP.

Dina basa sejen, pawang di Golang dibere dina panganteur tunggal, nu mere loba pilihan pikeun programmer. Janten, contona, middleware dilaksanakeun nganggo panangan, dimana ServeHTTP mimiti ngalakukeun hiji hal teras nyauran metode ServeHTTP tina panangan anu sanés.

Sakumaha didadarkeun di luhur, pawang ngan saukur ngahasilkeun réspon kana pamundut. Tapi anu pawang khusus anu kedah dianggo dina waktos anu khusus?

Ménta Routing

Pikeun nyieun pilihan katuhu, make hiji HTTP multiplexer. Dina sababaraha perpustakaan disebut muxer atanapi router, tapi aranjeunna sadayana sami. Fungsi multiplexer nyaéta nganalisis jalur pamundut tur pilih Handler luyu.

Upami anjeun peryogi dukungan pikeun rute kompleks, maka langkung saé ngagunakeun perpustakaan pihak katilu. Sababaraha anu paling maju - gorila / mux и go-chi / chi, perpustakaan ieu ngamungkinkeun pikeun nerapkeun processing panengah tanpa masalah nanaon. Kalayan pitulungna, anjeun tiasa ngonpigurasikeun ruteu wildcard sareng ngalaksanakeun sababaraha pancén anu sanés. Kauntungannana nyaéta kasaluyuan sareng pawang HTTP standar. Hasilna, Anjeun bisa nulis kode basajan nu bisa dirobah dina mangsa nu bakal datang.

Gawe sareng kerangka kompléks dina kaayaan normal bakal merlukeun solusi non-standar, sarta ieu nyata complicates pamakéan pawang standar. Pikeun nyiptakeun seuseueurna aplikasi, kombinasi perpustakaan standar sareng router saderhana bakal cekap.

Ngolah pamundut

Salaku tambahan, urang peryogi komponén anu bakal "ngadangukeun" kanggo sambungan anu lebet sareng alihan sadaya pamundut ka panangan anu leres. http.Server bisa kalayan gampang nanganan tugas ieu.

Di handap ieu nunjukkeun yén server nanggungjawaban kanggo sadaya tugas anu aya hubunganana sareng pamrosésan sambungan. Ieu, contona, dianggo nganggo protokol TLS. Pikeun nerapkeun panggero http.ListenAndServer, server HTTP baku dipaké.

Ayeuna hayu urang nempo conto nu leuwih kompleks.

Nambahkeun Hayu urang Encrypt

Sacara standar, aplikasi kami nganggo protokol HTTP, tapi disarankeun pikeun nganggo protokol HTTPS. Ieu tiasa dilakukeun tanpa masalah dina Go. Upami anjeun nampi sertipikat sareng konci pribadi, maka cukup pikeun ngadaptar ListenAndServeTLS kalayan sertipikat sareng file konci anu leres.

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

Anjeun salawasna bisa ngalakukeun hadé.

Hayu urang Encrypt nyadiakeun bebas sertipikat jeung pembaharuan otomatis. Pikeun ngagunakeun jasa, anjeun peryogi pakét autocert.

Cara panggampangna pikeun ngonpigurasikeun éta nyaéta ngagunakeun metodeu autocert.NewListener dina kombinasi sareng http.Serve. Métode ieu ngamungkinkeun anjeun kéngingkeun sareng ngapdet sertipikat TLS nalika server HTTP ngolah pamundut:

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

Lamun urang muka dina browser example.com, urang bakal nampi réspon HTTPS "Halo, dunya!"

Upami anjeun peryogi konfigurasi anu langkung rinci, maka anjeun kedah nganggo manajer autocert.Manager. Teras urang ngadamel conto http.Server urang sorangan (dugi ka ayeuna urang dianggo sacara standar) sareng tambahkeun manajer ka server TLSConfig:

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

Ieu mangrupikeun cara anu gampang pikeun nerapkeun dukungan HTTPS lengkep sareng pembaharuan sertipikat otomatis.

Nambahkeun ruteu khusus

The router standar kaasup dina perpustakaan baku téh alus, tapi pisan dasar. Paling aplikasi merlukeun routing leuwih kompleks, kaasup nested na wildcard ruteu, atawa prosedur pikeun netepkeun pola jalur sarta parameter.

Dina hal ieu, éta patut ngagunakeun bungkusan gorila / mux и go-chi / chi. Urang bakal diajar kumaha carana damel sareng anu terakhir - conto dipidangkeun di handap ieu.

Dibikeun nyaéta file api/v1/api.go anu ngandung rute pikeun API kami:

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

Urang nyetel awalan api / vq pikeun ruteu dina file utama.

Urang teras tiasa pasang ieu kana router utama urang dina awalan api/v1/ deui dina aplikasi utama urang:

// 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())

Gampangna Go damel sareng rute anu kompleks ngamungkinkeun pikeun nyederhanakeun struktur sareng pangropéa aplikasi anu ageung sareng kompleks.

Gawe sareng middleware

Pementasan ngalibatkeun bungkus hiji panangan HTTP sareng anu sanés, sahingga tiasa gancang ngalaksanakeun auténtikasi, komprési, logging, sareng sababaraha fungsi anu sanés.

Salaku conto, hayu urang tingali antarmuka http.Handler; urang bakal ngagunakeun éta pikeun nyerat pawang anu nga-asténtikasi pangguna jasa.

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

Aya router pihak katilu, kayaning chi, nu ngidinan Anjeun pikeun manjangkeun fungsionalitas middleware.

Gawe sareng file statik

Perpustakaan standar Go kalebet kamampuan pikeun damel sareng eusi statik, kalebet gambar, file JavaScript sareng CSS. Éta bisa diaksés ngaliwatan fungsi http.FileServer. Éta mulih panangan anu nyayogikeun file tina diréktori khusus.

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

Eta pasti patut remembering yén http.Dir mintonkeun eusi diréktori lamun teu ngandung file index.html utama. Dina hal ieu, pikeun nyegah diréktori ti keur compromised, Anjeun kudu make paket unindexed.

Pareum anu leres

Go ogé ngagaduhan fitur anu disebut shutdown anggun tina server HTTP. Ieu tiasa dilakukeun nganggo metode Shutdown (). server ieu dimimitian dina goroutine a, lajeng saluran listened pikeun nampa sinyal interupsi. Pas sinyal ditampi, server pareum, tapi henteu langsung, tapi saatos sababaraha detik.

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)

dina kacindekan

Go mangrupikeun basa anu kuat sareng perpustakaan standar anu ampir universal. Kamampuhan standarna lega pisan, sareng aranjeunna tiasa ditingkatkeun nganggo antarmuka - ieu ngamungkinkeun anjeun pikeun ngembangkeun server HTTP anu leres-leres dipercaya.

Skillbox nyarankeun:

sumber: www.habr.com

Tambahkeun komentar