a Recap of Request Handling in Go
Processing HTTP requests with Go is primarely about two things: ServeMuxes and Handlers.
ServeMux on pohjimmiltaan HTTP-pyyntöreititin (tai multiplexor). Se vertaa saapuvia pyyntöjä ennalta määritettyjen URL-polkujen luetteloon ja kutsuu polun käsittelijää aina, kun osuma löytyy.
käsittelijät vastaavat vastausten otsikoiden ja elinten kirjoittamisesta. Lähes mikä tahansa objekti voi olla käsittelijä, kunhan se täyttää http.Handler
rajapinnan. Maallikkotermein tämä tarkoittaa yksinkertaisesti sitä, että sillä on oltava ServeHTTP
menetelmä, jossa on seuraava allekirjoitus:
ServeHTTP(http.ResponseWriter, *http.Request)
Go: n HTTP-pakettialukset, joissa on muutama toiminto yhteisten käsittelijöiden tuottamiseksi, kuten FileServer
NotFoundHandler
ja RedirectHandler
. Aloitetaan yksinkertaisella mutta keksityllä esimerkillä:
mennään tästä nopeasti läpi:
-
main
funktio käytämmehttp.NewServeMux
funktio luoda tyhjä servemux. - tämän jälkeen käytetään
http.RedirectHandler
funktiota uuden käsittelijän luomiseen. Käsittelijä 307 ohjaa kaikki vastaanottamansa pyynnöt osoitteeseenhttp://example.org
. - seuraavaksi käytämme
mux.Handle
funktiota tämän rekisteröimiseksi uudella ServeMux ’ llämme, joten se toimii kaikkien saapuvien pyyntöjen käsittelijänä URL-polulla/foo
. - lopuksi luomme uuden palvelimen ja alamme kuunnella saapuvia pyyntöjä
http.ListenAndServe
funktiolla, siirtäen Servemuximme sen sovittamaan pyyntöjä vastaan.
Käynnistä sovellus:
ja käy http://localhost:3000/foo
selaimessasi. Sinun pitäisi huomata, että pyyntösi saa onnistuneesti ohjataan.
tarkkasilmäiset saattoivat huomata jotain mielenkiintoista: listenandserve-funktion tunnus on ListenAndServe(addr string, handler Handler)
, mutta ohitimme toisena parametrina Servemuxin.
tähän pystyimme, koska ServeMux-tyypillä on myös ServeHTTP
– menetelmä, eli sekin täyttää käsittelijän rajapinnan.
minulle on yksinkertaistavaa ajatella, että ServeMux on vain erityinen käsittelijä, joka itse vastauksen antamisen sijaan siirtää pyynnön toiselle käsittelijälle. Tämä ei ole niin paljon harppaus kuin se ensin kuulostaa – ketjuttaminen käsittelijät yhdessä on melko yleistä Go.
Custom Handlers
luodaan mukautettu käsittelijä, joka vastaa kulloiseenkin paikalliseen aikaan tietyssä muodossa:
tarkka koodi tässä ei ole liian tärkeä.
tärkeintä on, että meillä on objekti (tässä tapauksessa se on timeHandler
strukturoitu, mutta se voisi yhtä hyvin olla merkkijono tai funktio tai mikä tahansa muu), ja olemme toteuttaneet menetelmän, jossa on allekirjoitus ServeHTTP(http.ResponseWriter, *http.Request)
siihen. Se riittää käsittelijäksi.
upotetaan tämä konkreettisena esimerkkinä:
in the main
function we initialized the timeHandler
in tismalleen samalla tavalla we would any normal structured, using the &
symboli osoittimen antamiseksi. Ja sitten, kuten edellisessä esimerkissä, käytämme mux.Handle
funktiota rekisteröimään tämän ServeMux ’ llemme.
nyt kun suoritamme sovelluksen, ServeMux välittää kaikki /time
suoraan meidän timeHandler.ServeHTTP
– menetelmällemme.
Go ahead and give it a try: http://localhost:3000/time
.
Huomaa myös, että timeHandler
usealla reitillä:
toimii käsittelijöinä
yksinkertaisissa tapauksissa (kuten yllä olevassa esimerkissä), joissa määritellään uusia mukautettuja tyyppejä ja servehttp: / / www-menetelmät tuntuvat hieman monisanaisilta. Tarkastellaan vaihtoehtoista lähestymistapaa, jossa hyödynnämme Go: n http.HandlerFunc
– tyyppiä pakottaaksemme normaalin funktion täyttämään käsittelijän rajapinnan.
mikä tahansa funktio, jolla on allekirjoitus func(http.ResponseWriter, *http.Request)
, voidaan muuntaa HandlerFunc-tyypiksi. Tämä on hyödyllistä, koska HandleFunc – objektien mukana tulee sisäänrakennettu ServeHTTP
menetelmä, joka – melko taitavasti ja kätevästi-suorittaa alkuperäisen funktion sisällön.
Jos tämä kuulostaa hämmentävältä, kokeile vilkaista asiaankuuluvaa lähdekoodia. Näet, että se on hyvin ytimekäs tapa tehdä toiminto tyydyttää käsittelijä käyttöliittymä.
toistetaan timeHandler-sovellus tällä tekniikalla:
itse asiassa funktion muuntaminen Käsittelijäfunc-tyyppiseksi ja sen lisääminen tämän kaltaiseen Servemuxiin on niin yleistä, että Go tarjoaa oikotien: mux.HandleFunc
menetelmä.
tältä main()
funktio olisi näyttänyt, jos olisimme käyttäneet sen sijaan tätä oikotietä:
suurimman osan ajasta käyttäen tällainen toiminta käsittelijänä toimii hyvin. Mutta siinä on vähän rajoitusta, kun asiat alkavat monimutkaistua.
olet luultavasti huomannut, että aiemmasta menetelmästä poiketen meidän on pitänyt kovettaa aikamuoto timeHandler
funktiossa. Mitä tapahtuu, kun haluamme välittää tietoa tai muuttujia main()
käsittelijälle?
siisti lähestymistapa on laittaa käsittelijälogiikkamme lukkoon ja sulkea käyttämämme muuttujat:
timeHandler
funktiolla on nyt hienovaraisesti erilainen rooli. Sen sijaan, että pakottaisimme toiminnon käsittelijäksi (kuten teimme aiemmin), käytämme sitä nyt palauttaaksemme käsittelijän. Tässä on kaksi keskeistä tekijää.
ensin se Luo fn
, anonyymin funktion, joka käyttää ‐ tai sulkee Overin – format
muuttujan muodostaen sulkimen. Riippumatta siitä, mitä teemme sulkemisella, se pääsee aina käsiksi muuttujiin, jotka ovat paikallisia sille alueelle, jossa se luotiin – mikä tässä tapauksessa tarkoittaa, että sillä on aina pääsy format
muuttuja.
toiseksi sulkemisessamme on allekirjoitus func(http.ResponseWriter, *http.Request)
. Kuten saatat muistaa aiemmin, tämä tarkoittaa, että voimme muuntaa sen HandlerFunc tyyppi (niin, että se täyttää Handler käyttöliittymä). Meidän timeHandler
funktio palauttaa tämän muunnetun sulkemisen.
tässä esimerkissä olemme juuri siirtäneet yksinkertaisen merkkijonon käsittelijälle. Mutta reaalimaailman sovellus voisi käyttää tätä menetelmää siirtää tietokantayhteyden, mallikartan, tai minkä tahansa muun sovellustason yhteydessä. Se on hyvä vaihtoehto käyttää globaaleja muuttujia, ja on lisäetuna tehdä siisti itsenäinen käsittelijät testaukseen.
saman kuvion voi nähdä myös kirjoitettuna:
tai käyttämällä implisiittistä muuntamista HandlerFunc-tyyppiin paluun yhteydessä:
DefaultServeMux
olet luultavasti nähnyt DefaultServeMux ’ n mainittavan monessa paikassa, yksinkertaisimmista Hello World-esimerkeistä Go: n lähdekoodiin.
kesti kauan tajuta, ettei siinä ole mitään erikoista. DefaultServeMux on vain tavallinen ol ’ ServeMux kuten olemme jo käyttäneet, joka saa instantiated oletuksena, kun HTTP-pakettia käytetään. Tässä asiaankuuluva rivi Go-lähteestä:
var DefaultServeMux = NewServeMux()
yleensä Defaultservemuxia ei kannata käyttää, koska se aiheuttaa tietoturvariskin.
koska DefaultServeMux on tallennettu kokonaismuuttujaan, mikä tahansa paketti voi käyttää sitä ja rekisteröidä reitin – mukaan lukien sovelluksesi tuomat kolmannen osapuolen paketit. Jos jokin näistä kolmannen osapuolen paketeista vaarantuu, he voivat käyttää DefaultServeMux-toimintoa haitallisen käsittelijän paljastamiseksi verkkoon.
nyrkkisääntönä on siis hyvä välttää DefaultServeMux, ja käyttää sen sijaan omaa paikallisesti scopattua Servemuxia, kuten tähänkin asti. Mutta jos päätät käyttää sitä…
HTTP-paketti tarjoaa pari pikakuvaketta, joilla voit työskennellä DefaultServeMux: http-komennon kanssa.Käsittele ja http.HandleFunc. Nämä tekevät täsmälleen samoin kuin niiden kaimatoiminnot, joita olemme jo tarkastelleet, sillä erotuksella, että ne lisäävät käsittelijöitä Defaultservemuxiin luomasi sijaan.
lisäksi ListenAndServe sortuu käyttämään Defaultservemuxia, jos muita käsittelijöitä ei ole (eli toinen parametri on asetettu nil
).
joten viimeisenä vaiheena päivitetäänpä timeHandler-sovelluksemme käyttämään Defaultservemuxia sen sijaan:
Jos pidit tästä blogikirjoituksesta, älä unohda tarkistaa uutta Kirjaani siitä, miten ammattimaisia verkkosovelluksia Go!
Seuraa minua Twitterissä @ajmedwards.
kaikki tässä viestissä olevat koodinpätkät ovat vapaasti käytettävissä MIT-lisenssin nojalla.