chi
- это легкий, идиоматический и композиционный маршрутизатор для зданий HTTP Services. Особенно хорошо помогает вам написать большие услуги API REST, которые поддерживаются по мере роста и изменения вашего проекта. chi
построен на новом context
пакете, введенном в GO 1.7 для обработки сигнализации, отмены и значений с запросом в цепочке обработчика.
В центре внимания проекта было поиск элегантного и удобного дизайна для написания серверов API Rest, написанного во время разработки услуги API Pressly, которая поддерживает нашу общественную службу API, в котором, в свою очередь, все наши приложения на стороне клиента.
Ключевыми соображениями конструкции CHI являются: структура проекта, обслуживание, стандартные обработчики HTTP (только для STDLIB), производительность разработчиков и деконструкция большой системы во многие мелкие детали. Основной маршрутизатор github.com/go-chi/chi
довольно мал (менее 1000 loc), но мы также включили несколько полезных/дополнительных подпакеров: промежуточное программное обеспечение, рендеринг и docgen. Мы надеемся, что вам тоже понравится!
go get -u github.com/go-chi/chi/v5
net/http
context
пакете, обеспечивая цепочку ценностей, отмены и тайм -аутыdocgen
Авторагенераты, маршрутизация, от вашего источника в JSON или MarkdownСм. _Examples/ для множества примеров.
Так же просто:
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 )
}
Предварительный просмотр REST:
Вот небольшой предварительный просмотр того, как выглядит маршрутизация с CHI. Также взгляните на сгенерированные документы маршрутизации в json (routes.json) и в Markdown (Routes.md).
Я настоятельно рекомендую прочитать источник примеров, перечисленных выше, они покажут вам все функции CHI и служат хорошей формой документации.
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 )
})
}
Маршрутизатор Чи основан на своего рода Патрисии Радикс Три. Маршрутизатор полностью совместим с net/http
.
На вершине дерева построен интерфейс 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
}
Каждый метод маршрутизации принимает pattern
URL и цепочку handlers
. У шаблона URL поддерживает именованные Params (т.е. /users/{userID}
) и подстановочные знаки (т.е. /admin/*
). Параметры URL могут быть получены во время выполнения, вызывая chi.URLParam(r, "userID")
для названных параметров и chi.URLParam(r, "*")
для параметра подстановочного знака.
Средние войны Чи - это просто обработчики промежуточного программного обеспечения STDLIB/HTTP. В них нет ничего особенного, что означает, что маршрутизатор и все инструменты предназначены для совместимых и дружелюбных с любым промежуточным программным обеспечением в сообществе. Это предлагает гораздо лучшую расширяемость и повторное использование пакетов и лежит в основе цели Чи.
Вот пример стандартного промежуточного программного обеспечения Net/HTTP, где мы назначаем контекстный ключ "user"
значение "123"
. Это промежуточное программное обеспечение устанавливает гипотетический идентификатор пользователя в контексте запроса и вызывает следующий обработчик в цепочке.
// 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 использует стандартные обработки сетевых/HTTP -запросов. Этот небольшой фрагмент является примером фанка HTTP.Handler, который считывает идентификатор пользователя из контекста запроса - гипотетически, идентифицируя пользователь, отправляющий аутентифицированный запрос, проверенный+установленным предыдущим промежуточным обработчиком.
// 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 анализируется и хранит параметры URL прямо в контексте запроса. Вот пример того, как получить доступ к URL -параметрам в ваших обработчиках Net/HTTP. И, конечно же, Middlewares могут получить доступ к той же информации.
// 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 оснащен дополнительным пакетом middleware
, предоставляя набор стандартных net/http
MiddleWares. Обратите внимание, что любое промежуточное программное обеспечение в экосистеме, которая также совместима с net/http
может использоваться с MUX CHI.
Чи/промежуточный обработчик | описание |
---|---|
Разрешить | Обеспечивает соблюдение белых заголовков запроса, кодирующих контент |
AllingContentType | Явный белый список принятых типов контента запроса |
Базовый | Основная HTTP -аутентификация |
Компресс | Сжатие GZIP для клиентов, которые принимают сжатые ответы |
Contentcharset | Убедитесь, что Charset для заголовков запросов типа контента |
Чистая дорожка | Очистите двойные удары по пути запроса |
Gethead | Автоматически направлять неопределенные запросы головы, чтобы получить обработчики |
Сердцебиение | Мониторинг конечной точки, чтобы проверить пульс серверов |
Регистратор | Регистрирует начало и конец каждого запроса с истекшим временем обработки |
Nocache | Устанавливает заголовки ответов, чтобы предотвратить кэширование клиентов |
Профилировщик | Легко прикрепить net/http/pprof к вашим маршрутизаторам |
Реал | Устанавливает http.request's Remoteaddr на x-real-IP или x-forwarded-for |
Восстановитель | Изящно впитывает панику и печатает трассировку стека |
RequestId | Внедряет идентификатор запроса в контекст каждого запроса |
Redirectslashes | Перенаправить черты на пути маршрутизации |
Главные головы | Обработка маршрутов для заголовков запроса |
Сетидер | Короткое промежуточное программное обеспечение, чтобы установить ключ/значение заголовка ответа |
Стрипслашес | Стрипные черты на пути маршрутизации |
Закат | Закат Университет Унимок/Закат Сансет на ответ |
Дроссельная заслонка | Ставит потолок на количество одновременных запросов |
Тайм -аут | Сигналы в контексте запроса, когда достигнут крайний срок действия тайм -аута |
Urlformat | Расширение Parse от URL и поместите его в контекст запроса |
С обложением | Короткое промежуточное программное обеспечение, чтобы установить ключ/значение в контексте запроса |
Пожалуйста, смотрите https://github.com/go-chi для дополнительных пакетов.
упаковка | описание |
---|---|
корр | Совместное использование ресурсов по перекрестному происхождению (CORS) |
докген | Печать Chi.router маршруты во время выполнения. |
jwtauth | Jwt аутентификация |
hostrouter | Маршрутизация запросов на основе домена/хоста |
httplog | Небольшой, но мощный структурированный HTTP -регистрация |
httprate | HTTP -ограничитель запроса. |
httptracer | HTTP -запрос библиотека трассировки производительности |
httpvcr | Напишите детерминированные тесты для внешних источников |
паническое давление | Http -запрос Coalescer |
context
- это крошечный PKG, который обеспечивает простой интерфейс для контекста сигнала между стеками вызовов и goroutines. Первоначально он был написан Someer Ajmani и доступен в Stdlib с GO1.7.
Узнайте больше на https://blog.golang.org/context
и..
The Bendchmark Suite: https://github.com/pkieltyka/go-http-routing-benchmark
Результаты по состоянию на 29 ноября 2020 года с GO 1.15.5 на 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
Сравнение с другими маршрутизаторами: https://gist.github.com/pkieltyka/123032F12052520AACCAB752BD3E78CC
ПРИМЕЧАНИЕ. Аллеки в эталонном вышеупомянутом методе взяты из WithContext(context.Context)
, который клонирует http.request, устанавливает Context()
на дублированном (Alloc'd) запросе и возвращает его новый запрос. объект. Так работает контекст настройки запроса в Go.
Мы будем более чем рады видеть ваш вклад!
CHI - это просто маршрутизатор HTTP, который позволяет разложить обработку запросов на множество меньших слоев. Многие компании используют CHI, чтобы написать услуги REST для своих публичных API. Но REST-это просто соглашение для управления состоянием через HTTP, и есть много других предметов, необходимых для написания полной системы клиентского сервера или сети микросервисов.
Глядя за пределы отдыха, я также рекомендую несколько новых работ в этой области:
Copyright (C)-2015-Present Peter Kieltyka
Лицензирована по лицензии MIT