Leasachadh frithealaiche lìn ann an Golang - bho shìmplidh gu iom-fhillte

Leasachadh frithealaiche lìn ann an Golang - bho shìmplidh gu iom-fhillte

Còig bliadhna air ais thòisich mi Gophish a leasachadh, thug seo cothrom air Golang ionnsachadh. Thuig mi gur e cànan cumhachdach a th’ ann an Go, le mòran leabharlannan na chois. Tha Go ioma-chruthach: gu sònraichte, faodar a chleachdadh gus tagraidhean taobh an fhrithealaiche a leasachadh gun duilgheadas sam bith.

Tha an artaigil seo mu dheidhinn a bhith a’ sgrìobhadh frithealaiche ann an Go. Feuch an tòisich sinn le rudan sìmplidh mar “Hello world!” agus crìochnaich le tagradh leis na comasan a leanas:

- A’ cleachdadh Let's Encrypt airson HTTPS.
- Ag obair mar router API.
- Ag obair le bathar-bog meadhanach.
- Giullachd fhaidhlichean statach.
- dùnadh ceart.

Tha Skillbox a’ moladh: Cùrsa practaigeach "Python leasaiche bhon toiseach".

Tha sinn a ’cur nar cuimhne: airson a h-uile leughadair de "Habr" - lasachadh de 10 rubles nuair a chlàraicheas tu ann an cùrsa sam bith Skillbox a 'cleachdadh a' chòd adhartachaidh "Habr".

Halò, shaoghail!

Faodaidh tu frithealaiche lìn a chruthachadh ann an Go gu math luath. Seo eisimpleir de bhith a’ cleachdadh inneal-làimhseachaidh a thilleas an “Hello, world!” a chaidh a ghealltainn gu h-àrd.

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

Às deidh seo, ma ruitheas tu an tagradh agus fosgail an duilleag localhost, an uairsin chì thu sa bhad an teacsa “Hello, world!” (ma tha a h-uile càil ag obair ceart, gu dearbh).

Cleachdaidh sinn an inneal-làimhseachaidh iomadh uair nas fhaide air adhart, ach an toiseach tuigidh sinn mar a tha a h-uile càil ag obair.

lìon/http

Chleachd an eisimpleir am pasgan net/http, is e am prìomh inneal ann an Go airson a bhith a’ leasachadh an dà chuid frithealaichean agus teachdaichean HTTP. Gus an còd a thuigsinn, tuigidh sinn brìgh trì eileamaidean cudromach: http.Handler, http.ServeMux agus http.Server.

Luchd-làimhseachaidh HTTP

Nuair a gheibh sinn iarrtas, bidh an neach-làimhseachaidh ga sgrùdadh agus a’ gineadh freagairt. Tha luchd-làimhseachaidh ann an Go air an cur an gnìomh mar a leanas:

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

Tha a’ chiad eisimpleir a’ cleachdadh gnìomh cuideachaidh http.HandleFunc. Bidh e a’ cuairteachadh gnìomh eile, a bheir e fhèin http.ResponseWriter agus http.Request a-steach gu ServeHTTP.

Ann am faclan eile, tha luchd-làimhseachaidh ann an Golang air an taisbeanadh ann an aon eadar-aghaidh, a bheir mòran roghainnean don phrògramadair. Mar sin, mar eisimpleir, tha bathar meadhanach air a chur an gnìomh le bhith a 'cleachdadh inneal-làimhseachaidh, far a bheil ServeHTTP a' dèanamh rudeigin an toiseach agus an uairsin a 'gairm modh ServeHTTP inneal-làimhseachaidh eile.

Mar a chaidh ainmeachadh gu h-àrd, bidh luchd-làimhseachaidh dìreach a’ gineadh freagairtean do iarrtasan. Ach dè an inneal-làimhseachaidh sònraichte a bu chòir a chleachdadh aig àm sònraichte?

Iarrtas Routing

Gus an roghainn cheart a dhèanamh, cleachd ioma-fhillteadair HTTP. Ann an grunn leabharlannan canar muxer no router ris, ach tha iad uile mar an aon rud. Is e gnìomh an ioma-fhillteadair sgrùdadh a dhèanamh air an t-slighe iarrtas agus an inneal-làimhseachaidh iomchaidh a thaghadh.

Ma tha feum agad air taic airson slighe iom-fhillte, tha e nas fheàrr leabharlannan treas-phàrtaidh a chleachdadh. Tha cuid den fheadhainn as adhartaiche - gorilla/mux и go-chi/chi, tha na leabharlannan sin ga dhèanamh comasach giollachd eadar-mheadhanach a chuir an gnìomh gun duilgheadas sam bith. Le an cuideachadh, faodaidh tu slighe cairt fiadhaich a rèiteachadh agus grunn ghnìomhan eile a dhèanamh. Is e am buannachd aca co-chòrdalachd le luchd-làimhseachaidh HTTP àbhaisteach. Mar thoradh air an sin, faodaidh tu còd sìmplidh a sgrìobhadh a ghabhas atharrachadh san àm ri teachd.

Le bhith ag obair le frèaman iom-fhillte ann an suidheachadh àbhaisteach bidh feum air fuasglaidhean neo-àbhaisteach, agus tha seo gu mòr a’ dèanamh duilgheadas ann a bhith a’ cleachdadh làimhseachadh àbhaisteach. Gus a’ mhòr-chuid de thagraidhean a chruthachadh, bidh measgachadh den leabharlann bunaiteach agus router sìmplidh gu leòr.

Pròiseas Ceist

A bharrachd air an sin, feumaidh sinn pàirt a bhios “ag èisteachd” airson ceanglaichean a tha a’ tighinn a-steach agus ag ath-stiùireadh a h-uile iarrtas chun neach-làimhseachaidh ceart. Is urrainn do http.Server an obair seo a làimhseachadh gu furasta.

Tha na leanas a’ sealltainn gu bheil uallach air an fhrithealaiche airson a h-uile gnìomh co-cheangailte ri giullachd ceangail. Bidh seo, mar eisimpleir, ag obair a’ cleachdadh protocol TLS. Gus an gairm http.ListenAndServer a chuir an gnìomh, thèid frithealaiche HTTP àbhaisteach a chleachdadh.

A-nis leig dhuinn sùil a thoirt air eisimpleirean nas iom-fhillte.

A’ cur Let's Encrypt ris

Gu gnàthach, bidh an tagradh againn a’ ruith thairis air protocol HTTP, ach thathas a’ moladh protocol HTTPS a chleachdadh. Faodar seo a dhèanamh gun duilgheadasan ann an Go. Ma tha thu air teisteanas agus iuchair phrìobhaideach fhaighinn, tha e gu leòr ListenAndServeTLS a chlàradh leis an teisteanas ceart agus prìomh fhaidhlichean.

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

Faodaidh tu an-còmhnaidh a dhèanamh nas fheàrr.

Let's Encrypt a 'toirt seachad teisteanasan an-asgaidh le ùrachadh fèin-ghluasadach. Gus an t-seirbheis a chleachdadh, feumaidh tu pasgan autocert.

Is e an dòigh as fhasa air a rèiteachadh an dòigh autocert.NewListener a chleachdadh còmhla ri http.Serve. Leigidh an dòigh leat teisteanasan TLS fhaighinn agus ùrachadh fhad ‘s a bhios am frithealaiche HTTP a’ pròiseasadh iarrtasan:

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

Ma dh'fhosglas sinn sa bhrobhsair example.com, gheibh sinn freagairt HTTPS “Hello, world!”

Ma tha feum agad air rèiteachadh nas mionaidiche, bu chòir dhut am manaidsear autocert.Manager a chleachdadh. An uairsin cruthaichidh sinn an eisimpleir http.Server againn fhìn (gus an do chleachd sinn e gu bunaiteach) agus cuiridh sinn am manaidsear ris an t-seirbheisiche 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("", "")

Is e dòigh fhurasta a tha seo gus làn thaic HTTPS a chuir an gnìomh le ùrachadh teisteanais fèin-ghluasadach.

A’ cur slighean àbhaisteach ris

Tha an router bunaiteach a tha air a ghabhail a-steach san leabharlann àbhaisteach math, ach tha e gu math bunaiteach. Feumaidh a’ mhòr-chuid de thagraidhean slighe nas iom-fhillte, a’ toirt a-steach slighean neadachaidh agus cairt-fhiadhaich, no dòigh-obrach airson pàtrain is crìochan slighe a shuidheachadh.

Anns a 'chùis seo is fhiach a bhith a' cleachdadh pacaidean gorilla/mux и go-chi/chi. Ionnsaichidh sinn mar a dh'obraicheas sinn leis an fhear mu dheireadh - tha eisimpleir air a shealltainn gu h-ìosal.

Air a thoirt seachad tha am faidhle api/v1/api.go anns a bheil slighean airson an API againn:

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

Shuidhich sinn an ro-leasachan api/vq airson slighean sa phrìomh fhaidhle.

Faodaidh sinn an uairsin seo a chuir suas chun phrìomh router againn fon ro-leasachan api / v1 / air ais sa phrìomh thagradh againn:

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

Tha cho furasta sa tha Go a bhith ag obair le slighean iom-fhillte ga dhèanamh comasach structar agus cumail suas thagraidhean mòra, iom-fhillte a dhèanamh nas sìmplidhe.

Ag obair le middleware

Tha stèidse a’ toirt a-steach a bhith a’ pasgadh aon inneal-làimhseachaidh HTTP le fear eile, ga dhèanamh comasach dearbhadh, teannachadh, logadh agus grunn ghnìomhan eile a choileanadh gu sgiobalta.

Mar eisimpleir, leig dhuinn sùil a thoirt air an eadar-aghaidh http.Handler; cleachdaidh sinn e gus inneal-làimhseachaidh a sgrìobhadh a dhearbhas luchd-cleachdaidh seirbheis.

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

Tha routers treas-phàrtaidh ann, leithid chi, a leigeas leat comas-gnìomh meadhan-bathair a leudachadh.

Ag obair le faidhlichean statach

Tha an leabharlann àbhaisteach Go a’ toirt a-steach comasan airson a bhith ag obair le susbaint statach, a’ toirt a-steach ìomhaighean, faidhlichean JavaScript agus CSS. Faodar faighinn thuca tron ​​ghnìomh http.FileServer. Bidh e a 'tilleadh inneal-làimhseachaidh a bhios a' frithealadh fhaidhlichean bho eòlaire sònraichte.

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

Is fhiach cuimhneachadh gu cinnteach gu bheil http.Dir a’ taisbeanadh susbaint an eòlaire mura h-eil am prìomh fhaidhle index.html ann. Anns a 'chùis seo, gus casg a chur air an eòlaire bho bhith air a mhilleadh, bu chòir dhut am pasgan a chleachdadh unindexed.

Dùin sìos ceart

Tha feart aig Go cuideachd ris an canar dùnadh gràsmhor den fhrithealaiche HTTP. Faodar seo a dhèanamh a’ cleachdadh an dòigh Shutdown(). Tha am frithealaiche air a thòiseachadh ann an goroutine, agus an uairsin thathas ag èisteachd ris an t-sianal gus comharra brisidh fhaighinn. Cho luath ‘s a gheibhear an comharra, bidh an frithealaiche a’ tionndadh dheth, ach chan ann sa bhad, ach às deidh beagan dhiog.

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)

Mar cho-dhùnadh

Is e cànan cumhachdach a th’ ann an Go le leabharlann àbhaisteach cha mhòr uile-choitcheann. Tha na comasan bunaiteach aige gu math farsaing, agus faodar an àrdachadh le bhith a’ cleachdadh eadar-aghaidh - leigidh seo leat frithealaichean HTTP fìor earbsach a leasachadh.

Tha Skillbox a’ moladh:

Source: www.habr.com

Cuir beachd ann