Thinkgo is a Golang Web framework that handler is middleware, supports intelligent parameter mapping and validation, and automates API documentation.
v1.0
Go Version ≥1.6
go get -u -v github.com/henrylee2cn/thinkgo
package main
import (
"github.com/henrylee2cn/thinkgo"
"time"
)
type Index struct {
Id int `param:"<in:path> <required> <desc:ID> <range: 0:10>"`
Title string `param:"<in:query> <nonzero>"`
Paragraph []string `param:"<in:query> <name:p> <len: 1:10> <regexp: ^[\\w]*$>"`
Cookie string `param:"<in:cookie> <name:thinkgoID>"`
// Picture *multipart.FileHeader `param:"<in:formData> <name:pic> <maxmb:30>"`
}
func (i *Index) Serve(ctx *thinkgo.Context) error {
if ctx.CookieParam("thinkgoID") == "" {
ctx.SetCookie("thinkgoID", time.Now().String())
}
return ctx.JSON(200, i)
}
func main() {
app := thinkgo.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
app.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 interface oriented development (func or struct)
- Middleware and handler exactly the same, they together constitute the handler chain
- Supports the use of struct (implemented handler) tag tags to define request parameter information and its validation information
- The API documentation (swagger2.0) is automatically built by the handler
- Supports HTTP/HTTP2, HTTPS (tls/letsencrypt), UNIX and other Server types
- Multi-instance is supported, and these configurations information are independent of each other
- Supports the same instance to monitor multi-server and multi-port
- Based on the high-performance
httprouter
to redevelope, and provides chain or tree style to register router - Powerful file router supports for custom file systems, framework has provided DirFS, RenderFS, MarkdownFS and so on
- Supports cross-platform color log system, and has two output interface (console and file)
- Supports session management
- Supports global gzip compression configuration
- Supports XSRF security filtering
- Supports near-LRU memory caching (mainly used for static file cache)
- Nice and easy to use configuration file, automatically write default values
Handler and middleware are the same, both implemente Handler interface!
- function type
// Page handler doesn't contains API doc description
func Page() thinkgo.HandlerFunc {
return func(ctx *thinkgo.Context) error {
return ctx.String(200, "thinkgo")
}
}
// Page2 handler contains API doc description
var Page2 = thinkgo.WrapDoc(Page(), "test page2 notes", "test")
- struct type
// Param binds and validates the request parameters by Tags
type Param struct {
Id int `param:"<in:path> <required> <desc:ID> <range: 0:10>"`
Title string `param:"<in:query>"`
}
// Serve implemente Handler interface
func (p *Param) Serve(ctx *thinkgo.Context) error {
return ctx.JSON(200,
thinkgo.Map{
"Struct Params": p,
"Additional Param": ctx.PathParam("additional"),
}, true)
}
// Doc implemente API Doc interface (optional)
func (p *Param) Doc() thinkgo.Doc {
return thinkgo.Doc{
// Add the API notes to the API doc
Note: "param desc",
// declare the response content format to the API doc
Return: thinkgo.JSONMsg{
Code: 1,
Info: "success",
},
// additional request parameter declarations to the API doc (optional)
Params: []thinkgo.ParamInfo{
{
Name: "additional",
In: "path",
Model: "a",
Desc: "defined by the `Doc()` method",
},
},
}
}
The filter function must be HandleFunc type!
func Root2Index(ctx *thinkgo.Context) error {
// Direct access to `/index` is not allowed
if ctx.Path() == "/index" {
ctx.Stop()
return nil
}
if ctx.Path() == "/" {
ctx.ModifyPath("/index")
}
return nil
}
- tree style
// New application object, params: name, version
var app1 = thinkgo.New("myapp1", "1.0")
// router
app1.Filter(Root2Index).
Route(
app1.NewNamedGET("test page", "/page", Page()),
app1.NewNamedGET("test page2", "/page2", Page2),
app1.NewGroup("home",
app1.NewNamedGET("test param", "/param", &Param{
// sets the default value in the API documentation for the request parameters (optional)
Id: 1,
Title: "test param",
}),
),
)
app1.Run()
- chain style
// New application object, params: name, version
var app2 = thinkgo.New("myapp2", "1.0")
// router
app2.Filter(Root2Index)
app2.NamedGET("test page", "/page", Page())
app2.NamedGET("test page2", "/page2", Page2)
app2.Group("home")
{
app2.NamedGET("test param", "/param", &Param{
// sets the default value in the API documentation for the request parameters(optional)
Id: 1,
Title: "test param",
})
}
app2.Run()
- Each instance of the application has a single configuration (file name format
config/{appname}[_{version}].ini
). Refer to the following:
net_types = normal|tls # List of network type: normal | tls | letsencrypt | unix
addrs = 0.0.0.0:80|0.0.0.0:443 # List of multiple listening addresses
tls_certfile = # TLS certificate file path
tls_keyfile = # TLS key file path
letsencrypt_file = # SSL free certificate path
unix_filemode = 438 # File permissions for UNIX Server (438 equivalent to 0666)
read_timeout = 0 # Maximum duration for reading the full request (including body)
write_timeout = 0 # Maximum duration for writing the full response (including body)
multipart_maxmemory_mb = 32 # Maximum size of memory that can be used when receiving uploaded files
[router] # Routing configuration section
redirect_trailing_slash = true # Automatic redirection (for example, `/foo/` -> `/foo`)
redirect_fixed_path = true # Tries to fix the current request path, if no handle is registered for it
handle_method_not_allowed = true # Returns 405 if the requested method does not exist, otherwise returns 404
handle_options = true # Automatic response OPTIONS request, you can set the default Handler in Thinkgo
[xsrf] # XSRF security section
enable = false # Whether enabled or not
key = thinkgoxsrf # Encryption key
expire = 3600 # Expire of XSRF token
[session] # Session section
enable = false # Whether enabled or not
provider = memory # Data storage
name = thinkgosessionID # The client stores the name of the cookie
gc_max_lifetime = 3600 # The interval between triggering the GC
provider_config = # According to the different engine settings different configuration information
cookie_lifetime = 0 # The default value is 0, which is the lifetime of the browser
auto_setcookie = true # Automatically set on the session cookie value, the general default true
domain = # The domain name that is allowed to access this cookie
enable_sid_in_header = false # Whether to write a session ID to the header
name_in_header = Thinkgosessionid # The name of the header when the session ID is written to the header
enable_sid_in_urlquery = false # Whether to write the session ID to the URL Query params
[apidoc] # API documentation section
enable = true # Whether enabled or not
path = /apidoc # The URL path
nolimit = false # If true, access is not restricted
real_ip = false # If true, means verifying the real IP of the visitor
whitelist = 192.*|202.122.246.170 # `whitelist=192.*|202.122.246.170` means: only IP addresses that are prefixed with `192 'or equal to` 202.122.246.170' are allowed
desc = # Description of the application
email = # Technician's Email
terms_url = # Terms of service
license = # The license used by the API
license_url = # The URL of the protocol content page
- Only one global configuration is applied (
config/__global__.ini
). Refer to the following:
[cache] # Cache section
enable = false # Whether enabled or not
size_mb = 32 # Max size by MB for file cache, the cache size will be set to 512KB at minimum.
expire = 60 # Maximum duration for caching
[gzip] # compression section
enable = false # Whether enabled or not
min_length = 20 # The minimum length of content to be compressed
compress_level = 1 # Non-file response Body's compression level is 0-9, but the files' always 9
methods = GET # List of HTTP methods to compress. If not set, only GET requests are compressed.
[log] # Log section
console_enable = true # Whether enabled or not console logger
console_level = debug # Console logger level
file_enable = true # Whether enabled or not file logger
file_level = debug # File logger level
async_len = 0 # The length of asynchronous buffer, 0 means synchronization
tag | key | required | value | desc |
---|---|---|---|---|
param | in | only one | path | (position of param) if required is unsetted, auto set it. e.g. url: "http://www.abc.com/a/{path}" |
param | in | only one | query | (position of param) e.g. url: "http://www.abc.com/a?b={query}" |
param | in | only one | formData | (position of param) e.g. "request body: a=123&b={formData}" |
param | in | only one | body | (position of param) request body can be any content |
param | in | only one | header | (position of param) request header info |
param | in | only one | cookie | (position of param) request cookie info, support: http.Cookie ,fasthttp.Cookie ,string ,[]byte |
param | name | no | (e.g.id ) |
specify request param`s name |
param | required | no | request param is required | |
param | desc | no | (e.g.id ) |
request param description |
param | len | no | (e.g.3:6 3 ) |
length range of param's value |
param | range | no | (e.g.0:10 ) |
numerical range of param's value |
param | nonzero | no | param`s value can not be zero | |
param | maxmb | no | (e.g.32 ) |
when request Content-Type is multipart/form-data, the max memory for body.(multi-param, whichever is greater) |
param | regexp | no | (e.g.^\\w+$ ) |
verify the value of the param with a regular expression(param value can not be null) |
param | err | no | (e.g.incorrect password format ) |
the custom error for binding or validating |
NOTES:
- the binding object must be a struct pointer
- in addition to
*multipart.FileHeader
, the binding struct's field can not be a pointer regexp
orparam
tag is only usable whenparam:"type(xxx)"
is exist- if the
param
tag is not exist, anonymous field will be parsed - when the param's position(
in
) isformData
and the field's type ismultipart.FileHeader
, the param receives file uploaded - if param's position(
in
) iscookie
, field's type must behttp.Cookie
- param tags
in(formData)
andin(body)
can not exist at the same time - there should not be more than one
in(body)
param tag
base | slice | special |
---|---|---|
string | []string | [][]byte |
byte | []byte | [][]uint8 |
uint8 | []uint8 | *multipart.FileHeader (only for formData param) |
bool | []bool | []*multipart.FileHeader (only for formData param) |
int | []int | http.Cookie (only for net/http 's cookie param) |
int8 | []int8 | fasthttp.Cookie (only for fasthttp 's cookie param) |
int16 | []int16 | struct (struct type only for body param or as an anonymous field to extend params) |
int32 | []int32 | |
int64 | []int64 | |
uint8 | []uint8 | |
uint16 | []uint16 | |
uint32 | []uint32 | |
uint64 | []uint64 | |
float32 | []float32 | |
float64 | []float64 |
- barcode:
github.com/henrylee2cn/thinkgo/ext/barcode
- Bit unit conversion:
github.com/henrylee2cn/thinkgo/ext/bitconv
- gorm(DB ORM):
github.com/henrylee2cn/thinkgo/ext/db/gorm
- sqlx(DB ext):
github.com/henrylee2cn/thinkgo/ext/db/sqlx
- xorm(DB ORM):
github.com/henrylee2cn/thinkgo/ext/db/xorm
- directSQL(Configured SQL engine):
github.com/henrylee2cn/thinkgo/ext/db/directsql
- One-time Password:
github.com/henrylee2cn/thinkgo/ext/otp
- UUID:
github.com/henrylee2cn/thinkgo/ext/uuid
- Websocket:
github.com/henrylee2cn/thinkgo/ext/websocket
- ini:
github.com/henrylee2cn/thinkgo/ini
- cron:
github.com/henrylee2cn/thinkgo/ext/cron
- task:
github.com/henrylee2cn/thinkgo/ext/task
- http client:
github.com/henrylee2cn/thinkgo/ext/surfer
Thinkgo is under Apache v2 License. See the LICENSE file for the full license text.