chi
adalah router ringan, idiomatik dan komposisi untuk membangun layanan http go. Ini sangat bagus dalam membantu Anda menulis layanan API istirahat besar yang tetap dapat dipertahankan seiring dengan tumbuhnya dan perubahan proyek Anda. chi
dibangun di atas paket context
baru yang diperkenalkan di GO 1.7 untuk menangani pensinyalan, pembatalan, dan nilai-nilai yang diminta di seluruh rantai penangan.
Fokus dari proyek ini adalah untuk mencari desain yang elegan dan nyaman untuk menulis server API REST, yang ditulis selama pengembangan layanan API tekanan yang memberi kekuatan pada layanan API publik kami, yang pada gilirannya mendukung semua aplikasi sisi klien kami.
Pertimbangan utama dari desain CHI adalah: struktur proyek, pemeliharaan, penangan HTTP standar (hanya stdlib), produktivitas pengembang, dan mendekonstruksi sistem besar menjadi banyak bagian kecil. Router inti github.com/go-chi/chi
cukup kecil (kurang dari 1000 loc), tetapi kami juga telah menyertakan beberapa subpackage yang berguna/opsional: middleware, render dan docgen. Kami harap Anda juga menikmatinya!
go get -u github.com/go-chi/chi/v5
net/http
context
Baru, Memberikan Nilai Rantai, Pembatalan dan Batas Waktudocgen
menghasilkan dokumentasi perutean dari sumber Anda ke JSON atau MarkdownLihat _examples/ untuk berbagai contoh.
Semudah:
package main
import (
"net/http"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
)
func main () {
r := chi . NewRouter ()
r . Use ( middleware . Logger )
r . Get ( "/" , func ( w http. ResponseWriter , r * http. Request ) {
w . Write ([] byte ( "welcome" ))
})
http . ListenAndServe ( ":3000" , r )
}
Pratinjau Istirahat:
Berikut ini sedikit pratinjau tentang seperti apa rute dengan chi. Lihat juga dokumen perutean yang dihasilkan di JSON (routes.json) dan di Markdown (routes.md).
Saya sangat merekomendasikan membaca sumber contoh yang tercantum di atas, mereka akan menunjukkan kepada Anda semua fitur chi dan berfungsi sebagai bentuk dokumentasi yang baik.
import (
//...
"context"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
)
func main () {
r := chi . NewRouter ()
// A good base middleware stack
r . Use ( middleware . RequestID )
r . Use ( middleware . RealIP )
r . Use ( middleware . Logger )
r . Use ( middleware . Recoverer )
// Set a timeout value on the request context (ctx), that will signal
// through ctx.Done() that the request has timed out and further
// processing should be stopped.
r . Use ( middleware . Timeout ( 60 * time . Second ))
r . Get ( "/" , func ( w http. ResponseWriter , r * http. Request ) {
w . Write ([] byte ( "hi" ))
})
// RESTy routes for "articles" resource
r . Route ( "/articles" , func ( r chi. Router ) {
r . With ( paginate ). Get ( "/" , listArticles ) // GET /articles
r . With ( paginate ). Get ( "/{month}-{day}-{year}" , listArticlesByDate ) // GET /articles/01-16-2017
r . Post ( "/" , createArticle ) // POST /articles
r . Get ( "/search" , searchArticles ) // GET /articles/search
// Regexp url parameters:
r . Get ( "/{articleSlug:[a-z-]+}" , getArticleBySlug ) // GET /articles/home-is-toronto
// Subrouters:
r . Route ( "/{articleID}" , func ( r chi. Router ) {
r . Use ( ArticleCtx )
r . Get ( "/" , getArticle ) // GET /articles/123
r . Put ( "/" , updateArticle ) // PUT /articles/123
r . Delete ( "/" , deleteArticle ) // DELETE /articles/123
})
})
// Mount the admin sub-router
r . Mount ( "/admin" , adminRouter ())
http . ListenAndServe ( ":3333" , r )
}
func ArticleCtx ( next http. Handler ) http. Handler {
return http . HandlerFunc ( func ( w http. ResponseWriter , r * http. Request ) {
articleID := chi . URLParam ( r , "articleID" )
article , err := dbGetArticle ( articleID )
if err != nil {
http . Error ( w , http . StatusText ( 404 ), 404 )
return
}
ctx := context . WithValue ( r . Context (), "article" , article )
next . ServeHTTP ( w , r . WithContext ( ctx ))
})
}
func getArticle ( w http. ResponseWriter , r * http. Request ) {
ctx := r . Context ()
article , ok := ctx . Value ( "article" ).( * Article )
if ! ok {
http . Error ( w , http . StatusText ( 422 ), 422 )
return
}
w . Write ([] byte ( fmt . Sprintf ( "title:%s" , article . Title )))
}
// A completely separate router for administrator routes
func adminRouter () http. Handler {
r := chi . NewRouter ()
r . Use ( AdminOnly )
r . Get ( "/" , adminIndex )
r . Get ( "/accounts" , adminListAccounts )
return r
}
func AdminOnly ( next http. Handler ) http. Handler {
return http . HandlerFunc ( func ( w http. ResponseWriter , r * http. Request ) {
ctx := r . Context ()
perm , ok := ctx . Value ( "acl.permission" ).( YourPermissionType )
if ! ok || ! perm . IsAdmin () {
http . Error ( w , http . StatusText ( 403 ), 403 )
return
}
next . ServeHTTP ( w , r )
})
}
Router Chi didasarkan pada semacam Patricia Radix Trie. Router sepenuhnya kompatibel dengan net/http
.
Dibangun di atas pohon adalah antarmuka Router
:
// Router consisting of the core routing methods used by chi's Mux,
// using only the standard net/http.
type Router interface {
http. Handler
Routes
// Use appends one or more middlewares onto the Router stack.
Use ( middlewares ... func (http. Handler ) http. Handler )
// With adds inline middlewares for an endpoint handler.
With ( middlewares ... func (http. Handler ) http. Handler ) Router
// Group adds a new inline-Router along the current routing
// path, with a fresh middleware stack for the inline-Router.
Group ( fn func ( r Router )) Router
// Route mounts a sub-Router along a `pattern`` string.
Route ( pattern string , fn func ( r Router )) Router
// Mount attaches another http.Handler along ./pattern/*
Mount ( pattern string , h http. Handler )
// Handle and HandleFunc adds routes for `pattern` that matches
// all HTTP methods.
Handle ( pattern string , h http. Handler )
HandleFunc ( pattern string , h http. HandlerFunc )
// Method and MethodFunc adds routes for `pattern` that matches
// the `method` HTTP method.
Method ( method , pattern string , h http. Handler )
MethodFunc ( method , pattern string , h http. HandlerFunc )
// HTTP-method routing along `pattern`
Connect ( pattern string , h http. HandlerFunc )
Delete ( pattern string , h http. HandlerFunc )
Get ( pattern string , h http. HandlerFunc )
Head ( pattern string , h http. HandlerFunc )
Options ( pattern string , h http. HandlerFunc )
Patch ( pattern string , h http. HandlerFunc )
Post ( pattern string , h http. HandlerFunc )
Put ( pattern string , h http. HandlerFunc )
Trace ( pattern string , h http. HandlerFunc )
// NotFound defines a handler to respond whenever a route could
// not be found.
NotFound ( h http. HandlerFunc )
// MethodNotAllowed defines a handler to respond whenever a method is
// not allowed.
MethodNotAllowed ( h http. HandlerFunc )
}
// Routes interface adds two methods for router traversal, which is also
// used by the github.com/go-chi/docgen package to generate documentation for Routers.
type Routes interface {
// Routes returns the routing tree in an easily traversable structure.
Routes () [] Route
// Middlewares returns the list of middlewares in use by the router.
Middlewares () Middlewares
// Match searches the routing tree for a handler that matches
// the method/path - similar to routing a http request, but without
// executing the handler thereafter.
Match ( rctx * Context , method , path string ) bool
}
Setiap metode perutean menerima pattern
URL dan rantai handlers
. Pola URL mendukung Params bernama (yaitu. /users/{userID}
) dan Wildcards (yaitu. /admin/*
). Parameter URL dapat diambil saat runtime dengan menelepon chi.URLParam(r, "userID")
untuk parameter bernama dan chi.URLParam(r, "*")
untuk parameter wildcard.
Middlewares Chi hanyalah penangan middleware stdlib/http. Tidak ada yang istimewa tentang mereka, yang berarti router dan semua perkakas dirancang untuk kompatibel dan ramah dengan middleware mana pun di komunitas. Ini menawarkan ekstensibilitas dan penggunaan kembali paket yang jauh lebih baik dan merupakan jantung dari tujuan Chi.
Berikut adalah contoh middleware bersih/http standar di mana kami menetapkan kunci konteks "user"
nilai "123"
. Middleware ini menetapkan pengidentifikasi pengguna hipotetis pada konteks permintaan dan memanggil penangan berikutnya dalam rantai.
// HTTP middleware setting a value on the request context
func MyMiddleware ( next http. Handler ) http. Handler {
return http . HandlerFunc ( func ( w http. ResponseWriter , r * http. Request ) {
// create new context from `r` request context, and assign key `"user"`
// to value of `"123"`
ctx := context . WithValue ( r . Context (), "user" , "123" )
// call the next handler in the chain, passing the response writer and
// the updated request object with the new context value.
//
// note: context.Context values are nested, so any previously set
// values will be accessible as well, and the new `"user"` key
// will be accessible from this point forward.
next . ServeHTTP ( w , r . WithContext ( ctx ))
})
}
CHI menggunakan penangan net/http standar. Cuplikan kecil ini adalah contoh dari HTTP.Handler func yang membaca pengidentifikasi pengguna dari konteks permintaan - secara hipotetis, mengidentifikasi pengguna yang mengirimkan permintaan yang diautentikasi, divalidasi+ditetapkan oleh penangan middleware sebelumnya.
// HTTP handler accessing data from the request context.
func MyRequestHandler ( w http. ResponseWriter , r * http. Request ) {
// here we read from the request context and fetch out `"user"` key set in
// the MyMiddleware example above.
user := r . Context (). Value ( "user" ).( string )
// respond to the client
w . Write ([] byte ( fmt . Sprintf ( "hi %s" , user )))
}
Chi's Router Parses dan Store Parameter URL langsung ke konteks permintaan. Berikut adalah contoh cara mengakses URL Params di penangan net/http Anda. Dan tentu saja, Middlewares dapat mengakses informasi yang sama.
// HTTP handler accessing the url routing parameters.
func MyRequestHandler ( w http. ResponseWriter , r * http. Request ) {
// fetch the url parameter `"userID"` from the request of a matching
// routing pattern. An example routing pattern could be: /users/{userID}
userID := chi . URLParam ( r , "userID" )
// fetch `"key"` from the request context
ctx := r . Context ()
key := ctx . Value ( "key" ).( string )
// respond to the client
w . Write ([] byte ( fmt . Sprintf ( "hi %v, %v" , userID , key )))
}
CHI dilengkapi dengan paket middleware
opsional, menyediakan serangkaian net/http
middlewares standar. Harap dicatat, setiap middleware di ekosistem yang juga kompatibel dengan net/http
dapat digunakan dengan mux chi.
CHI/Middleware Handler | keterangan |
---|---|
AllowContentencoding | Menegakkan daftar putih header pengkodean konten permintaan |
AllowContentType | Daftar putih eksplisit dari tipe konten permintaan yang diterima |
Basicauth | Otentikasi HTTP Dasar |
Kompres | Kompresi gzip untuk klien yang menerima tanggapan terkompresi |
ContentCharset | Pastikan charset untuk header permintaan tipe konten |
Cleanpath | Bersihkan tebasan ganda dari jalur permintaan |
Gethead | Secara otomatis merutekan permintaan kepala yang tidak ditentukan untuk mendapatkan penangan |
Denyut jantung | Memantau titik akhir untuk memeriksa pulsa server |
Logger | Mencatat awal dan akhir dari setiap permintaan dengan waktu pemrosesan yang berlalu |
Nocache | Menetapkan header respons untuk mencegah klien dari caching |
Profiler | Dengan mudah memasang net/http/pprof ke router Anda |
RealiP | Menetapkan HTTP.Request's RemoteAddr ke X-Real-IP atau X-Forwarded-For |
Pemulihan | Dengan anggun menyerap panik dan mencetak jejak tumpukan |
Permintaan | Menyuntikkan ID permintaan ke dalam konteks setiap permintaan |
Redirectslashes | Redirect slash di jalur perutean |
RuteHeaders | Penanganan rute untuk header permintaan |
Setheader | Middleware pendek untuk mengatur tombol/nilai header respons |
Stripslash | Strip slash di jalur perutean |
Matahari terbenam | Sunset Set Deprecation/Sunset Header untuk Respons |
Mencekik | Menempatkan langit -langit pada jumlah permintaan bersamaan |
Batas waktu | Sinyal ke konteks permintaan saat batas waktu batas waktu tercapai |
Urlformat | Parse Extension dari URL dan letakkan di konteks permintaan |
Nilai | Middleware pendek untuk mengatur kunci/nilai pada konteks permintaan |
Silakan lihat https://github.com/go-chi untuk paket tambahan.
kemasan | keterangan |
---|---|
CORS | Berbagi Sumber Daya Cross-Origin (CORS) |
docgen | Cetak rute chi.Router saat runtime |
jwttauth | Otentikasi JWT |
Hostrouter | Routing permintaan berbasis domain/host |
httplog | Pencatatan permintaan HTTP terstruktur kecil tapi kuat |
httprate | Pembatas Tingkat Permintaan HTTP |
httptracer | Perpustakaan Penelusuran Kinerja Permintaan HTTP |
httpvcr | Tulis tes deterministik untuk sumber eksternal |
menyerbu | Permintaan HTTP Coalescer |
context
adalah PKG kecil yang menyediakan antarmuka sederhana untuk memberi sinyal konteks di seluruh tumpukan panggilan dan goroutine. Awalnya ditulis oleh Sameer Ajmani dan tersedia di Stdlib sejak GO1.7.
Pelajari lebih lanjut di https://blog.golang.org/context
Dan..
The Benchmark Suite: https://github.com/pkielta/go-http-routing-benchmark
Hasil pada 29 November 2020 dengan GO 1.15.5 di Linux AMD 3950X
BenchmarkChi_Param 3075895 384 ns/op 400 B/op 2 allocs/op
BenchmarkChi_Param5 2116603 566 ns/op 400 B/op 2 allocs/op
BenchmarkChi_Param20 964117 1227 ns/op 400 B/op 2 allocs/op
BenchmarkChi_ParamWrite 2863413 420 ns/op 400 B/op 2 allocs/op
BenchmarkChi_GithubStatic 3045488 395 ns/op 400 B/op 2 allocs/op
BenchmarkChi_GithubParam 2204115 540 ns/op 400 B/op 2 allocs/op
BenchmarkChi_GithubAll 10000 113811 ns/op 81203 B/op 406 allocs/op
BenchmarkChi_GPlusStatic 3337485 359 ns/op 400 B/op 2 allocs/op
BenchmarkChi_GPlusParam 2825853 423 ns/op 400 B/op 2 allocs/op
BenchmarkChi_GPlus2Params 2471697 483 ns/op 400 B/op 2 allocs/op
BenchmarkChi_GPlusAll 194220 5950 ns/op 5200 B/op 26 allocs/op
BenchmarkChi_ParseStatic 3365324 356 ns/op 400 B/op 2 allocs/op
BenchmarkChi_ParseParam 2976614 404 ns/op 400 B/op 2 allocs/op
BenchmarkChi_Parse2Params 2638084 439 ns/op 400 B/op 2 allocs/op
BenchmarkChi_ParseAll 109567 11295 ns/op 10400 B/op 52 allocs/op
BenchmarkChi_StaticAll 16846 71308 ns/op 62802 B/op 314 allocs/op
Perbandingan dengan router lain: https://gist.github.com/pkielta/123032f12052520aaccab752bd3e78cc
CATATAN: Allocs dalam tolok ukur di atas berasal dari panggilan ke metode http.request WithContext(context.Context)
yang mengkloning http.request, menetapkan Context()
pada permintaan duplikat (alloc'd) dan mengembalikannya dengan permintaan baru obyek. Beginilah cara pengaturan konteks pada permintaan di Go Works.
Kami akan senang melihat kontribusi Anda!
Chi hanyalah router HTTP yang memungkinkan Anda menguraikan penanganan permintaan menjadi banyak lapisan yang lebih kecil. Banyak perusahaan menggunakan CHI untuk menulis layanan istirahat untuk API publik mereka. Tapi, istirahat hanyalah konvensi untuk mengelola status melalui HTTP, dan ada banyak karya lain yang diperlukan untuk menulis sistem klien-server lengkap atau jaringan layanan mikro.
Melihat di luar istirahat, saya juga merekomendasikan beberapa karya baru di lapangan:
Hak Cipta (C) 2015-sekarang Peter Kieltyka
Berlisensi di bawah lisensi MIT