# 路由

进入`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" 的路由，使用GET方式请求，默认处理Handler为howToStart方法
		g.POST("start", howToStart) // g.POST 创建一个 "kratos-demo/start" 的路由，使用POST方式请求，默认处理Handler为howToStart方法
	}
}
```

bm的handler方法，结构如下：

```go
func howToStart(c *bm.Context) // handler方法默认传入bm的Context对象
```

### Ping

engine自带Ping方法，用于设置`/ping`路由的handler，该路由统一提供于负载均衡服务做健康检测。服务是否健康，可自定义`ping handler`进行逻辑判断，如检测DB是否正常等。

```go
func ping(c *bm.Context) {
    if some DB check not ok {
        c.AbortWithStatus(503)
    }
}
```

# 默认路由

默认路由有：

* /metrics 用于prometheus信息采集
* /metadata 可以查看所有注册的路由信息

查看加载的所有路由信息：

```shell
curl 'http://127.0.0.1:8000/metadata'
```

输出：

```json
{
    "code": 0,
    "message": "0",
    "ttl": 1,
    "data": {
        "/kratos-demo/start": {
            "method": "GET"
        },
        "/metadata": {
            "method": "GET"
        },
        "/metrics": {
            "method": "GET"
        },
        "/ping": {
            "method": "GET"
        }
    }
}
```

# 路径参数

使用方式如下：

```go
func initRouter(e *bm.Engine) {
	e.Ping(ping)
	g := e.Group("/kratos-demo")
	{
		g.GET("/start", howToStart)

		// 路径参数有两个特殊符号":"和"*"
		// ":" 跟在"/"后面为参数的key，匹配两个/中间的值 或 一个/到结尾(其中不再包含/)的值
		// "*" 跟在"/"后面为参数的key，匹配从 /*开始到结尾的所有值，所有*必须写在最后且无法多个

		// NOTE：这是不被允许的，会和 /start 冲突
		// g.GET("/:xxx")

		// NOTE: 可以拿到一个key为name的参数。注意只能匹配到/param1/felix，无法匹配/param1/felix/hao(该路径会404)
		g.GET("/param1/:name", pathParam)
		// NOTE: 可以拿到多个key参数。注意只能匹配到/param2/felix/hao/love，无法匹配/param2/felix或/param2/felix/hao
		g.GET("/param2/:name/:value/:felid", pathParam)
		// NOTE: 可以拿到一个key为name的参数 和 一个key为action的路径。
		// NOTE: 如/params3/felix/hello，action的值为"/hello"
		// NOTE: 如/params3/felix/hello/hi，action的值为"/hello/hi"
		// NOTE: 如/params3/felix/hello/hi/，action的值为"/hello/hi/"
		g.GET("/param3/:name/*action", pathParam)
	}
}

func pathParam(c *bm.Context) {
	name, _ := c.Params.Get("name")
	value, _ := c.Params.Get("value")
	felid, _ := c.Params.Get("felid")
	action, _ := c.Params.Get("action")
	path := c.RoutePath // NOTE: 获取注册的路由原始地址，如: /kratos-demo/param1/:name
	c.JSONMap(map[string]interface{}{
		"name":   name,
		"value":  value,
		"felid":  felid,
		"action": action,
		"path":   path,
	}, nil)
}
```

# 性能分析

启动时默认监听了`2333`端口用于`pprof`信息采集，如：

```shell
go tool pprof http://127.0.0.1:8000/debug/pprof/profile
```

改变端口可以使用flag，如：`-http.perf=tcp://0.0.0.0:12333`

# 扩展阅读

[bm模块说明](blademaster-mod.md)  
[bm中间件](blademaster-mid.md)  
[bm基于pb生成](blademaster-pb.md)  

