Faygo简洁优雅的Go Web框架
Faygo(原名Thinkgo)  
 
 
 
概述
Faygo以全新的架构实现,它面向Handler接口开发,是支持智能参数映射与校验、支持自动化API文档的Go语言web框架。
最新版本
版本号
v1.0
安装要求
Go Version ≥1.8
快速使用
方式一 源码下载
go get -u -v github.com/henrylee2cn/faygo
方式二 部署工具 (Go to fay)
go get -u -v github.com/henrylee2cn/fay
fay command [arguments] The commands are: new 创建、编译和运行(监控文件变化)一个新的faygo项目 run 编译和运行(监控文件变化)任意一个已存在的golang项目 fay new appname [apptpl] appname 指定新faygo项目的创建目录 apptpl 指定一个faygo项目模板(可选) fay run [appname] appname 指定待运行的golang项目路径(可选)
框架特性
面向Handler接口开发(func or struct),中间件与操作完全等同可任意拼接路由操作链
支持用struct Handler在Tag标签定义请求参数信息及其校验信息
支持自动构建API文档(swagger2.0)
支持多种网络类型:
HTTP
HTTPS/HTTP2(TLS)
HTTPS/HTTP2(Let's Encrypt TLS)
HTTPS/HTTP2(Let's Encrypt TLS on UNIX socket)
HTTP(UNIX socket)
HTTPS/HTTP2(TLS on UNIX socket)
支持多实例运行,且配置信息相互独立
支持同一实例监听多网络类型、多端口
基于高性能路由httprouter进行二次开发,支持链式与树形两种路由信息注册风格
强大的文件路由功能,支持自定义文件系统,框架提供快捷的DirFS、RenderFS、MarkdownFS等
提供近似LRU的文件缓存功能
跨平台的彩色日志系统,且同时支持console和file两种输出形式(可以同时使用)
提供Session管理功能
支持Gzip全局配置
提供XSRF跨站请求伪造安全过滤
简单整洁的配置文件,且自动补填默认值方便设置
支持平滑关闭与重启
struct Handler的多用途合一
简单示例
package main
import (
    // "mime/multipart"
    "time"
    "github.com/henrylee2cn/faygo"
)
type Index struct {
    Id        int      `param:""`
    Title     string   `param:""`
    Paragraph []string `param:""`
    Cookie    string   `param:""`
    // Picture         *multipart.FileHeader `param:""`
}
func (i *Index) Serve(ctx *faygo.Context) error {
    if ctx.CookieParam("faygoID") == "" {
        ctx.SetCookie("faygoID", time.Now().String())
    }
    return ctx.JSON(200, i)
}
func main() {
    app := faygo.New("myapp", "0.1")
    // Register the route in a chain style
    app.GET("/index/:id", new(Index))
    // Register the route in a tree style
    // app.Route(
    //     app.NewGET("/index/:id", new(Index)),
    // )
    // Start the service
    faygo.Run()
}
/*
http GET:
    http://localhost:8080/index/1?title=test&p=abc&p=xyz
response:
    {
        "Id": 1,
        "Title": "test",
        "Paragraph": [
            "abc",
            "xyz"
        ],
        "Cookie": "2016-11-13 01:14:40.9038005 +0800 CST"
    }
*/ 
 
操作和中间件
操作和中间件是相同的,都是实现了Handler接口!
函数类型
// 不含API文档描述
func Page() faygo.HandlerFunc {
    return func(ctx *faygo.Context) error {
        return ctx.String(200, "faygo")
    }
}
// 含API文档描述
var Page2 = faygo.WrapDoc(Page(), "测试页2的注意事项", "文本") 
结构体类型
// Param操作通过Tag绑定并验证请求参数
type Param struct {
    Id    int    `param:""`
    Title string `param:""`
}
// Serve实现Handler接口
func (p *Param) Serve(ctx *faygo.Context) error {
    return ctx.JSON(200,
        faygo.Map{
            "Struct Params":    p,
            "Additional Param": ctx.PathParam("additional"),
        }, true)
}
// Doc实现API文档接口(可选)
func (p *Param) Doc() faygo.Doc {
    return faygo.Doc{
        // 向API文档声明接口注意事项
        Note: "param desc",
        // 向API文档声明响应内容格式
        Return: faygo.JSONMsg{
            Code: 1,
            Info: "success",
        },
        // 向API文档增加额外的请求参数声明(可选)
        Params: []faygo.ParamInfo{
            {
                Name:  "additional",
                In:    "path",
                Model: "a",
                Desc:  "defined by the `Doc()` method",
            },
        },
    }
} 
过滤函数
过滤函数必须是HandlerFunc类型!
func Root2Index(ctx *faygo.Context) error {
    // 不允许直接访问`/index`
    if ctx.Path() == "/index" {
        ctx.Stop()
        return nil
    }
    if ctx.Path() == "/" {
        ctx.ModifyPath("/index")
    }
    return nil
} 
路由注册
树状
// 新建应用实例,参数:名称、版本
var app1 = faygo.New("myapp1", "1.0")
// 路由
app1.Filter(Root2Index).
    Route(
        app1.NewNamedGET("测试页1", "/page", Page()),
        app1.NewNamedGET("测试页2", "/page2", Page2),
        app1.NewGroup("home",
            app1.NewNamedGET("test param", "/param", &Param{
                // 为绑定的参数设定API文档中缺省值(可选)
                Id:    1,
                Title: "test param",
            }),
        ),
    ) 
链状
// 新建应用实例,参数:名称、版本
var app2 = faygo.New("myapp2", "1.0")
// 路由
app2.Filter(Root2Index)
app2.NamedGET("test page", "/page", Page())
app2.NamedGET("test page2", "/page2", Page2)
app2.Group("home")
{
    app2.NamedGET("test param", "/param", &Param{
        // 为绑定的参数设定API文档中缺省值(可选)
        Id:    1,
        Title: "test param",
    })
} 
平滑关闭与重启
平滑关闭
kill [pid]
平滑重启
kill -USR2 [pid]
配置文件说明
应用的各实例均有单独一份配置,其文件名格式
config/{appname}[_{version}].ini,配置详情:
net_types = http|https # 多种网络类型列表,支持 http | https | unix_http | unix_https | letsencrypt | unix_letsencrypt addrs = 0.0.0.0:80|0.0.0.0:443 # 多个监听地址列表 tls_certfile = # TLS证书文件路径 tls_keyfile = # TLS密钥文件路径 letsencrypt_dir = # Let's Encrypt TLS证书缓存目录 unix_filemode = 438 # UNIX listener的文件权限(438即0666) read_timeout = 0 # 读取请求数据超时 write_timeout = 0 # 写入响应数据超时 multipart_maxmemory_mb = 32 # 接收上传文件时允许使用的最大内存 [router] # 路由配置区 redirect_trailing_slash = true # 当前请求的URL含`/`后缀如`/foo/`且相应路由不存在时,如存在`/foo`,则自动跳转至`/foo` redirect_fixed_path = true # 自动修复URL,如`/FOO` `/..//Foo`均被跳转至`/foo`(依赖redirect_trailing_slash=true) handle_method_not_allowed = true # 若开启,当前请求方法不存在时返回405,否则返回404 handle_options = true # 若开启,自动应答OPTIONS类请求,可在Faygo中设置默认Handler [xsrf] # XSRF跨站请求伪造过滤配置区 enable = false # 是否开启 key = faygoxsrf # 加密key expire = 3600 # xsrf防伪token有效时长 [session] # Session配置区(详情参考beego session模块) enable = false # 是否开启 provider = memory # 数据存储方式 name = faygosessionID # 客户端存储cookie的名字 gc_max_lifetime = 3600 # 触发GC的时间 provider_config = # 配置信息,根据不同的引擎设置不同的配置信息 cookie_lifetime = 0 # 客户端存储的cookie的时间,默认值是0,即浏览器生命周期 auto_setcookie = true # 是否自动设置关于session的cookie值,一般默认true domain = # 可以访问此cookie的域名 enable_sid_in_header = false # 是否将session ID写入Header name_in_header = Faygosessionid # 将session ID写入Header时的头名称 enable_sid_in_urlquery = false # 是否将session ID写入url的query部分 [apidoc] # API文档 enable = true # 是否启用 path = /apidoc # 访问的URL路径 nolimit = false # 是否不限访问IP real_ip = false # 使用真实客户端的IP进行过滤 whitelist = 192.*|202.122.246.170 # 表示允许带有`192.`前缀或等于`202.122.246.170`的IP访问 desc = # 项目描述 email = # 联系人邮箱 terms_url = # 服务条款URL license = # 协议类型 license_url = # 协议内容URL
应用只有一份全局配置,文件名为
config/__global__.ini,配置详情:
[cache] # 文件内存缓存配置区 enable = false # 是否开启 size_mb = 32 # 允许缓存使用的最大内存(单位MB),为0时系统自动设置为512KB expire = 60 # 缓存最大时长 [gzip] # gzip压缩配置区 enable = false # 是否开启 min_length = 20 # 进行压缩的最小内容长度 compress_level = 1 # 非文件类响应Body的压缩水平(0-9),注意文件压缩始终为最优压缩比(9) methods = GET # 允许压缩的请求方法,为空时默认为GET [log] # 日志配置区 console_enable = true # 是否启用控制台日志 console_level = debug # 控制台日志打印水平 file_enable = true # 是否启用文件日志 file_level = debug # 文件日志打印水平 async_len = 0 # 0表示同步打印,大于0表示异步缓存长度
Handler结构体字段标签说明
| tag | key | required | value | desc | 
|---|---|---|---|---|
| param | in | 有且只有一个 | path | (参数位置)为空时自动补全,如URL http://www.abc.com/a/{path}  |  
  
| param | in | 有且只有一个 | query | (参数位置)如URL http://www.abc.com/a?b={query}  |  
  
| param | in | 有且只有一个 | formData | (参数位置)请求表单,如 a=123&b={formData}  |  
  
| param | in | 有且只有一个 | body | (参数位置)请求Body | 
| param | in | 有且只有一个 | header | (参数位置)请求头 | 
| param | in | 有且只有一个 | cookie | (参数位置)请求cookie,支持:*http.Cookie、http.Cookie、string、[]byte等 |  
  
| param | name | 否 | (如id) |  
   自定义参数名 | 
| param | required | 否 | required | 参数是否必须 | 
| param | desc | 否 | (如id) |  
   参数描述 | 
| param | len | 否 | (如3:63) |  
   字符串类型参数的长度范围 | 
| param | range | 否 | (如0:10) |  
   数字类型参数的数值范围 | 
| param | nonzero | 否 | nonzero | 是否能为零值 | 
| param | maxmb | 否 | (如32) |  
   当前Content-Type为multipart/form-data时,允许使用的最大内存,当设置了多个时使用较大值 |  
  
| param | regexp | 否 | (如^\w+$) |  
   使用正则验证参数值 | 
| param | err | 否 | (如密码格式错误) |  
   自定义参数绑定或验证的错误信息 | 
NOTES:
绑定的对象必须为结构体指针类型
除
*multipart.FileHeader外,绑定的结构体字段类型不能为指针类型只有在
param:"type(xxx)"存在时,regexp和param标签才有效若
param标签不存在,将尝试解析匿名字段当结构体标签
in为formData且字段类型为*multipart.FileHeader、multipart.FileHeader、[]*multipart.FileHeader或[]multipart.FileHeader时,该参数接收文件类型当结构体标签
in为cookie,字段类型必须为*http.Cookie或http.Cookie标签
in(formData)和in(body)不能同时出现在同一结构体不能存在多个
in(body)标签
Handler结构体字段类型说明
| base | slice | special | 
|---|---|---|
| string | []string | [][]byte | 
| byte | []byte | [][]uint8 | 
| uint8 | []uint8 | *multipart.FileHeader (仅formData参数使用) |  
  
| bool | []bool | []*multipart.FileHeader (仅formData参数使用) |  
  
| int | []int | *http.Cookie (仅net/http下的cookie参数使用) |  
  
| int8 | []int8 | http.Cookie (仅net/http下的cookie参数使用) |  
  
| int16 | []int16 | struct (body参数使用或用于匿名字段扩展参数) |  
  
| int32 | []int32 | |
| int64 | []int64 | |
| uint8 | []uint8 | |
| uint16 | []uint16 | |
| uint32 | []uint32 | |
| uint64 | []uint64 | |
| float32 | []float32 | |
| float64 | []float64 | 
扩展包
| 扩展包 | 导入路径 | 
|---|---|
| 各种条码 | github.com/henrylee2cn/faygo/ext/barcode |  
  
| 比特单位 | github.com/henrylee2cn/faygo/ext/bitconv |  
  
| gorm数据库引擎 | github.com/henrylee2cn/faygo/ext/db/gorm |  
  
| sqlx数据库引擎 | github.com/henrylee2cn/faygo/ext/db/sqlx |  
  
| xorm数据库引擎 | github.com/henrylee2cn/faygo/ext/db/xorm |  
  
| directSQL(配置化SQL引擎) | github.com/henrylee2cn/faygo/ext/db/directsql |  
  
| 口令算法 | github.com/henrylee2cn/faygo/ext/otp |  
  
| UUID | github.com/henrylee2cn/faygo/ext/uuid |  
  
| Websocket | github.com/henrylee2cn/faygo/ext/websocket |  
  
| ini配置 | github.com/henrylee2cn/faygo/ini |  
  
| 定时器 | github.com/henrylee2cn/faygo/ext/cron |  
  
| 任务工具 | github.com/henrylee2cn/faygo/ext/task |  
  
| HTTP客户端 | github.com/henrylee2cn/faygo/ext/surfer |  
  
开源协议
Faygo 项目采用商业应用友好的 Apache2.0 协议发布。
