# gee-web
**Repository Path**: bankarian/gee-web
## Basic Information
- **Project Name**: gee-web
- **Description**: Go 练手项目,实现一个基础的 Web 框架。
- **Primary Language**: Go
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2021-01-06
- **Last Updated**: 2021-04-11
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 功能总结
## 1、http 服务
Engine 类型作为 gee 的核心,实现了 http.Handler 接口,用于提供基本的 http 服务。
## 2、路由
### 2.1 基础路由
以 map 来存储路由和与其绑定的处理函数,**URL-http 方法**作为 map 的 Key,具体的处理函数 handler 作为 map 的 Value。
### 2.2 路由组
路由组能更加方便地支持从 URL 的某一个部分分叉,拓展路由。
```go
// Using route group
engine := gee.New()
g := engine.Group("/somepath")
{
g.GET("/aaa", /* ... */)
g.GET("/bbb", /* ... */)
}
// Using common route
engine := gee.New()
g.GET("/sompath/aaa", /* ... */)
g.GET("/somepath/bbb", /* ... */)
```
为了支持路由组,所有的路由使用 Trie 来进行存储,**每一个 http 方法对应一棵 Trie**。
```go
type router struct {
// method : *node
roots map[string]*node
// method-pattern : handler
handlers map[string]HandlerFunc
}
```
```go
// Trie 节点类型
type node struct {
pattern string // 完整的 URL 模式,可以携带参数。存储在 #叶子
part string // 通过 "/" 分割出的每一个路径片段,存储在 #内部节点,用于索引到最终的 #叶子
children []*node // 当前节点的所有孩子
isParam bool // 当前的 part 是否是参数。参数有两种
// 1. 变量参数 :param
// 2. 路径参数(只能包含一个) *path
}
```
## 3、上下文 Context
上下文的出现主要是统一处理 http 请求函数 handler 的结构,http 服务的所有参数都集合到结构体 Context 中,这样所有handler 结构就可以统一定义为一个 HandlerFunc。
```go
type Context struct {
// origin objects
Writer http.ResponseWriter // 在 ServeHTTP 方法中将其初始化
Req *http.Request // 在 ServeHTTP 方法中将其初始化
// request info
Path string
Method string
Params map[string]string
// response info
StatusCode int
// middlewares
handlers []HandlerFunc
index int
}
```
```go
// HandlerFunc defines the request handler used by Gee
type HandlerFunc func(*Context)
```
## 4、中间件
中间件就是在处理服务端真正提供服务之前进行预处理,本质上也可以定义为一个 HandlerFunc,所以需要维护一个 handler 列表,将中间件存储在其中。那么当接收到一个 http 请求后,对应的 handler 添加到 handler 列表中,然后从头顺序执行整个 handler 列表,就达到了先执行中间件再真正处理请求的目的。
中间件列表的维护,由 Context 和 RouterGroup 完成。
## 5、panic 恢复
Go 语言提供了 `recover` 函数来从 panic 中恢复,避免当前 goroutine 直接结束。`recover` 只在 `defer` 任务中生效,所以添加一个中间件,进行错误恢复处理。
```go
func Recovery() HandlerFunc {
return func(c *Context) {
defer func() {
if err := recover(); err != nil {
message := fmt.Sprintf("%s", err)
log.Printf("%s\n\n", trace(message))
c.Fail(http.StatusInternalServerError, "Internal Server Error")
}
}()
c.Next()
}
}
```
