Pêşveçûna servera malperê li Golang - ji hêsan berbi tevlihev

Pêşveçûna servera malperê li Golang - ji hêsan berbi tevlihev

Pênc sal berê min dest pê kir Gophish pêşve bibin, ev derfetek ji bo fêrbûna Golang peyda kir. Min fêm kir ku Go zimanek hêzdar e, ku ji hêla gelek pirtûkxane ve tê tije kirin. Go pirreng e: bi taybetî, ew dikare bê pirsgirêk pêşdebirina serîlêdanên server-side were bikar anîn.

Ev gotar li ser nivîsandina serverek li Go ye. Ka em bi tiştên hêsan ên mîna "Hello dinya!" dest pê bikin û bi serîlêdanek bi kapasîteyên jêrîn bi dawî bibin:

- Ji bo HTTPS-ê Werin em şîfre bikin.
- Wekî routerek API-ê dixebitin.
- Bi navgîniyê re dixebitin.
- Pêvajoya pelên statîk.
- Girtina rast.

Skillbox pêşniyar dike: Kursa pratîk "Pêşvebirê Python ji sifirê".

Em bînin bîra xwe: ji bo hemî xwendevanên "Habr" - dema ku hûn beşdarî qursek Skillbox-ê bi karanîna koda danasînê ya "Habr" têne qeyd kirin 10 rubleyan dakêşin.

Silav, cîhan!

Hûn dikarin di Go de serverek malperê pir zû biafirînin. Li vir mînakek karanîna kargêrek heye ku "Silav, cîhan!" ya ku li jor hatî sozdayî vedigerîne.

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

Piştî vê yekê, heke hûn serîlêdanê bimeşînin û rûpelê vekin localhost, wê hingê hûn ê tavilê nivîsa "Silav, cîhan!" (heke her tişt rast dixebite, bê guman).

Em ê paşê gelek caran hilberker bikar bînin, lê pêşî em fêm bikin ka her tişt çawa dixebite.

net/http

Mînak pakêt bikar anî net/http, ew di Go de amûra bingehîn e ku hem pêşkêşker û hem jî xerîdarên HTTP pêşve bibin. Ji bo têgihîştina kodê, werin em wateya sê hêmanên girîng fam bikin: http.Handler, http.ServeMux û http.Server.

Rêvebirên HTTP

Dema ku em daxwazek distînin, hilber wê analîz dike û bersivek çêdike. Handlers in Go bi vî rengî têne bicîh kirin:

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

Mînaka yekem fonksiyona alîkarê http.HandleFunc bikar tîne. Ew fonksiyonek din vedigire, ku di encamê de http.ResponseWriter û http.Request digire nav ServeHTTP.

Bi gotinek din, di Golang de destwerdan di navbeynek yekane de têne pêşkêş kirin, ku gelek vebijarkan dide bernameçêker. Ji ber vê yekê, mînakî, navgîniya navgîn bi karanîna destekek tête bicîh kirin, li wir ServeHTTP pêşî tiştek dike û dûv re gazî rêbaza ServeHTTP ya destekek din dike.

Wekî ku li jor behs kir, hilber bi tenê bersivên daxwazan diafirînin. Lê divê kîjan hilgirê taybetî di demek taybetî de were bikar anîn?

Daxwaza Rêvekirinê

Ji bo ku hûn bijartina rast bikin, pirjimarek HTTP bikar bînin. Di hejmarek pirtûkxaneyan de jê re muxer an router tê gotin, lê ew hemî heman tişt in. Fonksiyona multiplexer ev e ku riya daxwazê ​​analîz bike û hilgirê guncan hilbijêrin.

Heke hûn ji bo rêveçûna tevlihev hewceyê piştgirî hewce ne, wê hingê çêtir e ku hûn pirtûkxaneyên sêyemîn bikar bînin. Hin ji yên herî pêşkeftî - gorilla/mux и go-çî/çî, ev pirtûkxane îmkana pêkanîna pêvajoyek navîn bêyî pirsgirêk dikin. Bi arîkariya wan, hûn dikarin rêvekirina wildcard mîheng bikin û hejmarek karên din pêk bînin. Feydeya wan lihevhatina bi hilgirên standard HTTP re ye. Wekî encamek, hûn dikarin kodek hêsan binivîsin ku dikare di pêşerojê de were guheztin.

Di rewşek normal de xebitandina bi çarçoveyên tevlihev re dê çareseriyên ne-standard hewce bike, û ev yek bi girîngî karanîna hilgirên xwerû tevlihev dike. Ji bo afirandina pirraniya serîlêdanan, berhevoka pirtûkxaneya xwerû û routerek hêsan dê bes be.

Query Processing

Digel vê yekê, me pêdivî bi pêkhateyek heye ku dê ji bo girêdanên hatina "guhdarî" bike û hemî daxwazan berbi hilgirê rast vegerîne. http.Server bi hêsanî dikare vî karî bike.

Ya jêrîn destnîşan dike ku server ji hemî karên ku bi pêvajoya pêwendiyê ve girêdayî ne berpirsiyar e. Ev, ji bo nimûne, bi karanîna protokola TLS dixebite. Ji bo pêkanîna banga http.ListenAndServer, serverek standard HTTP tê bikar anîn.

Niha em li mînakên tevlihevtir binêrin.

Zêdekirina Let's Encrypt

Bi xwerû, serîlêdana me li ser protokola HTTP-ê dimeşîne, lê tê pêşniyar kirin ku protokola HTTPS bikar bînin. Ev dikare bêyî pirsgirêk di Go de were kirin. Ger we sertîfîkayek û mifteya taybet wergirtibe, wê hingê bes e ku hûn ListenAndServeTLS bi sertîfîkaya rast û pelên mifteyê tomar bikin.

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

Hûn dikarin her gav çêtir bikin.

Let's Encrypt bi nûvekirina otomatîkî sertîfîkayên belaş peyda dike. Ji bo ku hûn karûbarê bikar bînin, hûn pakêtek hewce ne autocert.

Rêya herî hêsan a mîhengkirina wê ev e ku meriv rêbaza autocert.NewListener bi tevlêbûna http.Serve re bikar bîne. Rêbaz dihêle hûn sertîfîkayên TLS bistînin û nûve bikin dema ku servera HTTP daxwazan dike:

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

Ger em di gerokê de vekin example.com, em ê bersivek HTTPS "Silav, cîhan!"

Ger hewcedariya we bi veavakirina berfirehtir hebe, wê hingê divê hûn rêveberê autocert.Manager bikar bînin. Dûv re em mînaka xwe ya http.Server diafirînin (heta nuha me ew bi xwerû bikar anî) û rêveberê li servera TLSConfig zêde dikin:

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

Ev rêgezek hêsan e ku meriv bi nûvekirina sertîfîkaya otomatîkî piştgirîya tevahî ya HTTPS-ê bicîh bike.

Zêdekirina rêyên xwerû

Routera xwerû ya ku di pirtûkxaneya standard de tê de baş e, lê ew pir bingehîn e. Pir sepanan rêveçûnek tevlihevtir hewce dike, di nav de rêçên hêlîn û hêlîn, an prosedurek ji bo danîna qalibên rê û pîvanan.

Di vê rewşê de hêja ye ku pakêtan bikar bînin gorilla/mux и go-çî/çî. Em ê fêr bibin ka meriv çawa bi ya paşîn re dixebite - mînakek li jêr tê nîşandan.

Pelê api/v1/api.go tê dayîn ku rêyên ji bo API-ya me vedihewîne:

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

Me pêşgira api/vq ji bo rêgezan di pelê sereke de destnîşan kir.

Dûv re em dikarin vê li ser routerê xweya sereke di binê pêşgira api/v1/ de vegerînin serîlêdana xweya sereke:

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

Karkirina Go bi riyên tevlihev re hêsantir dike ku avahîsazkirin û domandina serîlêdanên mezin û tevlihev hêsan bike.

Bi navgîniyê re dixebitin

Staging tevlîhevkirina yek destekek HTTP-ê bi yekî din re vedihewîne, ku gengaz e ku meriv zû rastrastkirin, berhevkirin, têketin û çend fonksiyonên din pêk bîne.

Weke mînak, em li navbeynkariya http.Handler binêrin; em ê wê bikar bînin da ku rêgezek ku bikarhênerên karûbarê piştrast dike binivîsin.

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

Roterên partiya sêyemîn hene, wek chi, ku dihêle hûn fonksiyona navgîniyê dirêj bikin.

Bi pelên statîk re dixebitin

Pirtûkxaneya standard Go kapasîteyên xebata bi naveroka statîk, tevî wêne, JavaScript û pelên CSS-ê vedihewîne. Ew dikarin bi riya fonksiyona http.FileServer ve werin gihîştin. Ew rêvekerek vedigerîne ku pelan ji pelrêçek taybetî re xizmet dike.

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

Bê guman hêjayî bibîrxistinê ye ku http.Dir naveroka pelrêçayê nîşan dide heke pelê sereke index.html tune be. Di vê rewşê de, ji bo pêşîlêgirtina pelrêçîtiyê, divê hûn pakêtê bikar bînin unindexed.

Girtina rast

Go di heman demê de xwedan taybetmendiyek bi navê qutkirina xweş a servera HTTP jî heye. Ev dikare bi karanîna rêbaza Shutdown () were kirin. Pêşkêşkar bi gorutinekê dest pê dike, û dûv re kanal tê guhdarî kirin da ku îşaretek qutbûnê werbigire. Hema ku îşaret tê wergirtin, server vediqete, lê ne tavilê, lê piştî çend saniyan.

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)

Wekî encamê

Go zimanek hêzdar e ku bi pirtûkxaneyek standard hema hema gerdûnî ye. Kapasîteyên wê yên xwerû pir berfireh in, û ew dikarin bi karanîna navberan werin zêdekirin - ev dihêle hûn serverên HTTP-ê bi rastî pêbawer pêşve bibin.

Skillbox pêşniyar dike:

Source: www.habr.com

Add a comment