Pangembangan server web ing Golang - saka prasaja nganti kompleks

Pangembangan server web ing Golang - saka prasaja nganti kompleks

Limang taun kepungkur aku miwiti ngembangake Gophish, iki menehi kesempatan kanggo sinau Golang. Aku nyadari yen Go minangka basa sing kuat, dilengkapi karo akeh perpustakaan. Go iku serbaguna: utamane, bisa digunakake kanggo ngembangake aplikasi sisih server tanpa masalah.

Artikel iki babagan nulis server ing Go. Ayo diwiwiti kanthi prasaja kaya "Hello world!" lan mungkasi aplikasi kanthi kapabilitas ing ngisor iki:

- Nggunakake Ayo Encrypt kanggo HTTPS.
- Makarya minangka router API.
- Nggarap middleware.
- Pangolahan file statis.
- Mati sing bener.

Skillbox nyaranake: Kursus praktis "Pengembang Python saka awal".

Kita ngelingake: kanggo kabeh sing maca "Habr" - diskon 10 rubel nalika ndhaptar kursus Skillbox nggunakake kode promosi "Habr".

Halo, jagad!

Sampeyan bisa nggawe server web ing Go kanthi cepet banget. Iki minangka conto nggunakake pawang sing ngasilake "Halo, jagad!" sing dijanjekake ing ndhuwur.

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

Sawise iki, yen sampeyan mbukak aplikasi lan mbukak kaca localhost, banjur sampeyan bakal langsung ndeleng teks "Halo, jagad!" (yen kabeh bisa digunakake kanthi bener, mesthi).

Kita bakal nggunakake handler kaping pirang-pirang mengko, nanging pisanan ayo kang ngerti carane kabeh bisa.

net / http

Conto digunakake paket net/http, iku alat utama ing Go kanggo ngembangake server lan klien HTTP. Kanggo ngerti kode, ayo kang ngerti makna saka telung unsur penting: http.Handler, http.ServeMux lan http.Server.

panangan HTTP

Nalika kita nampa panjalukan, pawang nganalisa lan ngasilake respon. Handler ing Go ditindakake kaya ing ngisor iki:

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

Conto pisanan nggunakake fungsi helper http.HandleFunc. Iku mbungkus fungsi liyane, kang siji njupuk http.ResponseWriter lan http.Request menyang ServeHTTP.

Ing tembung liyane, pawang ing Golang presented ing antarmuka siji, kang menehi akeh pilihan kanggo programmer. Dadi, contone, middleware dileksanakake nggunakake handler, ngendi ServeHTTP pisanan nindakake soko lan banjur nelpon cara ServeHTTP handler liyane.

Kaya sing kasebut ing ndhuwur, pawang mung ngasilake respon kanggo panjaluk. Nanging pawang tartamtu sing kudu digunakake ing wektu tartamtu?

Njaluk Routing

Kanggo nggawe pilihan sing tepat, gunakake multiplexer HTTP. Ing sawetara perpustakaan diarani muxer utawa router, nanging kabeh padha. Fungsi multiplexer punika njelasno path request lan pilih handler cocok.

Yen sampeyan butuh dhukungan kanggo rute kompleks, luwih becik nggunakake perpustakaan pihak katelu. Sawetara sing paling maju - gorila / mux ΠΈ go-chi/chi, perpustakaan iki ngidini kanggo ngleksanakake pangolahan penengah tanpa masalah. Kanthi bantuan, sampeyan bisa ngatur rute wildcard lan nindakake sawetara tugas liyane. Kauntungane yaiku kompatibilitas karo panangan HTTP standar. AkibatΓ©, sampeyan bisa nulis kode prasaja sing bisa diowahi ing mangsa ngarep.

Nggarap kerangka kompleks ing kahanan normal mbutuhake solusi non-standar, lan iki nggawe rumit panggunaan panangan standar. Kanggo nggawe mayoritas aplikasi, kombinasi perpustakaan standar lan router sing prasaja bakal cukup.

Pangolahan pitakon

Kajaba iku, kita butuh komponen sing bakal "ngrungokake" kanggo sambungan sing mlebu lan ngarahake kabeh panjaluk menyang pawang sing bener. http.Server bisa gampang nangani tugas iki.

Ing ngisor iki nuduhake yen server tanggung jawab kanggo kabeh tugas sing ana hubungane karo pangolahan sambungan. Iki, contone, dianggo nggunakake protokol TLS. Kanggo ngleksanakake panggilan http.ListenAndServer, server HTTP standar digunakake.

Saiki ayo ndelok conto sing luwih rumit.

Nambahake Ayo Encrypt

Kanthi gawan, aplikasi kita nganggo protokol HTTP, nanging disaranake nggunakake protokol HTTPS. Iki bisa rampung tanpa masalah ing Go. Yen sampeyan wis nampa sertifikat lan kunci pribadi, mula cukup kanggo ndhaptar ListenAndServeTLS kanthi sertifikat lan file kunci sing bener.

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

Sampeyan bisa tansah nindakake luwih apik.

Ayo Encrypt menehi sertifikat free karo nganyari maneh otomatis. Kanggo nggunakake layanan kasebut, sampeyan butuh paket autocert.

Cara paling gampang kanggo ngatur iku nggunakake autocert.NewListener cara ing kombinasi karo http.Serve. Cara kasebut ngidini sampeyan entuk lan nganyari sertifikat TLS nalika server HTTP ngolah panjaluk:

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

Yen kita mbukak ing browser example.com, kita bakal nampa respon HTTPS "Halo, donya!"

Yen sampeyan mbutuhake konfigurasi sing luwih rinci, sampeyan kudu nggunakake manajer autocert.Manager. Banjur kita nggawe conto http.Server kita dhewe (nganti saiki digunakake minangka standar) lan nambah manajer menyang 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("", "")

Iki minangka cara sing gampang kanggo ngetrapake dhukungan HTTPS lengkap kanthi nganyari sertifikat otomatis.

Nambahake rute khusus

Router standar sing kalebu ing perpustakaan standar apik, nanging dhasar banget. Umume aplikasi mbutuhake rute sing luwih rumit, kalebu rute nested lan wildcard, utawa prosedur kanggo nyetel pola lan paramèter path.

Ing kasus iki, iku worth nggunakake paket gorila / mux ΠΈ go-chi/chi. Kita bakal sinau cara nggarap sing terakhir - conto ditampilake ing ngisor iki.

Diwenehake yaiku file api/v1/api.go sing ngemot rute kanggo API kita:

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

Kita nyetel awalan api/vq kanggo rute ing file utama.

Kita banjur bisa masang iki menyang router utama ing ngisor api / v1 / awalan bali ing aplikasi utama kita:

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

Gampang nggarap rute rumit Go bisa nggawe gampang struktur lan pangopènan aplikasi sing kompleks.

Nggarap middleware

Pementasan kalebu mbungkus siji panangan HTTP karo liyane, supaya bisa cepet nindakake otentikasi, kompresi, logging, lan sawetara fungsi liyane.

Minangka conto, ayo goleki antarmuka http.Handler; kita bakal nggunakake aplikasi kasebut kanggo nulis pawang sing ngotentikasi pangguna layanan.

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

Ana router pihak katelu, kayata chi, sing ngidini sampeyan ngluwihi fungsi middleware.

Nggarap file statis

Pustaka standar Go kalebu kemampuan kanggo nggarap konten statis, kalebu gambar, file JavaScript lan CSS. Padha bisa diakses liwat fungsi http.FileServer. Iki ngasilake handler sing nglayani file saka direktori tartamtu.

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

Perlu dieling-eling yen http.Dir nampilake isi direktori yen ora ngemot file index.html utama. Ing kasus iki, kanggo nyegah direktori dikompromi, sampeyan kudu nggunakake paket kasebut unindexed.

Mati sing bener

Go uga duwe fitur sing diarani mateni server HTTP. Iki bisa ditindakake kanthi nggunakake metode Shutdown (). Server diwiwiti ing goroutine, banjur saluran dirungokake kanggo nampa sinyal interrupt. Sanalika sinyal ditampa, server dipateni, nanging ora langsung, nanging sawise sawetara 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)

Minangka kesimpulan

Go minangka basa sing kuat kanthi perpustakaan standar sing meh universal. Kapabilitas standar kasebut amba banget, lan bisa ditambah kanthi nggunakake antarmuka - iki ngidini sampeyan ngembangake server HTTP sing bisa dipercaya.

Skillbox nyaranake:

Source: www.habr.com

Add a comment