በጎላንግ ውስጥ የድር አገልጋዮችን ማዳበር - ከቀላል እስከ ውስብስብ

በጎላንግ ውስጥ የድር አገልጋዮችን ማዳበር - ከቀላል እስከ ውስብስብ

የጀመርኩት ከአምስት አመት በፊት ነው። ጎፊሽ ማዳበርጎላንግ መማር አስችሎታል። ጎ ኃይለኛ ቋንቋ እንደሆነ ተገነዘብኩ፣ እሱም በብዙ ቤተ-መጻሕፍት የተሞላ። ሂድ ሁለገብ ነው፡በተለይ ከአገልጋይ ወገን የሆኑ አፕሊኬሽኖችን በቀላሉ ማዳበር ይችላሉ።

ይህ መጣጥፍ በGo ውስጥ አገልጋይ ስለመጻፍ ነው። እንደ "ሄሎ አለም!" ባሉ ቀላል ነገሮች እንጀምር እና እነዚህን ባህሪያት የያዘ መተግበሪያ እንጨርስ።

- ለኤችቲቲፒኤስ ኢንክሪፕት እንጠቀም።
- እንደ ኤፒአይ ራውተር ይስሩ።
- ከመሃል ዌር ጋር በመስራት ላይ.
- የማይንቀሳቀሱ ፋይሎችን ማስተናገድ።
- ትክክለኛ መዘጋት.

Skillbox ይመክራል፡ ተግባራዊ ኮርስ "Python ገንቢ ከባዶ".

እኛ እናስታውስዎታለን- ለሁሉም የ "ሀብር" አንባቢዎች - የ "Habr" የማስተዋወቂያ ኮድን በመጠቀም በማንኛውም የ Skillbox ኮርስ ውስጥ ሲመዘገቡ የ 10 ሩብልስ ቅናሽ.

ሰላም ዓለም!

በ Go ውስጥ የድር አገልጋይ መፍጠር በጣም ፈጣን ሊሆን ይችላል። ከላይ ቃል የተገባለትን “ሄሎ፣ ዓለም!” የሚመልስ ተቆጣጣሪን የመጠቀም ምሳሌ እዚህ አለ።

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

ከዚያ በኋላ, መተግበሪያውን ካስኬዱ እና ገጹን ከፈቱ localhost, ከዚያ ወዲያውኑ "ሄሎ, ዓለም!" የሚለውን ጽሑፍ ያያሉ. (በእርግጥ, ሁሉም ነገር በትክክል የሚሰራ ከሆነ).

በሚከተለው ውስጥ ተቆጣጣሪውን ደጋግመን እንጠቀማለን, ግን በመጀመሪያ ሁሉም እንዴት እንደሚሰራ እንረዳ.

net/http

ምሳሌው ጥቅሉን ተጠቅሟል net/httpሁለቱንም አገልጋዮች እና ኤችቲቲፒ ደንበኞችን ለማዳበር የ Go ዋና መሳሪያ ነው። ኮዱን ለመረዳት የሶስት ጠቃሚ አካላትን ትርጉም እንረዳ፡- http.Handler፣ http.ServeMux እና http.Server።

የኤችቲቲፒ ተቆጣጣሪዎች

ጥያቄ ስንቀበል፣ ተቆጣጣሪው ይተነትናል እና ምላሽ ያመነጫል። በGo ውስጥ ያሉ ተቆጣጣሪዎች እንደሚከተለው ይተገበራሉ፡

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

የመጀመሪያው ምሳሌ http.HandleFunc አጋዥ ተግባርን ይጠቀማል። ሌላ ተግባር ያጠቃልላል እሱም በተራው http.ResponseWriter እና http.Request በ ServeHTTP ይቀበላል።

በሌላ አነጋገር በጎላንግ ውስጥ ያሉ ተቆጣጣሪዎች በአንድ በይነገጽ ይወከላሉ, ይህም ለፕሮግራም አውጪው ብዙ እድሎችን ይሰጣል. ስለዚህ ለምሳሌ መካከለኛ ዌር የሚተገበረው ተቆጣጣሪን በመጠቀም ሲሆን ሰርቪኤችቲቲፒ መጀመሪያ አንድ ነገር ሲያደርግ እና የሌላ ተቆጣጣሪ የServeHTTP ዘዴን ይጠራል።

ከላይ እንደተጠቀሰው፣ ተቆጣጣሪዎች በቀላሉ ለጥያቄዎች ምላሽ ይሰጣሉ። ግን የትኛው ተቆጣጣሪ በተወሰነ ጊዜ ጥቅም ላይ መዋል አለበት?

መስመር ጠይቅ

ትክክለኛውን ምርጫ ለማድረግ፣ HTTP multiplexer ይጠቀሙ። በበርካታ ቤተ-መጻሕፍት ውስጥ ሙክሰር ወይም ራውተር ይባላል, ግን ሁሉም ተመሳሳይ ናቸው. የብዝሃ ማሰራጫው ተግባር የጥያቄውን መንገድ መተንተን እና ተገቢውን ተቆጣጣሪ መምረጥ ነው።

ለተወሳሰበ መስመር ድጋፍ ከፈለጉ የሶስተኛ ወገን ቤተ-መጽሐፍቶችን መጠቀም የተሻለ ነው። በጣም የላቁ አንዱ ጎሪላ/ሙክስ и go-ቺ/ቺ, እነዚህ ቤተ-መጻሕፍት ያለ ምንም ችግር መካከለኛ ሂደትን ተግባራዊ ለማድረግ ያስችላሉ. በእነሱ እርዳታ የዱር ካርድ ማዞሪያን ማዘጋጀት እና ሌሎች በርካታ ተግባራትን ማከናወን ይችላሉ. የእነሱ ጥቅም ከመደበኛ የኤችቲቲፒ ተቆጣጣሪዎች ጋር ተኳሃኝነት ነው። በውጤቱም, ለወደፊቱ ሊስተካከል የሚችል ቀላል ኮድ መጻፍ ይችላሉ.

በተለመደው ሁኔታ ውስጥ ከተወሳሰቡ ማዕቀፎች ጋር መሥራት መደበኛ መፍትሄዎችን አያስፈልገውም ፣ እና ይህ ነባሪ ተቆጣጣሪዎችን አጠቃቀምን በእጅጉ ያወሳስበዋል ። አብዛኛዎቹን አፕሊኬሽኖች ለመፍጠር የነባሪው ቤተ-መጽሐፍት እና ቀላል ራውተር ጥምረት በቂ ይሆናል።

የጥያቄ ሂደት

በተጨማሪም፣ ለሚመጡ ግንኙነቶች "የሚሰማ" እና ሁሉንም ጥያቄዎች ወደ ትክክለኛው ተቆጣጣሪ የሚያዞር አካል እንፈልጋለን። http. አገልጋይ በቀላሉ ይህን ተግባር መቋቋም ይችላል.

የሚከተለው የሚያሳየው አገልጋዩ ከግንኙነቶች አያያዝ ጋር ለተያያዙ ስራዎች ሁሉ ሃላፊነቱን እንደሚወስድ ነው። ይህ ለምሳሌ በTLS ፕሮቶኮል ላይ መሥራት ነው። የ http.ListenAndServer ጥሪን ለመተግበር መደበኛ HTTP አገልጋይ ጥቅም ላይ ይውላል።

አሁን የበለጠ ውስብስብ ምሳሌዎችን እንመልከት.

እንመስጥርን በማከል

በነባሪ የእኛ መተግበሪያ በኤችቲቲፒ ፕሮቶኮል ላይ ይሰራል፣ ነገር ግን HTTPS ፕሮቶኮልን ለመጠቀም ይመከራል። በ Go ውስጥ, ይህ ያለችግር ሊከናወን ይችላል. የምስክር ወረቀት እና የግል ቁልፍ ከተቀበልክ ListenAndServeTLSን ከትክክለኛው የምስክር ወረቀት እና ቁልፍ ፋይሎች ጋር መፃፍ በቂ ነው።

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

ሁልጊዜ የተሻለ መስራት ትችላለህ።

እንመሳጠር አውቶማቲክ እድሳት የሚቻልበት ነጻ የምስክር ወረቀቶች ይሰጣል. አገልግሎቱን ለመጠቀም, ጥቅል ያስፈልግዎታል autocert.

እሱን ለማዋቀር ቀላሉ መንገድ autocert.NewListener ዘዴን ከ http.Serve ጋር በማጣመር መጠቀም ነው። የኤችቲቲፒ አገልጋይ ሲጠይቅ ዘዴው የTLS ሰርተፊኬቶችን እንዲቀበሉ እና እንዲያድሱ ይፈቅድልዎታል፡-

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

በአሳሹ ውስጥ ከከፈትን example.com, የኤችቲቲፒኤስ ምላሽ አግኝተናል "ሄሎ, ዓለም!".

የበለጠ ዝርዝር ውቅር ከፈለጉ ፣ ከዚያ autocert.Managerን መጠቀም አለብዎት። ከዚያ የራሳችንን http.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("", "")

ይህ በራስ ሰር ሰርተፍኬት እድሳት ሙሉ HTTPS ድጋፍን ለመተግበር ቀላል መንገድ ነው።

ብጁ መስመሮችን ማከል

በመደበኛ ቤተ-መጽሐፍት ውስጥ የተካተተው ነባሪ ራውተር ጥሩ ነው, ግን በጣም መሠረታዊ ነው. አብዛኛዎቹ አፕሊኬሽኖች የጎጆ እና የዱር ካርድ መንገዶችን፣ ወይም የስርዓተ-ጥለት እና የዱካ መለኪያዎችን ጨምሮ የበለጠ ውስብስብ ማዘዋወር ያስፈልጋቸዋል።

በዚህ ሁኔታ, ፓኬጆችን መጠቀም አለብዎት ጎሪላ/ሙክስ и go-ቺ/ቺ. ከኋለኛው ጋር እንዴት እንደሚሰራ እንማራለን - አንድ ምሳሌ ከዚህ በታች ይታያል.

ለኤፒአይያችን መንገዶችን የያዘው የ api/v1/api.go ፋይል ተሰጥቷል፡-

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

በዋናው ፋይል ውስጥ ለመንገዶች የ api/vq ቅድመ ቅጥያ አዘጋጅተናል።

ከዚያ ይህንን በዋናው መተግበሪያችን ውስጥ በ api/v1/ ቅድመ ቅጥያ ስር ወደ ዋናው ራውተር መጫን እንችላለን፡-

// 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 ውስጥ ካሉ ውስብስብ መንገዶች ጋር አብሮ የመስራት ቀላልነት ትልቅ ውስብስብ አፕሊኬሽኖችን አወቃቀሩን እና ጥገናን ቀላል ያደርገዋል።

ከመሃል ዌር ጋር በመስራት ላይ

በመካከለኛ ሂደት ውስጥ አንድ የኤችቲቲፒ ተቆጣጣሪ ከሌላው ጋር መጠቅለል ጥቅም ላይ ይውላል ፣ ይህም ማረጋገጥ ፣ መጭመቅ ፣ ምዝግብ ማስታወሻ እና አንዳንድ ሌሎች ተግባራትን በፍጥነት ለማከናወን ያስችላል።

እንደ ምሳሌ, የ http.Handler በይነገጽን እናስብ, በእሱ እርዳታ የአገልግሎት ተጠቃሚዎችን ማረጋገጫ የያዘ ተቆጣጣሪ እንጽፋለን.

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

የመካከለኛ ሂደትን ተግባር ለማራዘም የሚያስችልዎ እንደ ቺ ያሉ የሶስተኛ ወገን ራውተሮች አሉ።

ከስታቲክ ፋይሎች ጋር በመስራት ላይ

የGo's standard ቤተመፃህፍት ምስሎችን ጨምሮ ከስታቲክ ይዘት ጋር ለመስራት መገልገያዎችን እንዲሁም JavaScript እና CSS ፋይሎችን ያካትታል። በ http.FileServer ተግባር በኩል ሊገኙ ይችላሉ. ከአንድ የተወሰነ ማውጫ ፋይሎችን የሚያሰራጭ ተቆጣጣሪ ይመልሳል።

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

ያስታውሱ http.Dir ዋናውን index.html ፋይል ከሌለው የማውጫውን ይዘቶች ያሳያል. በዚህ አጋጣሚ, ማውጫው እንዳይጣስ ለመከላከል, ጥቅሉን መጠቀም አለብዎት unindexed.

ትክክለኛ መዘጋት

ጎ የኤችቲቲፒ አገልጋይን እንደ ቆንጆ መዘጋት ያለ ባህሪም አለው። ይህ የመዝጋት () ዘዴን በመጠቀም ሊከናወን ይችላል. አገልጋዩ በጐሮታይን ነው የጀመረው፣ከዚያም ቻናሉ የማቋረጫ ሲግናል እንዲቀበል ይደመጣል። ምልክቱ እንደደረሰ አገልጋዩ ይጠፋል ፣ ግን ወዲያውኑ አይደለም ፣ ግን ከጥቂት ሰከንዶች በኋላ።

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)

እንደ አንድ መደምደሚያ

ጎ ከሞላ ጎደል ሁለንተናዊ መደበኛ ቤተ-መጽሐፍት ያለው ኃይለኛ ቋንቋ ነው። የእሱ ነባሪ ችሎታዎች በጣም ሰፊ ናቸው, እና በበይነገጾች እገዛ እነሱን ማጠናከር ይችላሉ - ይህ በእውነት አስተማማኝ የኤችቲቲፒ አገልጋዮችን እንዲያዳብሩ ያስችልዎታል.

Skillbox ይመክራል፡

ምንጭ: hab.com

አስተያየት ያክሉ