service 包
service 包实现了 Nirvana 的 API 处理框架:
Service.ServeHTTP()
----------------------
↓ ↑
|-----Filters------| ↑
↓ ↑
|---Router Match---| ↑
↓ ↑
|-------------Middlewares------------|
↓ ↑
|-------------Executor---------------|
↓ ↑
|-ParameterGenerators-|-DestinationHandlers-|
↓ ↑
|------------User Function-----------|
service 包的入口是 Builder:
// Builder builds service.
type Builder interface {
// Logger returns logger of builder.
Logger() log.Logger
// SetLogger sets logger to server.
SetLogger(logger log.Logger)
// Modifier returns modifier of builder.
Modifier() DefinitionModifier
// SetModifier sets definition modifier.
SetModifier(m DefinitionModifier)
// Filters returns all request filters.
Filters() []Filter
// AddFilters add filters to filter requests.
AddFilter(filters ...Filter)
// AddDescriptors adds descriptors to router.
AddDescriptor(descriptors ...definition.Descriptor) error
// Middlewares returns all router middlewares.
Middlewares() map[string][]definition.Middleware
// Definitions returns all definitions. If a modifier exists, it will be executed.
Definitions() map[string][]definition.Definition
// Build builds a service to handle request.
Build() (Service, error)
}
type Service interface {
http.Handler
}
// DefinitionModifier is used in Server. It's used to modify definition.
// If you want to add some common data into all definitions, you can write
// a customized modifier for it.
type DefinitionModifier func(d *definition.Definition)
// Filter can filter request. It has the highest priority in a request
// lifecycle. It runs before router matching.
// If a filter return false, that means the request should be filtered.
// If a filter want to filter a request, it should handle the request
// by itself.
type Filter func(resp http.ResponseWriter, req *http.Request) bool
Builder 构建 Service 来提供 HTTP 服务。因此 Builder 提供了多个方法用于设置生成服务需要的日志,Definition 修改器,请求过滤器,API 描述符。构建完成的 Service 实际上是一个 http.Handler,用来处理请求。
其中 Definition 修改器用于在生成路由之前修改 API Definition。请求过滤器则是在 Service 执行的时候才会被调用,请求过滤器的优先级高于路由匹配。也就是说,在路由匹配之前,请求就有可能被过滤器直接过滤掉。
Builder 还会将 API Definition 转换为路由需要的数据结构,涉及到以下内容:
对应 Consumes 和 Produces 的 Consumer 和 Producer
Consumer 针对请求的 body,将数据转换为业务函数需要的数据类型(通常是结构体)。
Producer 则是将业务函数的返回值转换并写入到响应的 body 中。// Consumer handles specifically typed data from a reader and unmarshals it into an object. type Consumer interface { // ContentType returns a HTTP MIME type. ContentType() string // Consume unmarshals data from r into v. Consume(r io.Reader, v interface{}) error } // Producer marshals an object to specifically typed data and write it into a writer. type Producer interface { // ContentType returns a HTTP MIME type. ContentType() string // Produce marshals v to data and write to w. Produce(w io.Writer, v interface{}) error }
- 对应 Prefab 类型的 Prefab 生成器
这个生成器用于创建业务函数需要的特定实例,一般是服务端实例,即不是从请求里获取的数据而生成的。
service 包里提供了一个 Context Prefab 生成器,简单的将参数里的 context 返回出去,供业务函数使用。// Prefab creates instances for internal type. These instances are not // unmarshaled form http request data. type Prefab interface { // Name returns prefab name. Name() string // Type is instance type. Type() reflect.Type // Make makes an instance. Make(ctx context.Context) (interface{}, error) }
- 对应 golang 基础类型的转换器
这些转换器一般是用于将请求里的 query,header 等简单字符串数据转换为 golang 的基础类型,供业务函数使用。// Converter is used to convert []string to specific type. Data must have one // element at least or it will panic. type Converter func(ctx context.Context, data []string) (interface{}, error)
- 用于封装请求的 ValueContainer
这个接口是对 Request 的一次封装,方便获取对应位置的字符串数据。// ValueContainer contains values from a request. type ValueContainer interface { // Path returns path value by key. Path(key string) (string, bool) // Query returns value from query string. Query(key string) ([]string, bool) // Header returns value by header key. Header(key string) ([]string, bool) // Form returns value from request. It is valid when // http "Content-Type" is "application/x-www-form-urlencoded" // or "multipart/form-data". Form(key string) ([]string, bool) // File returns a file reader when "Content-Type" is "multipart/form-data". File(key string) (multipart.File, bool) // Body returns a reader to read data from request body. // The reader only can read once. Body() (reader io.ReadCloser, contentType string, ok bool) }
- 用于封装响应的 ResponseWriter
ResponseWriter 是对 http.ResponseWriter 的一个扩展,提供了一些功能方便中间件使用。// ResponseWriter extends http.ResponseWriter. type ResponseWriter interface { http.ResponseWriter // HeaderWritable can check whether WriteHeader() has // been called. If the method returns false, you should // not recall WriteHeader(). HeaderWritable() bool // StatusCode returns status code. StatusCode() int // ContentLength returns the length of written content. ContentLength() int }
- 用于合并请求和响应的 Context
HTTPContext 实现了 Context 接口,包装了请求的信息。作为路由上下文使用。// HTTPContext describes an http context. type HTTPContext interface { Request() *http.Request ResponseWriter() ResponseWriter ValueContainer() ValueContainer RoutePath() string }
- 用于生成业务函数的参数的 ParameterGenerator
ParameterGenerator 是真正的参数生成器,通过调用 Consumer,Converter,Prefab 等来完成业务函数的参数生成。// ParameterGenerator is used to generate object for a parameter. type ParameterGenerator interface { // Source returns the source generated by current generator. Source() definition.Source // Validate validates whether defaultValue and target type is valid. Validate(name string, defaultValue interface{}, target reflect.Type) error // Generate generates an object by data from value container. Generate(ctx context.Context, vc ValueContainer, consumers []Consumer, name string, target reflect.Type) (interface{}, error) }
用于将业务函数返回值写入 Response 的 DestinationHandler
DestinationHandler 是业务函数返回值处理器,通过调用 Producer 将返回值转换为字节写入响应中。
在 DestinationHandler 中,错误是会进行特殊处理的。如果业务函数返回的错误符合 Error 接口,则会根据这个接口来生成错误码和返回数据结构。// Error is a common interface for error. // If an error implements the interface, type handlers can // use Code() to get a specified HTTP status code. type Error interface { // Code is a HTTP status code. Code() int // Message is an object which contains information of the error. Message() interface{} } const ( // HighPriority for error type. // If an error occurs, ignore meta and data. HighPriority int = 100 // MediumPriority for meta type. MediumPriority int = 200 // LowPriority for data type. LowPriority int = 300 ) // DestinationHandler is used to handle the results from API handlers. type DestinationHandler interface { // Type returns definition.Type which the type handler can handle. Destination() definition.Destination // Priority returns priority of the type handler. Type handler with higher priority will prior execute. Priority() int // Validate validates whether the type handler can handle the target type. Validate(target reflect.Type) error // Handle handles a value. If the handler has something wrong, it should return an error. // The handler descides how to deal with value by producers and status code. // The status code is a success status code. If everything is ok, the handler should use the status code. // // There are three cases for return values (goon means go on or continue): // 1. go on is true, err is nil. // It means that current type handler did nothing (or looks like did nothing) and next type handler // should take the context. // 2. go on is false, err is nil. // It means that current type handler has finished the context and next type handler should not run. // 3. err is not nil // It means that current type handler handled the context but something wrong. All subsequent type // handlers should not run. Handle(ctx context.Context, producers []Producer, code int, value interface{}) (goon bool, err error) }
注:以上每个接口对应的实例都是可以通过相关的函数注册和修改的。