mirror of
https://github.com/go-kratos/kratos.git
synced 2025-03-17 21:07:54 +02:00
add doc with blademaster
This commit is contained in:
parent
2739a26481
commit
0c58cd9c5a
BIN
doc/img/bm-arch-2-2.png
Normal file
BIN
doc/img/bm-arch-2-2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.7 KiB |
BIN
doc/img/bm-arch-2-3.png
Normal file
BIN
doc/img/bm-arch-2-3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
BIN
doc/img/bm-handlers.png
Normal file
BIN
doc/img/bm-handlers.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
@ -0,0 +1,104 @@
|
||||
# 背景
|
||||
|
||||
基于bm的handler机制,可以自定义很多middleware(中间件)进行通用的业务处理,比如用户登录鉴权。接下来就以鉴权为例,说明middleware的写法和用法。
|
||||
|
||||
# 写自己的中间件
|
||||
|
||||
middleware本质上就是一个handler,如下代码:
|
||||
```go
|
||||
// Handler responds to an HTTP request.
|
||||
type Handler interface {
|
||||
ServeHTTP(c *Context)
|
||||
}
|
||||
|
||||
// HandlerFunc http request handler function.
|
||||
type HandlerFunc func(*Context)
|
||||
|
||||
// ServeHTTP calls f(ctx).
|
||||
func (f HandlerFunc) ServeHTTP(c *Context) {
|
||||
f(c)
|
||||
}
|
||||
```
|
||||
|
||||
1. 实现了`Handler`接口,可以作为engine的全局中间件使用:`engine.User(YourHandler)`
|
||||
2. 声明为`HandlerFunc`方法,可以作为router的局部中间件使用:`e.GET("/path", YourHandlerFunc)`
|
||||
|
||||
简单示例代码如下:
|
||||
|
||||
```go
|
||||
type Demo struct {
|
||||
Key string
|
||||
Value string
|
||||
}
|
||||
// ServeHTTP implements from Handler interface
|
||||
func (d *Demo) ServeHTTP(ctx *bm.Context) {
|
||||
ctx.Set(d.Key, d.Value)
|
||||
}
|
||||
|
||||
e := bm.DefaultServer(nil)
|
||||
d := &Demo{}
|
||||
|
||||
// Handler使用如下:
|
||||
e.Use(d)
|
||||
|
||||
// HandlerFunc使用如下:
|
||||
e.GET("/path", d.ServeHTTP)
|
||||
|
||||
// 或者只有方法
|
||||
myHandler := func(ctx *bm.Context) {
|
||||
// some code
|
||||
}
|
||||
e.GET("/path", myHandler)
|
||||
```
|
||||
|
||||
|
||||
# 全局中间件
|
||||
|
||||
在blademaster的`server.go`代码中,有以下代码:
|
||||
|
||||
```go
|
||||
func DefaultServer(conf *ServerConfig) *Engine {
|
||||
engine := NewServer(conf)
|
||||
engine.Use(Recovery(), Trace(), Logger())
|
||||
return engine
|
||||
}
|
||||
```
|
||||
|
||||
会默认创建一个bm engine,并注册`Recovery(), Trace(), Logger()`三个middlerware,用于全局handler处理。优先级从前到后。
|
||||
如果需要自定义默认全局执行的middleware,可以使用`NewServer`方法创建一个无middleware的engine对象。
|
||||
如果想要将自定义的middleware注册进全局,可以继续调用Use方法如下:
|
||||
|
||||
```go
|
||||
engine.Use(YourMiddleware())
|
||||
```
|
||||
|
||||
此方法会将`YourMiddleware`追加到已有的全局middleware后执行。
|
||||
|
||||
# 局部中间件
|
||||
|
||||
先来看一段示例(代码再pkg/net/http/blademaster/middleware/auth模块下):
|
||||
|
||||
```go
|
||||
func Example() {
|
||||
myHandler := func(ctx *bm.Context) {
|
||||
mid := metadata.Int64(ctx, metadata.Mid)
|
||||
ctx.JSON(fmt.Sprintf("%d", mid), nil)
|
||||
}
|
||||
|
||||
authn := auth.New(&auth.Config{DisableCSRF: false})
|
||||
|
||||
e := bm.DefaultServer(nil)
|
||||
|
||||
// "/user"接口必须保证登录用户才能访问,那么我们加入"auth.User"来确保用户鉴权通过,才能进入myHandler进行业务逻辑处理
|
||||
e.GET("/user", authn.User, myHandler)
|
||||
// "/guest"接口访客用户就可以访问,但如果登录用户我们需要知道mid,那么我们加入"auth.Guest"来尝试鉴权获取mid,但肯定会继续执行myHandler进行业务逻辑处理
|
||||
e.GET("/guest", authn.Guest, myHandler)
|
||||
|
||||
// "/owner"开头的所有接口,都需要进行登录鉴权才可以被访问,那可以创建一个group并加入"authn.User"
|
||||
o := e.Group("/owner", authn.User)
|
||||
o.GET("/info", myHandler) // 该group创建的router不需要再显示的加入"authn.User"
|
||||
o.POST("/modify", myHandler) // 该group创建的router不需要再显示的加入"authn.User"
|
||||
|
||||
e.Start()
|
||||
}
|
||||
```
|
79
doc/wiki-cn/blademaster-mod.md
Normal file
79
doc/wiki-cn/blademaster-mod.md
Normal file
@ -0,0 +1,79 @@
|
||||
# Context
|
||||
|
||||
以下是 blademaster 中 Context 对象结构体声明的代码片段:
|
||||
```go
|
||||
// Context is the most important part. It allows us to pass variables between
|
||||
// middleware, manage the flow, validate the JSON of a request and render a
|
||||
// JSON response for example.
|
||||
type Context struct {
|
||||
context.Context
|
||||
|
||||
Request *http.Request
|
||||
Writer http.ResponseWriter
|
||||
|
||||
// flow control
|
||||
index int8
|
||||
handlers []HandlerFunc
|
||||
|
||||
// Keys is a key/value pair exclusively for the context of each request.
|
||||
Keys map[string]interface{}
|
||||
|
||||
Error error
|
||||
|
||||
method string
|
||||
engine *Engine
|
||||
}
|
||||
```
|
||||
|
||||
* 首先可以看到 blademaster 的 Context 结构体中会 embed 一个标准库中的 Context 实例,bm 中的 Context 也是直接通过该实例来实现标准库中的 Context 接口。
|
||||
* Request 和 Writer 字段用于获取当前请求的与输出响应。
|
||||
* index 和 handlers 用于 handler 的流程控制;handlers 中存储了当前请求需要执行的所有 handler,index 用于标记当前正在执行的 handler 的索引位。
|
||||
* Keys 用于在 handler 之间传递一些额外的信息。
|
||||
* Error 用于存储整个请求处理过程中的错误。
|
||||
* method 用于检查当前请求的 Method 是否与预定义的相匹配。
|
||||
* engine 字段指向当前 blademaster 的 Engine 实例。
|
||||
|
||||
以下为 Context 中所有的公开的方法:
|
||||
```go
|
||||
// 用于 Handler 的流程控制
|
||||
func (c *Context) Abort()
|
||||
func (c *Context) AbortWithStatus(code int)
|
||||
func (c *Context) Bytes(code int, contentType string, data ...[]byte)
|
||||
func (c *Context) IsAborted() bool
|
||||
func (c *Context) Next()
|
||||
|
||||
// 用户获取或者传递请求的额外信息
|
||||
func (c *Context) RemoteIP() (cip string)
|
||||
func (c *Context) Set(key string, value interface{})
|
||||
func (c *Context) Get(key string) (value interface{}, exists bool)
|
||||
|
||||
// 用于校验请求的 payload
|
||||
func (c *Context) Bind(obj interface{}) error
|
||||
func (c *Context) BindWith(obj interface{}, b binding.Binding) error
|
||||
|
||||
// 用于输出响应
|
||||
func (c *Context) Render(code int, r render.Render)
|
||||
func (c *Context) Redirect(code int, location string)
|
||||
func (c *Context) Status(code int)
|
||||
func (c *Context) String(code int, format string, values ...interface{})
|
||||
func (c *Context) XML(data interface{}, err error)
|
||||
func (c *Context) JSON(data interface{}, err error)
|
||||
func (c *Context) JSONMap(data map[string]interface{}, err error)
|
||||
func (c *Context) Protobuf(data proto.Message, err error)
|
||||
```
|
||||
|
||||
所有方法基本上可以分为三类:
|
||||
|
||||
* 流程控制
|
||||
* 额外信息传递
|
||||
* 请求处理
|
||||
* 响应处理
|
||||
|
||||
# Handler
|
||||
|
||||

|
||||
|
||||
初次接触 blademaster 的用户可能会对其 Handler 的流程处理产生不小的疑惑,实际上 bm 对 Handler 对处理非常简单。
|
||||
将 Router 模块中预先注册的中间件与其他 Handler 合并,放入 Context 的 handlers 字段,并将 index 置 0,然后通过 Next() 方法一个个执行下去。
|
||||
部分中间件可能想要在过程中中断整个流程,此时可以使用 Abort() 方法提前结束处理。
|
||||
有些中间件还想在所有 Handler 执行完后再执行部分逻辑,此时可以在自身 Handler 中显式调用 Next() 方法,并将这些逻辑放在调用了 Next() 方法之后。
|
64
doc/wiki-cn/blademaster-quickstart.md
Normal file
64
doc/wiki-cn/blademaster-quickstart.md
Normal file
@ -0,0 +1,64 @@
|
||||
# 准备工作
|
||||
|
||||
推荐使用[kratos tool](kratos-tool.md)快速生成项目,如我们生成一个叫`kratos-demo`的项目。
|
||||
|
||||
生成目录结构如下:
|
||||
```
|
||||
├── CHANGELOG.md
|
||||
├── CONTRIBUTORS.md
|
||||
├── LICENSE
|
||||
├── README.md
|
||||
├── cmd
|
||||
│ ├── cmd
|
||||
│ └── main.go
|
||||
├── configs
|
||||
│ ├── application.toml
|
||||
│ ├── grpc.toml
|
||||
│ ├── http.toml
|
||||
│ ├── log.toml
|
||||
│ ├── memcache.toml
|
||||
│ ├── mysql.toml
|
||||
│ └── redis.toml
|
||||
├── go.mod
|
||||
├── go.sum
|
||||
└── internal
|
||||
├── dao
|
||||
│ └── dao.go
|
||||
├── model
|
||||
│ └── model.go
|
||||
├── server
|
||||
│ └── http
|
||||
│ └── http.go
|
||||
└── service
|
||||
└── service.go
|
||||
```
|
||||
|
||||
# 路由
|
||||
|
||||
创建项目成功后,进入`internal/server/http`目录下,打开`http.go`文件,其中有默认生成的`blademaster`模板。其中:
|
||||
```go
|
||||
engine = bm.DefaultServer(hc.Server)
|
||||
initRouter(engine)
|
||||
if err := engine.Start(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
```
|
||||
是bm默认创建的`engine`及启动代码,我们看`initRouter`初始化路由方法,默认实现了:
|
||||
```go
|
||||
func initRouter(e *bm.Engine) {
|
||||
e.Ping(ping) // engine自带的"/ping"接口,用于负载均衡检测服务健康状态
|
||||
g := e.Group("/kratos-demo") // e.Group 创建一组 "/kratos-demo" 起始的路由组
|
||||
{
|
||||
g.GET("/start", howToStart) // g.GET 创建一个 "kratos-demo/start" 的路由,默认处理Handler为howToStart方法
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
bm的handler方法,结构如下:
|
||||
```go
|
||||
func howToStart(c *bm.Context) // handler方法默认传入bm的Context对象
|
||||
```
|
||||
|
||||
# 扩展阅读
|
||||
|
||||
[bm模块说明](blademaster-mod.md) [bm中间件](blademaster-mid.md) [bm基于pb生成](blademaster-pb.md)
|
@ -0,0 +1,33 @@
|
||||
# 背景
|
||||
|
||||
在像微服务这样的分布式架构中,经常会有一些需求需要你调用多个服务,但是还需要确保服务的安全性、同一化每次的请求日志或者追踪用户完整的行为等等。要实现这些功能,你可能需要在所有服务中都设置一些相同的属性,虽然这个可以通过一些明确的接入文档来描述或者准入规范来界定,但是这么做的话还是有可能会有一些问题:
|
||||
|
||||
1. 你很难让每一个服务都实现上述功能。因为对于开发者而言,他们应当注重的是实现功能。很多项目的开发者经常在一些日常开发中遗漏了这些关键点,经常有人会忘记去打日志或者去记录调用链。但是对于一些大流量的互联网服务而言,一个线上服务一旦发生故障时,即使故障时间很小,其影响面会非常大。一旦有人在关键路径上忘记路记录日志,那么故障的排除成本会非常高,那样会导致影响面进一步扩大。
|
||||
2. 事实上实现之前叙述的这些功能的成本也非常高。比如说对于鉴权(Identify)这个功能,你要是去一个服务一个服务地去实现,那样的成本也是非常高的。如果说把这个确保认证的责任分担在每个开发者身上,那样其实也会增加大家遗忘或者忽略的概率。
|
||||
|
||||
为了解决这样的问题,你可能需要一个框架来帮助你实现这些功能。比如说帮你在一些关键路径的请求上配置必要的鉴权或超时策略。那样服务间的调用会被多层中间件所过滤并检查,确保整体服务的稳定性。
|
||||
|
||||
# 设计目标
|
||||
|
||||
* 性能优异,不应该惨杂太多业务逻辑的成分
|
||||
* 方便开发使用,开发对接的成本应该尽可能地小
|
||||
* 后续鉴权、认证等业务逻辑的模块应该可以通过业务模块的开发接入该框架内
|
||||
* 默认配置已经是 production ready 的配置,减少开发与线上环境的差异性
|
||||
|
||||
# 概览
|
||||
|
||||
* 参考`gin`设计整套HTTP框架,去除`gin`中不需要的部分逻辑
|
||||
* 内置一些必要的中间件,便于业务方可以直接上手使用
|
||||
|
||||
# blademaster架构
|
||||
|
||||

|
||||
|
||||
blademaster 由几个非常精简的内部模块组成。其中 Router 用于根据请求的路径分发请求,Context 包含了一个完整的请求信息,Handler 则负责处理传入的 Context,Handlers 为一个列表,一个串一个地执行。
|
||||
所有的中间件均以 Handler 的形式存在,这样可以保证 blademaster 自身足够精简,且扩展性足够强。
|
||||
|
||||

|
||||
|
||||
blademaster 处理请求的模式非常简单,大部分的逻辑都被封装在了各种 Handler 中。一般而言,业务逻辑作为最后一个 Handler。正常情况下,每个 Handler 按照顺序一个一个串形地执行下去。
|
||||
但是 Handler 中可以也中断整个处理流程,直接输出 Response。这种模式常被用于校验登陆的中间件中;一旦发现请求不合法,直接响应拒绝。
|
||||
请求处理的流程中也可以使用 Render 来辅助渲染 Response,比如对于不同的请求需要响应不同的数据格式(JSON、XML),此时可以使用不同的 Render 来简化逻辑。
|
@ -4,8 +4,10 @@
|
||||
* [快速开始](quickstart.md)
|
||||
* [案例](https://github.com/bilibili/kratos-demo)
|
||||
* [http blademaster](blademaster.md)
|
||||
* [middleware](blademaster-mid.md)
|
||||
* [protobuf生成](blademaster-pb.md)
|
||||
* [bm quickstart](blademaster-quickstart.md)
|
||||
* [bm module](blademaster-mod.md)
|
||||
* [bm middleware](blademaster-mid.md)
|
||||
* [bm protobuf](blademaster-pb.md)
|
||||
* [grpc warden](warden.md)
|
||||
* [middleware](warden-mid.md)
|
||||
* [protobuf生成](warden-pb.md)
|
||||
|
7
pkg/net/http/blademaster/middleware/auth/README.md
Normal file
7
pkg/net/http/blademaster/middleware/auth/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
#### blademaster/middleware/auth
|
||||
|
||||
##### 项目简介
|
||||
|
||||
blademaster 的 authorization middleware,主要用于设置路由的认证策略
|
||||
|
||||
注:仅仅是个demo,请根据自身业务实现具体鉴权逻辑
|
153
pkg/net/http/blademaster/middleware/auth/auth.go
Normal file
153
pkg/net/http/blademaster/middleware/auth/auth.go
Normal file
@ -0,0 +1,153 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"github.com/bilibili/kratos/pkg/ecode"
|
||||
bm "github.com/bilibili/kratos/pkg/net/http/blademaster"
|
||||
"github.com/bilibili/kratos/pkg/net/metadata"
|
||||
)
|
||||
|
||||
// Config is the identify config model.
|
||||
type Config struct {
|
||||
// csrf switch.
|
||||
DisableCSRF bool
|
||||
}
|
||||
|
||||
// Auth is the authorization middleware
|
||||
type Auth struct {
|
||||
conf *Config
|
||||
}
|
||||
|
||||
// authFunc will return mid and error by given context
|
||||
type authFunc func(*bm.Context) (int64, error)
|
||||
|
||||
var _defaultConf = &Config{
|
||||
DisableCSRF: false,
|
||||
}
|
||||
|
||||
// New is used to create an authorization middleware
|
||||
func New(conf *Config) *Auth {
|
||||
if conf == nil {
|
||||
conf = _defaultConf
|
||||
}
|
||||
auth := &Auth{
|
||||
conf: conf,
|
||||
}
|
||||
return auth
|
||||
}
|
||||
|
||||
// User is used to mark path as access required.
|
||||
// If `access_token` is exist in request form, it will using mobile access policy.
|
||||
// Otherwise to web access policy.
|
||||
func (a *Auth) User(ctx *bm.Context) {
|
||||
req := ctx.Request
|
||||
if req.Form.Get("access_token") == "" {
|
||||
a.UserWeb(ctx)
|
||||
return
|
||||
}
|
||||
a.UserMobile(ctx)
|
||||
}
|
||||
|
||||
// UserWeb is used to mark path as web access required.
|
||||
func (a *Auth) UserWeb(ctx *bm.Context) {
|
||||
a.midAuth(ctx, a.authCookie)
|
||||
}
|
||||
|
||||
// UserMobile is used to mark path as mobile access required.
|
||||
func (a *Auth) UserMobile(ctx *bm.Context) {
|
||||
a.midAuth(ctx, a.authToken)
|
||||
}
|
||||
|
||||
// Guest is used to mark path as guest policy.
|
||||
// If `access_token` is exist in request form, it will using mobile access policy.
|
||||
// Otherwise to web access policy.
|
||||
func (a *Auth) Guest(ctx *bm.Context) {
|
||||
req := ctx.Request
|
||||
if req.Form.Get("access_token") == "" {
|
||||
a.GuestWeb(ctx)
|
||||
return
|
||||
}
|
||||
a.GuestMobile(ctx)
|
||||
}
|
||||
|
||||
// GuestWeb is used to mark path as web guest policy.
|
||||
func (a *Auth) GuestWeb(ctx *bm.Context) {
|
||||
a.guestAuth(ctx, a.authCookie)
|
||||
}
|
||||
|
||||
// GuestMobile is used to mark path as mobile guest policy.
|
||||
func (a *Auth) GuestMobile(ctx *bm.Context) {
|
||||
a.guestAuth(ctx, a.authToken)
|
||||
}
|
||||
|
||||
// authToken is used to authorize request by token
|
||||
func (a *Auth) authToken(ctx *bm.Context) (int64, error) {
|
||||
req := ctx.Request
|
||||
key := req.Form.Get("access_token")
|
||||
if key == "" {
|
||||
return 0, ecode.Unauthorized
|
||||
}
|
||||
// NOTE: 请求登录鉴权服务接口,拿到对应的用户id
|
||||
var mid int64
|
||||
// TODO: get mid from some code
|
||||
return mid, nil
|
||||
}
|
||||
|
||||
// authCookie is used to authorize request by cookie
|
||||
func (a *Auth) authCookie(ctx *bm.Context) (int64, error) {
|
||||
req := ctx.Request
|
||||
session, _ := req.Cookie("SESSION")
|
||||
if session == nil {
|
||||
return 0, ecode.Unauthorized
|
||||
}
|
||||
// NOTE: 请求登录鉴权服务接口,拿到对应的用户id
|
||||
var mid int64
|
||||
// TODO: get mid from some code
|
||||
|
||||
// check csrf
|
||||
clientCsrf := req.FormValue("csrf")
|
||||
if a.conf != nil && !a.conf.DisableCSRF && req.Method == "POST" {
|
||||
// NOTE: 如果开启了CSRF认证,请从CSRF服务获取该用户关联的csrf
|
||||
var csrf string // TODO: get csrf from some code
|
||||
if clientCsrf != csrf {
|
||||
return 0, ecode.Unauthorized
|
||||
}
|
||||
}
|
||||
|
||||
return mid, nil
|
||||
}
|
||||
|
||||
func (a *Auth) midAuth(ctx *bm.Context, auth authFunc) {
|
||||
mid, err := auth(ctx)
|
||||
if err != nil {
|
||||
ctx.JSON(nil, err)
|
||||
ctx.Abort()
|
||||
return
|
||||
}
|
||||
setMid(ctx, mid)
|
||||
}
|
||||
|
||||
func (a *Auth) guestAuth(ctx *bm.Context, auth authFunc) {
|
||||
mid, err := auth(ctx)
|
||||
// no error happened and mid is valid
|
||||
if err == nil && mid > 0 {
|
||||
setMid(ctx, mid)
|
||||
return
|
||||
}
|
||||
|
||||
ec := ecode.Cause(err)
|
||||
if ecode.Equal(ec, ecode.Unauthorized) {
|
||||
ctx.JSON(nil, ec)
|
||||
ctx.Abort()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// set mid into context
|
||||
// NOTE: This method is not thread safe.
|
||||
func setMid(ctx *bm.Context, mid int64) {
|
||||
ctx.Set(metadata.Mid, mid)
|
||||
if md, ok := metadata.FromContext(ctx); ok {
|
||||
md[metadata.Mid] = mid
|
||||
return
|
||||
}
|
||||
}
|
40
pkg/net/http/blademaster/middleware/auth/example_test.go
Normal file
40
pkg/net/http/blademaster/middleware/auth/example_test.go
Normal file
@ -0,0 +1,40 @@
|
||||
package auth_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
bm "github.com/bilibili/kratos/pkg/net/http/blademaster"
|
||||
"github.com/bilibili/kratos/pkg/net/http/blademaster/middleware/auth"
|
||||
"github.com/bilibili/kratos/pkg/net/metadata"
|
||||
)
|
||||
|
||||
// This example create a identify middleware instance and attach to several path,
|
||||
// it will validate request by specified policy and put extra information into context. e.g., `mid`.
|
||||
// It provides additional handler functions to provide the identification for your business handler.
|
||||
func Example() {
|
||||
myHandler := func(ctx *bm.Context) {
|
||||
mid := metadata.Int64(ctx, metadata.Mid)
|
||||
ctx.JSON(fmt.Sprintf("%d", mid), nil)
|
||||
}
|
||||
|
||||
authn := auth.New(&auth.Config{
|
||||
DisableCSRF: false,
|
||||
})
|
||||
|
||||
e := bm.DefaultServer(nil)
|
||||
|
||||
// mark `/user` path as User policy
|
||||
e.GET("/user", authn.User, myHandler)
|
||||
// mark `/mobile` path as UserMobile policy
|
||||
e.GET("/mobile", authn.UserMobile, myHandler)
|
||||
// mark `/web` path as UserWeb policy
|
||||
e.GET("/web", authn.UserWeb, myHandler)
|
||||
// mark `/guest` path as Guest policy
|
||||
e.GET("/guest", authn.Guest, myHandler)
|
||||
|
||||
o := e.Group("/owner", authn.User)
|
||||
o.GET("/info", myHandler)
|
||||
o.POST("/modify", myHandler)
|
||||
|
||||
e.Start()
|
||||
}
|
@ -120,6 +120,7 @@ func main() {
|
||||
|
||||
# Reviewer
|
||||
`
|
||||
|
||||
_tplDao = `package dao
|
||||
|
||||
import (
|
||||
@ -312,11 +313,12 @@ func (s *Service) Close() {
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"{{.Name}}/internal/model"
|
||||
"{{.Name}}/internal/service"
|
||||
|
||||
"github.com/bilibili/kratos/pkg/conf/paladin"
|
||||
"github.com/bilibili/kratos/pkg/log"
|
||||
bm "github.com/bilibili/kratos/pkg/net/http/blademaster"
|
||||
"github.com/bilibili/kratos/pkg/net/http/blademaster/middleware/verify"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -337,19 +339,18 @@ func New(s *service.Service) (engine *bm.Engine) {
|
||||
}
|
||||
svc = s
|
||||
engine = bm.DefaultServer(hc.Server)
|
||||
initRouter(engine, verify.New(nil))
|
||||
initRouter(engine)
|
||||
if err := engine.Start(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func initRouter(e *bm.Engine, v *verify.Verify) {
|
||||
func initRouter(e *bm.Engine) {
|
||||
e.Ping(ping)
|
||||
e.Register(register)
|
||||
g := e.Group("/{{.Name}}")
|
||||
{
|
||||
g.GET("/start", v.Verify, howToStart)
|
||||
g.GET("/start", howToStart)
|
||||
}
|
||||
}
|
||||
|
||||
@ -360,14 +361,14 @@ func ping(ctx *bm.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
func register(c *bm.Context) {
|
||||
c.JSON(map[string]interface{}{}, nil)
|
||||
}
|
||||
|
||||
// example for http request handler.
|
||||
func howToStart(c *bm.Context) {
|
||||
c.String(0, "Golang 大法好 !!!")
|
||||
k := &model.Kratos{
|
||||
Hello: "Golang 大法好 !!!",
|
||||
}
|
||||
c.JSON(k, nil)
|
||||
}
|
||||
|
||||
`
|
||||
_tplAPIProto = `// 定义项目 API 的 proto 文件 可以同时描述 gRPC 和 HTTP API
|
||||
// protobuf 文件参考:
|
||||
@ -411,7 +412,11 @@ message HelloReq {
|
||||
//go:generate TODO:待完善工具protoc.sh
|
||||
`
|
||||
_tplModel = `package model
|
||||
`
|
||||
|
||||
// Kratos hello kratos.
|
||||
type Kratos struct {
|
||||
Hello string
|
||||
}`
|
||||
_tplGRPCServer = `package grpc
|
||||
|
||||
import (
|
||||
|
Loading…
x
Reference in New Issue
Block a user