Golangda veb-serverni ishlab chiqish - oddiydan murakkabgacha

Golangda veb-serverni ishlab chiqish - oddiydan murakkabgacha

Besh yil oldin men boshladim Gophishni rivojlantirish, bu Golangni o'rganish imkoniyatini berdi. Men Go bu ko'plab kutubxonalar bilan to'ldiriladigan kuchli til ekanligini angladim. Go ko'p qirrali: xususan, u hech qanday muammosiz server tomonidagi ilovalarni ishlab chiqish uchun ishlatilishi mumkin.

Ushbu maqola Go'da server yozish haqida. Keling, “Salom dunyo!” kabi oddiy narsalardan boshlaylik va quyidagi imkoniyatlarga ega dastur bilan yakunlaylik:

- HTTPS uchun Let's Encrypt-dan foydalanish.
— API router sifatida ishlash.
- O'rta dastur bilan ishlash.
— Statik fayllarni qayta ishlash.
- To'g'ri o'chirish.

Skillbox tavsiya qiladi: Amaliy kurs "Python dasturchisi noldan".

Sizga eslatib o'tamiz: "Habr" ning barcha o'quvchilari uchun - "Habr" promo-kodidan foydalangan holda har qanday Skillbox kursiga yozilishda 10 000 rubl chegirma.

Salom Dunyo!

Go'da juda tez veb-server yaratishingiz mumkin. Yuqorida va'da qilingan "Salom, dunyo!" ni qaytaradigan ishlov beruvchidan foydalanishga misol.

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

Shundan so'ng, agar siz dasturni ishga tushirsangiz va sahifani ochsangiz localhost, shunda siz darhol “Salom, dunyo!” matnini ko'rasiz. (agar hamma narsa to'g'ri ishlayotgan bo'lsa, albatta).

Biz ishlov beruvchidan keyin bir necha marta foydalanamiz, lekin avval hamma narsa qanday ishlashini tushunib olaylik.

net/http

Misol paketdan foydalangan net/http, bu ikkala server va HTTP mijozlarini ishlab chiqish uchun Go'dagi asosiy vositadir. Kodni tushunish uchun uchta muhim elementning ma'nosini tushunamiz: http.Handler, http.ServeMux va http.Server.

HTTP ishlov beruvchilari

Biz so'rovni olganimizda, ishlov beruvchi uni tahlil qiladi va javob beradi. Go-da ishlov beruvchilar quyidagicha amalga oshiriladi:

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

Birinchi misol http.HandleFunc yordamchi funksiyasidan foydalanadi. U boshqa funktsiyani o'rab oladi, bu esa o'z navbatida http.ResponseWriter va http.Request-ni ServeHTTP-ga oladi.

Boshqacha qilib aytganda, Golangdagi ishlov beruvchilar bitta interfeysda taqdim etilgan bo'lib, bu dasturchiga juda ko'p imkoniyatlarni beradi. Shunday qilib, masalan, o'rta dastur ishlov beruvchi yordamida amalga oshiriladi, bunda ServeHTTP avval biror narsa qiladi va keyin boshqa ishlov beruvchining ServeHTTP usulini chaqiradi.

Yuqorida aytib o'tilganidek, ishlov beruvchilar so'rovlarga javoblarni ishlab chiqaradilar. Lekin ma'lum bir vaqtda qaysi maxsus ishlov beruvchidan foydalanish kerak?

Marshrutni so'rash

To'g'ri tanlov qilish uchun HTTP multipleksoridan foydalaning. Bir qator kutubxonalarda u muxer yoki router deb ataladi, ammo ularning barchasi bir xil. Multiplekserning vazifasi so'rov yo'lini tahlil qilish va tegishli ishlov beruvchini tanlashdir.

Agar sizga murakkab marshrutlash uchun yordam kerak bo'lsa, unda uchinchi tomon kutubxonalaridan foydalanish yaxshiroqdir. Eng ilg'orlardan ba'zilari - gorilla/mux и go-chi/chi, bu kutubxonalar hech qanday muammosiz oraliq ishlov berishni amalga oshirish imkonini beradi. Ularning yordami bilan siz joker belgilarni marshrutlashni sozlashingiz va bir qator boshqa vazifalarni bajarishingiz mumkin. Ularning afzalligi standart HTTP ishlov beruvchilari bilan muvofiqligidir. Natijada, kelajakda o'zgartirilishi mumkin bo'lgan oddiy kod yozishingiz mumkin.

Oddiy vaziyatda murakkab ramkalar bilan ishlash nostandart echimlarni talab qiladi va bu standart ishlov beruvchilardan foydalanishni sezilarli darajada murakkablashtiradi. Ilovalarning katta qismini yaratish uchun standart kutubxona va oddiy routerning kombinatsiyasi etarli bo'ladi.

So'rovni qayta ishlash

Bundan tashqari, bizga kiruvchi ulanishlarni "tinglaydigan" va barcha so'rovlarni to'g'ri ishlov beruvchiga yo'naltiradigan komponent kerak. http.Server bu vazifani osongina bajara oladi.

Quyida server ulanishni qayta ishlash bilan bog'liq barcha vazifalar uchun javobgar ekanligini ko'rsatadi. Bu, masalan, TLS protokoli yordamida ishlaydi. http.ListenAndServer chaqiruvini amalga oshirish uchun standart HTTP serveridan foydalaniladi.

Endi murakkabroq misollarni ko'rib chiqaylik.

Keling, shifrlaymiz

Odatiy bo'lib, bizning ilovamiz HTTP protokoli orqali ishlaydi, ammo HTTPS protokolidan foydalanish tavsiya etiladi. Bu Go'da muammosiz amalga oshirilishi mumkin. Agar siz sertifikat va shaxsiy kalit olgan bo'lsangiz, ListenAndServeTLS-ni to'g'ri sertifikat va kalit fayllar bilan ro'yxatdan o'tkazish kifoya.

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

Siz har doim yaxshiroq qila olasiz.

Keling, shifrlanamiz avtomatik yangilash bilan bepul sertifikatlar beradi. Xizmatdan foydalanish uchun sizga paket kerak autocert.

Uni sozlashning eng oson yo'li autocert.NewListener usulini http.Serve bilan birgalikda ishlatishdir. Usul sizga HTTP serveri so'rovlarni qayta ishlash vaqtida TLS sertifikatlarini olish va yangilash imkonini beradi:

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

Agar biz brauzerda ochsak example.com, biz HTTPS javobini olamiz “Salom, dunyo!”

Agar sizga batafsil konfiguratsiya kerak bo'lsa, autocert.Manager menejeridan foydalaning. Keyin biz o'z http.Server misolimizni yaratamiz (hozirgacha biz uni sukut bo'yicha ishlatganmiz) va menejerni TLSConfig serveriga qo'shamiz:

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

Bu avtomatik sertifikat yangilanishi bilan to'liq HTTPS qo'llab-quvvatlashini amalga oshirishning oson yo'lidir.

Maxsus marshrutlarni qo'shish

Standart kutubxonaga kiritilgan standart router yaxshi, lekin u juda oddiy. Aksariyat ilovalar yanada murakkab marshrutlashni talab qiladi, jumladan ichki va joker belgilar marshrutlari yoki yo'l naqshlari va parametrlarini o'rnatish tartibi.

Bunday holda paketlardan foydalanishga arziydi gorilla/mux и go-chi/chi. Biz ikkinchisi bilan qanday ishlashni o'rganamiz - misol quyida ko'rsatilgan.

Bizning API uchun marshrutlarni o'z ichiga olgan api/v1/api.go fayli berilgan:

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

Biz asosiy fayldagi marshrutlar uchun api/vq prefiksini o'rnatdik.

Keyin biz buni asosiy dasturimizda api/v1/ prefiksi ostida asosiy routerimizga o'rnatishimiz mumkin:

// 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-ning murakkab marshrutlar bilan ishlash qulayligi katta, murakkab ilovalarni tuzilmasini soddalashtirish va ularga xizmat ko'rsatishni soddalashtirish imkonini beradi.

O'rta dastur bilan ishlash

Bosqichlash bir HTTP ishlov beruvchisini boshqasi bilan o'rashni o'z ichiga oladi, bu autentifikatsiya, siqish, jurnalga yozish va boshqa bir qancha funktsiyalarni tezda bajarishga imkon beradi.

Misol tariqasida http.Handler interfeysini ko'rib chiqamiz; biz undan xizmat foydalanuvchilarini autentifikatsiya qiluvchi ishlov beruvchi yozish uchun foydalanamiz.

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

O'rta dastur funksiyasini kengaytirish imkonini beruvchi chi kabi uchinchi tomon routerlari mavjud.

Statik fayllar bilan ishlash

Go standart kutubxonasi statik kontent, jumladan tasvirlar, JavaScript va CSS fayllari bilan ishlash imkoniyatlarini o'z ichiga oladi. Ularga http.FileServer funksiyasi orqali kirish mumkin. U ma'lum bir katalogdagi fayllarga xizmat ko'rsatadigan ishlov beruvchini qaytaradi.

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

Shuni esda tutish kerakki, http.Dir katalogning mazmunini ko'rsatadi, agar unda asosiy index.html fayli bo'lmasa. Bunday holda, katalogning buzilishining oldini olish uchun siz paketdan foydalanishingiz kerak unindexed.

To'g'ri o'chirish

Go'da, shuningdek, HTTP serverini oqlangan o'chirish deb nomlangan xususiyat mavjud. Buni Shutdown() usuli yordamida amalga oshirish mumkin. Server gorutinda ishga tushiriladi va keyin kanal uzilish signalini qabul qilish uchun tinglanadi. Signal qabul qilinishi bilanoq, server o'chadi, lekin darhol emas, balki bir necha soniyadan keyin.

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)

Natijada

Go - bu deyarli universal standart kutubxonaga ega kuchli til. Uning standart imkoniyatlari juda keng va ular interfeyslar yordamida kengaytirilishi mumkin - bu sizga chinakam ishonchli HTTP serverlarini ishlab chiqish imkonini beradi.

Skillbox tavsiya qiladi:

Manba: www.habr.com

a Izoh qo'shish