chi
는 GO HTTP 서비스를 구축하기위한 가볍고 관용적이며 복합 가능한 라우터입니다. 프로젝트가 성장하고 변화함에 따라 유지 관리 가능한 대규모 REST API 서비스를 작성하는 데 특히 도움이됩니다. chi
는 GO 1.7에 도입 된 새로운 context
패키지를 기반으로 핸들러 체인에서 신호, 취소 및 요청 스코핑 된 값을 처리합니다.
이 프로젝트의 초점은 공개 API 서비스를 강화하는 프레스 다운 API 서비스를 개발하는 동안 작성된 REST API 서버를 작성하기위한 우아하고 편안한 디자인을 찾는 것이 었습니다.
Chi 설계의 주요 고려 사항은 프로젝트 구조, 유지 관리 가능성, 표준 HTTP 핸들러 (STDLIB 전용), 개발자 생산성 및 대형 시스템을 많은 작은 부품으로 해체하는 것입니다. 핵심 라우터 github.com/go-chi/chi
는 상당히 작지만 (1000 LOC 미만) 유용한/선택적 하위 포장 (미들웨어, 렌더 및 Docgen)도 포함했습니다. 우리는 당신도 그것을 즐기기를 바랍니다!
go get -u github.com/go-chi/chi/v5
net/http
와 호환되는 생태계에서 HTTP 또는 미들웨어 PKG를 사용하십시오.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 (LOTES.JSON)과 MarkDown (lours.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 )
})
}
Chi의 라우터는 일종의 Patricia radix trie를 기반으로합니다. 라우터는 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
}
각 라우팅 방법은 URL pattern
과 handlers
체인을 허용합니다. URL 패턴은 params (예 : /users/{userID}
) 및 와일드 카드 (예 : /admin/*
)를 지원합니다. URL 매개 변수는 이름 지정된 매개 변수의 경우 chi.URLParam(r, "userID")
호출하고 와일드 카드 매개 변수의 경우 chi.URLParam(r, "*")
호출하여 런타임에 가져올 수 있습니다.
Chi의 중간 전쟁은 단지 stdlib net/http 미들웨어 핸들러입니다. 그들에게는 특별한 것이 없으므로 라우터와 모든 툴링은 커뮤니티의 모든 미들웨어와 호환되고 친숙하도록 설계되었습니다. 이것은 패키지의 확장 성과 재사용을 훨씬 더 잘 제공하며 Chi의 목적의 핵심입니다.
다음은 컨텍스트 키 "user"
"123"
값을 할당하는 표준 NET/HTTP 미들웨어의 예입니다. 이 미들웨어는 요청 컨텍스트에서 가상의 사용자 식별자를 설정하고 체인에서 다음 처리기를 호출합니다.
// 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는 표준 NET/HTTP 요청 처리기를 사용합니다. 이 작은 스 니펫은 요청 컨텍스트에서 사용자 식별자를 읽는 http.handler func의 예입니다. 가설 적으로, 이전 미들웨어 핸들러에 의해 확인 된 인증 된 요청을 보내는 사용자를 식별합니다.
// 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 매개 변수를 요청 컨텍스트에 바로 구문 분석하고 저장합니다. 다음은 NET/HTTP 핸들러에서 URL 매개 변수에 액세스하는 방법의 예입니다. And of course, middlewares are able to access the same information.
// 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 comes equipped with an optional middleware
package, providing a suite of standard net/http
middlewares. Please note, any middleware in the ecosystem that is also compatible with net/http
can be used with chi's mux.
Chi/Middleware 처리기 | 설명 |
---|---|
허용 콘텐츠 인코딩 | 요청 컨텐츠 인코딩 헤더의 화이트리스트를 시행합니다 |
allowContentType | 허용 된 요청 컨텐츠 유형의 명시 적 화이트리스트 |
BASICAUTH | 기본 HTTP 인증 |
압박 붕대 | 압축 응답을 수락하는 클라이언트를위한 GZIP 압축 |
ContentCharset | 컨텐츠 유형 요청 헤더에 대한 charset을 확인하십시오 |
클린 경로 | 요청 경로에서 이중 슬래시를 청소하십시오 |
gethead | 정의되지 않은 헤드 요청을 자동으로 노선하여 핸들러를 얻습니다 |
심장 박동 | 서버 펄스를 확인하려면 엔드 포인트 모니터링 |
나무꾼 | 경과 처리 처리 시간으로 각 요청의 시작 및 끝을 기록합니다. |
Nocache | 클라이언트가 캐싱을 방지하기 위해 응답 헤더를 설정합니다 |
프로파일 러 | Easily attach net/http/pprof to your routers |
realip | http.request의 remoteaddr를 Xeal-IP 또는 X-forwarded-for로 설정합니다 |
복구 자 | 공황을 우아하게 흡수하고 스택 추적을 인쇄합니다 |
requestId | 각 요청의 컨텍스트에 요청 ID를 주입합니다. |
리디렉션 슬래시 | 라우팅 경로에서 슬래시를 리디렉션합니다 |
RouteHeaders | 요청 헤더에 대한 경로 처리 |
세 테더 | 응답 헤더 키/값을 설정하려면 단기간 미들웨어 |
스트립 슬래시 | 라우팅 경로에서 슬래시를 벗겨냅니다 |
일몰 | 일몰 세트 감가 상각/일몰 헤더는 응답으로 |
조절판 | 동시 요청 수에 천장을 넣습니다 |
시간 초과 | 시간 초과 마감일에 도달하면 요청 컨텍스트에 대한 신호 |
urlformat | URL에서 연장을 구문 분석하고 요청 컨텍스트에 넣습니다. |
value | 요청 컨텍스트에서 키/값을 설정하려면 단기간 미들웨어 |
추가 패키지는 https://github.com/go-chi를 참조하십시오.
패키지 | 설명 |
---|---|
코스 | 크로스 오리핀 자원 공유 (CORS) |
Docgen | 런타임에 chi.router 경로를 인쇄하십시오 |
jwtauth | JWT 인증 |
호스트 로터 | 도메인/호스트 기반 요청 라우팅 |
httplog | 작지만 강력한 구조화 된 HTTP 요청 로깅 |
httprate | HTTP 요청 비율 리미터 |
httptracer | HTTP 요청 성능 추적 라이브러리 |
httpvcr | 외부 소스에 대한 결정 론적 테스트를 작성하십시오 |
우르르 도망치게 하다 | HTTP 요청 Coalescer |
context
는 통화 스택 및 고리 틴에서 컨텍스트를 신호 할 수있는 간단한 인터페이스를 제공하는 작은 PKG입니다. 그것은 원래 Sameer Ajmani가 작성했으며 Go1.7 이후 stdlib에서 사용할 수 있습니다.
https://blog.golang.org/context에서 자세히 알아보십시오
그리고..
벤치 마크 스위트 : https://github.com/pkieltyka/go-http-routing-benchmark
2020 년 11 월 29 일 기준 Linux AMD 3950X에서 Go 1.15.5와 함께
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
참고 : 위의 벤치 마크의 할당은 http.request의 호출 http.request를 클론하는 http.request의 WithContext(context.Context)
메소드로의 통화에서부터 복제 된 (alloc'd) 요청에서 Context()
를 설정하고 새 요청을 반환합니다. 물체. 이것은 GO 요청에서 컨텍스트를 설정하는 방법입니다.
우리는 당신의 기여를 보게되어 기쁩니다!
Chi는 HTTP 라우터 일뿐 아니라 많은 작은 레이어로 요청 처리를 분해 할 수 있습니다. 많은 회사들이 Chi를 사용하여 공개 API에 대한 휴식 서비스를 작성합니다. 그러나 REST는 HTTP를 통해 상태를 관리하기위한 협약 일 뿐이며, 완전한 클라이언트 서버 시스템 또는 마이크로 서비스 네트워크를 작성하는 데 필요한 다른 부분이 많이 있습니다.
휴식을 넘어서서, 나는 또한 현장에서 새로운 작품을 추천합니다.
저작권 (C) 2015 년 Peter Kieltyka
MIT 라이센스에 따라 라이센스