README
¶
xmux
Based on native net HTTP is extremely simple and flexible, focusing on the routing of front and back-end separation projects
Function is up to you
required
go version >= 1.18
Navigation
- install
- quick start
- Using GET, POST, PUT, PATCH, DELETE and OPTIONS
- routing group
- prefix
- auto detect duplicates
- context value transfer
- auto ignore slash
- module
- hook function
- set request header
- data binding
- url regular match
- websocket
- permission control module
- cache module
- pprof group
- swagger group
- connection instance
Install
go get github.com/hyahm/xmux
Quick Start
package main
import (
"net/http"
"github.com/hyahm/xmux"
)
func main() {
router := xmux.NewRouter()
router.Get("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("<h1>hello world!<h1>"))
})
router.Run()
}
open http://localhost:8080 in brower you can see hello world!
Multiple request method
package main
import (
"net/http"
"github.com/hyahm/xmux"
)
func main() {
router := xmux.NewRouter()
//Just for example, the following writing method is not recommended, but route.Reqeust("/",nil, "POST", "GET")
router.Get("/", nil) // get request
router.Post("/", nil) // post request
router.Request("/getpost", nil, "POST", "GET") // both get and post requests are supported
router.Any("/any", nil) // supports all requests except options
router.Run()
}
Route Group
aritclegroup.go
func hello(w http.ResponseWriter, r *http.Request) {
fmt.Println(xmux.Var(r)["id"])
w.Write([]byte("hello world!!!!"))
return
}
var Article *xmux.RouteGroup
func init() {
Article = xmux.NewRouteGroup()
Article.Get("/{int:id}", hello)
}
main.go
func main() {
router := xmux.NewRouter()
router.AddGroup(aritclegroup.Article)
}
prefix
// notice: DelPrefix and Prefix are valid only by routegroup
func main() {
router := xmux.NewRouter().Prefix("test")
router.Get("/bbb", c) // /test/bbb
router.Get("/ccc", c).DelPrefix("test") // /test/bbb
g := xmux.NewRouteGroup()
g.Get("/aaa", noCache).DelModule(setKey) // /test/bbb
g.Get("/no/cache1", noCache1).DelModule(setKey).DelPrefix("test") // /no/cache1
router.AddGroup(g)
router.Run()
}
Automatically detect duplicates
Write a lot of routes. I don't know if there are duplicates
An error will be reported when running the above, as follows
func main() {
router := xmux.NewRouter()
router.Get("/get",show) //
router.Get("/get",nil) //
router.Run()
}
2019/11/29 21:51:11 GET pattern duplicate for /get
ignore url path slash
Remove any unnecessary slashes, for example
/asdf/sadf//asdfsadf/asdfsdaf////as/// -> /asdf/sadf/asdfsadf/asdfsdaf/as
func main() {
router := xmux.NewRouter()
router.IgnoreSlash = true
router.Get("/get",show)
router.Get("/get/",show)
router.Run()
}
if
router.IgnoreSlash = false
Then an error will be reported when running the above, and / get / will be changed to / get as follows
2019/11/29 21:51:11 pattern duplicate for /get
Three Global handle
// This is the global options request processing. The front-end pre request is exempted. You have to write a pre request processing every time. By default, it will return OK, which can also be customized
HandleOptions: handleoptions(),
//404 is returned by default. You can also customize it
HandleNotFound: handleNotFound(),
// /favicon
HanleFavicon: methodNotAllowed(),
// The default method called is as follows. No route was found
func handleNotFound(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Access-Control-Allow-Origin", "*")
// Note: which is to pass the status code to exit and print the status code
GetInstance(r).StatusCode = http.StatusNotFound
w.WriteHeader(http.StatusNotFound)
}
Module which replaces the middleware functions of other frameworks and is more flexible and simple
- Priority module
Global routing > group routing > private routing
if there is a high priority, execute first.
If you don't want to use it, you can delete it separately at the route point or route group you don't want to use delmodule
Note: Meaning of module return value: true: directly return to the client without subsequent processing. False means continue to execute downward
func home(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("hello world home"))
return
}
func hf(w http.ResponseWriter, r *http.Request) bool {
fmt.Println("44444444444444444444444444")
return true
}
func hf1(w http.ResponseWriter, r *http.Request) bool {
fmt.Println("66666")
return false
}
func main() {
router := xmux.NewRouter().AddModule(hf).SetHeader("name", "cander")
router.Get("/home/{test}",home).AddModule(hf1) // Module sequence hf -> hf1 -> home
router.Get("/test/{test}",home).DelModule(hf) // home
router.Run()
}
Context value transfer
- Custom values can only be assigned from the module
// set key value
xmux.GetInstance(r).Set("key", "value")
// get value
xmux.GetInstance(r).Get("key")
Hook
- NotFoundRequiredField : Processing tick for failed verification of required fields
- UnmarshalError : Built in Unmarshal error hook
- Exit (start time.Time, w http.ResponseWriter, r *http.Request) : handle exit
- Enter( w http.ResponseWriter, r *http.Request) bool : handle enter
func exit(start time.Time, w http.ResponseWriter, r *http.Request) {
// Any valid request will end up here
fmt.Println(time.Since(start).Seconds(), r.URL.Path)
}
func enter( w http.ResponseWriter, r *http.Request) bool {
// Any request will coming,You can filter IP domain names and other security or debugging operations
fmt.Println(time.Since(start).Seconds(), r.URL.Path)
}
router := xmux.NewRouter()
router.Enter = enter
router.Exit = exit
Set Header
Cross origin is mainly about adding request headers. Other frameworks are generally set up with the help of middleware
However, this route greatly simplifies the cross origin configuration with the help of the above request header settings
Priority
Private route > group route > global route (if there is one with high priority, the one with low priority will be overwritten)
// For the example of cross origin processing, after setting the following request header, all routes will be attached to the request header,
// If some routes have separate request headers, they can be set separately
func main() {
router := xmux.NewRouter()
router.IgnoreSlash = true
// The main solution is cross origin. Because it is a global request header, all the routes added later support cross origin
router.SetHeader("Access-Control-Allow-Origin", "*")
// Allowed request headers
router.SetHeader("Access-Control-Allow-Headers", "Content-Type,Access-Token,X-Token,Origin,smail,authorization")
router.Get("/", index)
router.Run()
}
Data binding (the data after binding analysis takes effect before the module)
-Bindjason: bound is a JSON
-Bindxml: binding is an XML
-Bindform: a form is bound, can not bind file , you need get file from from r.FormFile()
-Bind: custom processing binding (processed by module)
Validation field must required
type User struct {
Username string "json:"username,required"
}
-
router.PrintRequestStr: Print the content of the acceptance request body
-
xmux.MaxPrintLength: If the size of the printed form exceeds the specified size, it will not be printed (default 2K)
func JsonToStruct(w http.ResponseWriter, r *http.Request) bool {
// If any error message is reported, return true directly, which means that the handle has been executed directly and does not continue to go back
if goconfig.ReadBool("debug", false) {
b, err := ioutil.ReadAll(r.Body)
if err != nil {
return true
}
err = json.Unmarshal(b, xmux.GetInstance(r).Data)
if err != nil {
return true
}
} else {
err := json.NewDecoder(r.Body).Decode(xmux.GetInstance(r).Data)
if err != nil {
return true
}
}
return false
}
type DataName struct{}
type DataStd struct{}
type DataFoo struct{}
func AddName(w http.ResponseWriter, r *http.Request) {
df := xmux.GetInstance(r).Data.(*DataName)
fmt.Printf("%#v", df)
}
func AddStd(w http.ResponseWriter, r *http.Request) {
df := xmux.GetInstance(r).Data.(*DataStd)
fmt.Printf("%#v", df)
}
func AddFoo(w http.ResponseWriter, r *http.Request) {
df := xmux.GetInstance(r).Data.(*DataFoo)
fmt.Printf("%#v", df)
}
func main() {
router := xmux.NewRouter()
router.Post("/important/name", AddName).Bind(&DataName{}).AddModule(JsonToStruct)
router.Post("/important/std", AddStd).Bind(&DataStd{}).AddModule(JsonToStruct)
router.Post("/important/foo", AddFoo).Bind(&DataFoo{}).AddModule(JsonToStruct)
// You can also directly use the built-in
// If it is in JSON format, you can directly bind JSON. The effect is similar to that above
router.Post("/important/foo/by/json", AddFoo).BindJson(&DataFoo{})
router.Run()
}
- Binding return value
data := &Response{
Code: 200,
}
router := xmux.NewRouter().BindResponse(data)
Pass Bind response (nil) to set and cancel a route using global binding
Matching route
The following five types are supported
Word matches only numbers and letter underscores (default)
-
string matches all characters without /
-
int match integer
-
all: match all, including/
-
re: Custom regular
example:
- /aaa/{name} is the same as the following one, omitting the type, and the default is word
- /aaa/{string: name} This is the same as above. The string type
- /aaa/{int: name} matches the int type
- /aaa/adf{re:([a-z]{1,4})sf([0-9]{0,10})sd: name, age} This is a paragraph that matches two parameters name, age,
Curly braces indicate a matching rule, in which two colons are divided into three parts
The first one: re indicates the use of custom rules. Only re has two colon divisions,
The second: regular expression, which cannot appear: the parameters to be extracted are enclosed by (),
Third: parameter name. The number of pairs () in the front and the number of parameters to be matched in the back are separated by commas
For example: /aaa/adfaasf16sd
This is a match. Name: aa age: 16
xmux.Var(r)["name"]
websocket
Here is a complete example
package main
import (
"fmt"
"log"
"net/http"
"sync"
"time"
"github.com/hyahm/xmux"
)
type client struct {
msg string
c *xmux.BaseWs
}
var msgchan chan client
var wsmu sync.RWMutex
var ps map[*xmux.BaseWs]byte
func sendMsg() {
for {
c := <-msgchan
for p := range ps {
if c.c == p {
// Don't send it to yourself
continue
}
fmt.Println(c.msg)
//The length of the sent MSG cannot exceed 1 < < 31, otherwise the content will be lost and subcontracting is recommended
p.SendMessage([]byte(c.msg), ps[p])
}
}
}
func ws(w http.ResponseWriter, r *http.Request) {
p, err := xmux.UpgradeWebSocket(w, r)
if err != nil {
w.Write([]byte(err.Error()))
return
}
p.SendMessage([]byte("hello"), xmux.TypeMsg)
wsmu.Lock()
ps[p] = xmux.TypeMsg
wsmu.Unlock()
tt := time.NewTicker(time.Second * 2)
go func() {
for {
<-tt.C
if err := p.SendMessage([]byte(time.Now().String()), xmux.TypeMsg); err != nil {
break
}
}
}()
for {
if p.Conn == nil {
return
}
// Package
msgType, msg, err := p.ReadMessage()
if err != nil {
fmt.Println(err.Error())
// Disconnected
wsmu.Lock()
delete(ps, p)
wsmu.Unlock()
break
}
ps[p] = msgType
c := client{
msg: msg,
c: p,
}
msgchan <- c
}
}
func main() {
router := xmux.NewRouter()
wsmu = sync.RWMutex{}
msgchan = make(chan client, 100)
ps = make(map[*xmux.BaseWs]byte)
router.SetHeader("Access-Control-Allow-Origin", "*")
router.Get("/{int:uid}", ws)
go sendMsg()
if err := http.ListenAndServe(":8080", router); err != nil {
log.Fatal(err)
}
}
<!DOCTYPE html>
<html>
<head>
<title>go websocket</title>
<meta charset="utf-8" />
</head>
<body>
<script type="text/javascript">
var wsUri = "ws://localhost:8080/3";
var output;
var connect = false;
function init() {
output = document.getElementById("output");
testWebSocket();
}
function testWebSocket() {
websocket = new WebSocket(wsUri, WebSocket.binaryType);
websocket.onopen = function(evt) {
onOpen(evt)
};
websocket.onclose = function(evt) {
onClose(evt)
};
websocket.onmessage = function(evt) {
onMessage(evt)
};
websocket.onerror = function(evt) {
onError(evt)
};
}
function onOpen(evt) {
writeToScreen("CONNECTED");
connect = true
// doSend("WebSocket rocks");
}
function onClose(evt) {
connect = false
writeToScreen("DISCONNECTED");
}
function onMessage(evt) {
msg = String.fromCharCode(evt.data)
console.log(msg)
writeToScreen('<span style="color: blue;">RESPONSE: ' + evt.data + '</span>');
// websocket.close();
}
function onError(evt) {
writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
}
function doSend(message) {
if (!connect) {
console.log("connect error")
return
}
writeToScreen("SENT: " + message);
websocket.send(message);
}
function writeToScreen(message) {
var pre = document.createElement("p");
pre.style.wordWrap = "break-word";
pre.innerHTML = message;
output.appendChild(pre);
}
window.addEventListener("load", init, false);
function sendBtnClick() {
var msg = document.getElementById("input").value;
doSend(msg);
document.getElementById("input").value = '';
}
function closeBtnClick() {
websocket.close();
}
</script>
<h2>WebSocket Test</h2>
<input type="text" id="input"></input>
<button onclick="sendBtnClick()">send</button>
<button onclick="closeBtnClick()">close</button>
<div id="output"></div>
</body>
</html>
swagger
All applicable functions start with swagger, and the data structure is the same as [swagger]( https://swagger.io/docs/specification/2-0/basic-structure/ )The same as that of the document, please refer to the swagger data structure
package main
import "github.com/hyahm/xmux"
func main() {
router := xmux.NewRouter()
router.Get("/", nil)
router.AddGroup(router.ShowSwagger("/docs", "localhost:8080"))
router.Run()
}
Gets the current number of connections
xmux.GetConnents()
Graceful stop
xmux.StopService()
Built in routing cache
xmux.NewRouter(cache ...uint64) // Cache is a built-in LRU path cache. The default cache 10000 is not written. Please modify it yourself according to the situation
Permission control
- Page permissions
The idea comes from the roles of the front-end framework routing component meta Judging by a given array
Take the Vue backend project with the largest number of front-end stars in GitHub as an example https://github.com/PanJiaChen/vue-element-admin
src/router/index.js Page permission routing inside
{
path: '/permission',
component: Layout,
redirect: '/permission/page',
alwaysShow: true, // will always show the root menu
name: 'Permission',
meta: {
title: 'Permission',
icon: 'lock',
roles: ['admin', 'editor'] // you can set roles in root nav
},
children: [
{
path: 'page',
component: () => import('@/views/permission/page'),
name: 'PagePermission',
meta: {
title: 'Page Permission',
roles: ['admin'] // or you can only set roles in sub nav
}
},
{
path: 'directive',
component: () => import('@/views/permission/directive'),
name: 'DirectivePermission',
meta: {
title: 'Directive Permission'
// if do not set roles, means: this page does not required permission
}
},
{
path: 'role',
component: () => import('@/views/permission/role'),
name: 'RolePermission',
meta: {
title: 'Role Permission',
roles: ['admin']
}
}
]
},
xmux Corresponding writing
func AddName(w http.ResponseWriter, r *http.Request) {
fmt.Printf("%v", "AddName")
}
func AddStd(w http.ResponseWriter, r *http.Request) {
fmt.Printf("%v", "AddStd")
}
func AddFoo(w http.ResponseWriter, r *http.Request) {
fmt.Printf("%v", "AddFoo")
}
func role(w http.ResponseWriter, r *http.Request) {
fmt.Printf("%v", "role")
}
func DefaultPermissionTemplate(w http.ResponseWriter, r *http.Request) (post bool) {
// Get the permission of the corresponding URI, which is set by addpagekeys and delpagekeys
pages := xmux.GetInstance(r).GetPageKeys()
// If the length is 0, it means that anyone can access it
if len(pages) == 0 {
return false
}
// Get the corresponding role of the user and judge that it is all in
roles := []string{"admin"} //Obtain the user's permission from the database or redis
for _, role := range roles {
if _, ok := pages[role]; ok {
//What matches here is the existence of this permission. Continue to follow for so long
return false
}
}
// no permission
w.Write([]byte("no permission"))
return true
}
func
func main() {
router := xmux.NewRouter()
router.AddModule(DefaultPermissionTemplate).AddPageKeys("admin", "editor")
router.Post("/permission", AddName)
router.Post("/permission/page", AddStd).DelPageKeys("editor")
router.Post("/permission/directive", AddFoo)
// You can also directly use the built-in
router.Post("/permission/role", role).DelPageKeys("editor")
router.Run()
}
- More detailed addition, deletion, modification and query authority, but not limited to addition, deletion, modification and query
I think the simplest thing is to judge according to the function name of handle,
You can refer to the permission template of xmux.DefaultPermissionTemplate
Cache
-
Initialize cache cache.InitResponseCache(Cacher) Cacher is a interface
type Cacher interface { Add(string, []byte) (string, bool) Get(string) ([]byte, bool) }
if you want use lru or lfu or alfu cache. you can use github.com/hyahm/gocache
-
The module that needs to set the cached key (the core module does not need to be cached if it is not set)
-
To set the value of cachekey cache.GetInstance(r).Set(xmux.CacheKey, fmt.Sprintf("%s_%v", r.URL.Path, uid))
-
The cache module needs to be mounted
example of not bind return data
package main
import (
"fmt"
"net/http"
"time"
"github.com/hyahm/gocache"
"github.com/hyahm/xmux"
)
func c(w http.ResponseWriter, r *http.Request) {
fmt.Println("comming c")
now := time.Now().String()
xmux.GetInstance(r).Response.(*Response).Data = now
}
func noCache(w http.ResponseWriter, r *http.Request) {
fmt.Println("update c")
xmux.NeedUpdate("/aaa")
}
func noCache1(w http.ResponseWriter, r *http.Request) {
fmt.Println("comming noCache1")
now := time.Now().String()
xmux.GetInstance(r).Response.(*Response).Data = now
}
func setKey(w http.ResponseWriter, r *http.Request) bool {
xmux.GetInstance(r).Set(xmux.CacheKey, r.URL.Path)
fmt.Print(r.URL.Path + " is cached")
return false
}
type Response struct {
Code int `json:"code"`
Data interface{} `json:"data"`
}
func main() {
r := &Response{
Code: 0,
}
cth := gocache.NewCache[string, []byte](100, gocache.LFU)
xmux.InitResponseCache(cth)
// If not bind response use xmux.DefaultCacheTemplateCacheWithoutResponse instead of xmux.DefaultCacheTemplateCacheWithResponse
router := xmux.NewRouter().AddModule(setKey, xmux.DefaultCacheTemplateCacheWithResponse)
router.BindResponse(r)
router.Get("/aaa", c)
router.Get("/update/aaa", noCache).DelModule(setKey)
router.Get("/no/cache1", noCache1).DelModule(setKey)
router.Run()
}
Client file download (official built-in method MP4 file as an example)
func PlayVideo(w http.ResponseWriter, r *http.Request) {
filename := xmux.Var(r)["filename"]
f, err := os.Open(<mp4file>)
if err != nil {
w.WriteHeader(404)
return
}
defer f.Close()
w.Header().Set("Content-Type", "video/mp4")
w.Header().Set("X-Download-Options", "noopen")
http.ServeContent(w, r, filename, time.Now(), f)
Client file upload (official built-in method)
func UploadFile(w http.ResponseWriter, r *http.Request) {
// The maximum size of the official default uploaded file is 32m. You can set a new size through this method
r.ParseMultipartForm(100 << 20) // 100M
// read file
file, header, err := r.FormFile("file")
if err != nil {
return
}
f, err := os.OpenFile(<storefilepath>, os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return
}
defer f.Close()
_, err := io.Copy(f, file)
if err != nil {
return
}
}
performance analysis Pprof
func main() {
router := xmux.NewRouter()
router.Post("/", nil)
router.AddGroup(xmux.Pprof())
router.Run()
}
open http://localhost:8080/debug/pprof can see pprof page
View the detailed middleware module and other information of a Handel
//View the details of a specified route
router. DebugAssignRoute("/user/info")
//Check the fixed URI of a regular fire matching route to obtain the details of a route
router. DebugIncludeTpl("")
//Show all, not recommended,
router. DebugRoute()
router. DebugTpl()
out
2022/01/22 17:16:11 url: /user/info, method: GET, header: map[], module: xmux.funcOrder{"github.com/hyahm/xmux.DefaultPermissionTemplate"}, midware: "" , pages: map[string]struct {}{}
Connection Instance
xmux.GetInstance(r).Body // Bind request data, This data is only available when the binding value is
xmux.GetInstance(r).CacheKey // cache key
xmux.GetInstance(r).Data // Value parsed by data binding
xmux.GetInstance(r).Response // Response data
xmux.GetInstance(r).StatusCode // status_code
xmux.GetInstance(r).Get() // Get context value
xmux.GetInstance(r).Set() // Set context value
xmux.GetInstance(r).GetConnectId() // Get current connect id
xmux.GetInstance(r).GetFuncName() // It is related to the authority of adding, deleting, modifying and querying
xmux.GetInstance(r).GetPageKeys() // Related to page permissions
Life cycle flow chart
Documentation
¶
Index ¶
- Constants
- Variables
- func BinaryStringToBytes(s string) (bs []byte)
- func ByteToBinaryString(b byte) string
- func BytesToBinaryString(bs []byte) string
- func Clone(src interface{}) interface{}
- func DefaultCacheTemplateCacheWithResponse(w http.ResponseWriter, r *http.Request) bool
- func DefaultCacheTemplateCacheWithoutResponse(w http.ResponseWriter, r *http.Request) bool
- func DefaultModuleTemplate(w http.ResponseWriter, r *http.Request) bool
- func DefaultPermissionTemplate(w http.ResponseWriter, r *http.Request) (post bool)
- func ExsitsCache(key string) bool
- func GenRsa(prikey, pubkey, crtkey string) error
- func GetCache(key string) []byte
- func GetConnents() int32
- func GetLimit(count, page, limit int) (int, int, int)
- func GetPerm(permList []string, flag uint8) []bool
- func InitResponseCache(cache Cacher)
- func IsUpdate(key string) bool
- func JsonFile(jsonPath, url, host string, router *Router, schemes ...string) http.HandlerFunc
- func NeedUpdate(key string)
- func PrettySlash(p string) string
- func RSA_Encrypt(plainText []byte, path string) ([]byte, error)
- func ReadBinaryString(s string, data interface{}) (err error)
- func RsaDecryptFromBase64(s string, priviteKeyPath string) ([]byte, error)
- func RsaDecryptFromString(s string, priviteKeyPath string) ([]byte, error)
- func SetCache(key string, value []byte)
- func SetKey(name string) string
- func SetPem(name string) string
- func SetUpdate(key string)
- func ShutDown()
- func StartService()
- func StopService()
- func Subtract[T comparable](a, b []T) []T
- func SubtractSliceMap[T comparable](a []T, b map[T]struct{}) []T
- func ToBinaryString(v interface{}) (s string)
- func Uint16ToBinaryString(i uint16) string
- func Uint32ToBinaryString(i uint32) string
- func Uint64ToBinaryString(i uint64) string
- func UnescapeUnicode(raw []byte) (string, error)
- func Var(r *http.Request) params
- type BaseWs
- type CacheStatus
- type Cacher
- type ContentType
- type Definition
- type FlowData
- type Info
- type JsonStr
- type MethodStrcut
- type MethodsRoute
- func (mr MethodsRoute) AddModule(handles ...func(http.ResponseWriter, *http.Request) bool) MethodsRoute
- func (mr MethodsRoute) AddPageKeys(pagekeys ...string) MethodsRoute
- func (mr MethodsRoute) Bind(dest interface{}) MethodsRoute
- func (mr MethodsRoute) BindByContentType(dest interface{}) MethodsRoute
- func (mr MethodsRoute) BindForm(dest interface{}) MethodsRoute
- func (mr MethodsRoute) BindJson(dest interface{}) MethodsRoute
- func (mr MethodsRoute) BindResponse(dest interface{}) MethodsRoute
- func (mr MethodsRoute) BindXml(dest interface{}) MethodsRoute
- func (mr MethodsRoute) BindYaml(dest interface{}) MethodsRoute
- func (mr MethodsRoute) DelHeader(key string) MethodsRoute
- func (mr MethodsRoute) DelModule(handles ...func(http.ResponseWriter, *http.Request) bool) MethodsRoute
- func (mr MethodsRoute) DelPageKeys(pagekeys ...string) MethodsRoute
- func (mr MethodsRoute) GetRoute(method string) *Route
- func (mr MethodsRoute) SetHeader(key, value string) MethodsRoute
- type Opt
- type Parameter
- type ParameterType
- type Response
- type Route
- func (rt *Route) AddModule(handles ...func(http.ResponseWriter, *http.Request) bool) *Route
- func (rt *Route) AddPageKeys(pagekeys ...string) *Route
- func (rt *Route) Bind(s interface{}) *Route
- func (rt *Route) BindByContentType(s interface{}) *Route
- func (rt *Route) BindForm(s interface{}) *Route
- func (rt *Route) BindJson(s interface{}) *Route
- func (rt *Route) BindResponse(response interface{}) *Route
- func (rt *Route) BindXml(s interface{}) *Route
- func (rt *Route) BindYaml(s interface{}) *Route
- func (rt *Route) DelHeader(dh ...string) *Route
- func (rt *Route) DelModule(handles ...func(http.ResponseWriter, *http.Request) bool) *Route
- func (rt *Route) DelPageKeys(pagekeys ...string) *Route
- func (rt *Route) DelPrefix(prefixs ...string) *Route
- func (rt *Route) GetHeader() map[string]string
- func (rt *Route) Prefix(prefix string) *Route
- func (rt *Route) SetHeader(k, v string) *Route
- func (rt *Route) SwaggerAddParameter(pt Parameter) *Route
- func (rt *Route) SwaggerSummary(summary string) *Route
- type RouteGroup
- func (g *RouteGroup) AddGroup(group *RouteGroup) *RouteGroup
- func (g *RouteGroup) AddModule(handles ...func(http.ResponseWriter, *http.Request) bool) *RouteGroup
- func (g *RouteGroup) AddPageKeys(pagekeys ...string) *RouteGroup
- func (gr *RouteGroup) Any(pattern string, handler func(http.ResponseWriter, *http.Request)) MethodsRoute
- func (g *RouteGroup) BindResponse(response interface{}) *RouteGroup
- func (gr *RouteGroup) Connect(pattern string, handler func(http.ResponseWriter, *http.Request)) *Route
- func (g *RouteGroup) DebugAssignRoute(thisurl string)
- func (g *RouteGroup) DebugIncludeTpl(pattern string)
- func (g *RouteGroup) DelHeader(headers ...string) *RouteGroup
- func (g *RouteGroup) DelModule(handles ...func(http.ResponseWriter, *http.Request) bool) *RouteGroup
- func (g *RouteGroup) DelPageKeys(pagekeys ...string) *RouteGroup
- func (g *RouteGroup) DelPrefix(prefixs ...string) *RouteGroup
- func (gr *RouteGroup) Delete(pattern string, handler func(http.ResponseWriter, *http.Request)) *Route
- func (gr *RouteGroup) Get(pattern string, handler func(http.ResponseWriter, *http.Request)) *Route
- func (gr *RouteGroup) Head(pattern string, handler func(http.ResponseWriter, *http.Request)) *Route
- func (gr *RouteGroup) Options(pattern string, handler func(http.ResponseWriter, *http.Request)) *Route
- func (gr *RouteGroup) Patch(pattern string, handler func(http.ResponseWriter, *http.Request)) *Route
- func (gr *RouteGroup) Post(pattern string, handler func(http.ResponseWriter, *http.Request)) *Route
- func (g *RouteGroup) Prefix(prefixs ...string) *RouteGroup
- func (gr *RouteGroup) Put(pattern string, handler func(http.ResponseWriter, *http.Request)) *Route
- func (gr *RouteGroup) Request(pattern string, handler func(http.ResponseWriter, *http.Request), ...) *Route
- func (gr *RouteGroup) Requests(pattern string, handler func(http.ResponseWriter, *http.Request), ...) MethodsRoute
- func (g *RouteGroup) SetHeader(k, v string) *RouteGroup
- func (gr *RouteGroup) Trace(pattern string, handler func(http.ResponseWriter, *http.Request)) *Route
- type Router
- func (r *Router) AddGroup(group *RouteGroup) *Router
- func (r *Router) AddModule(handles ...func(http.ResponseWriter, *http.Request) bool) *Router
- func (r *Router) AddPageKeys(pagekeys ...string) *Router
- func (r *Router) Any(pattern string, handler func(http.ResponseWriter, *http.Request)) MethodsRoute
- func (r *Router) BindResponse(response interface{}) *Router
- func (r *Router) Connect(pattern string, handler func(http.ResponseWriter, *http.Request)) *Route
- func (r *Router) Debug(ctx context.Context, opt ...string)
- func (r *Router) DebugAssignRoute(thisurl string)
- func (r *Router) DebugIncludeTpl(pattern string)
- func (r *Router) DebugRoute()
- func (r *Router) DebugTpl()
- func (r *Router) Delete(pattern string, handler func(http.ResponseWriter, *http.Request)) *Route
- func (r *Router) Get(pattern string, handler func(http.ResponseWriter, *http.Request)) *Route
- func (r *Router) Head(pattern string, handler func(http.ResponseWriter, *http.Request)) *Route
- func (r *Router) Options(pattern string, handler func(http.ResponseWriter, *http.Request)) *Route
- func (r *Router) Patch(pattern string, handler func(http.ResponseWriter, *http.Request)) *Route
- func (r *Router) Post(pattern string, handler func(http.ResponseWriter, *http.Request)) *Route
- func (r *Router) Prefix(prefixs ...string) *Router
- func (r *Router) Put(pattern string, handler func(http.ResponseWriter, *http.Request)) *Route
- func (r *Router) Request(pattern string, handler func(http.ResponseWriter, *http.Request), ...) MethodsRoute
- func (r *Router) Run(opt ...string) error
- func (r *Router) RunTLS(keyfile, pemfile string, opt ...string) error
- func (r *Router) RunUnsafeTLS(opt ...string) error
- func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request)
- func (r *Router) SetHeader(k, v string) *Router
- func (r *Router) ShowSwagger(url, host string, schemes ...string) *RouteGroup
- func (r *Router) Trace(pattern string, handler func(http.ResponseWriter, *http.Request)) *Route
- type Schema
- type Swagger
- type SwaggerUIOpts
- type Type
- type UMR
- type WebSocket
- type WsHandler
Constants ¶
const ( MIMEJSON = "application/json" MIMEXML = "application/xml" MIMEXML2 = "text/xml" MIMEPlain = "text/plain" MIMEPOSTForm = "application/x-www-form-urlencoded" MIMEMultipartPOSTForm = "multipart/form-data" MIMEPROTOBUF = "application/x-protobuf" MIMEMSGPACK = "application/x-msgpack" MIMEMSGPACK2 = "application/msgpack" MIMEYAML = "application/x-yaml" )
const ( TypeMsg = byte(129) TypeBinary = byte(130) TypeClose = byte(136) TypePing = byte(137) TypePong = byte(138) )
const PAGES = "PAGES"
Variables ¶
var ( ErrConnectClosed = errors.New("connect closed") ErrorType = errors.New("type error") ErrorProtocol = errors.New("protocol undefined") ErrorGetLenth = errors.New("get length error") ErrorGetMsg = errors.New("read data error") ErrorMsgNotEnough = errors.New("data length not enough") ErrorNotFoundHandle = errors.New("please write a Handle") ErrorRespose = errors.New("websocket: response does not implement http.Hijacker") ErrorHandshake = errors.New("websocket: client sent data before handshake is complete") ErrorNoWebsocketKey = errors.New("not found Sec-WebSocket-Key") )
var ErrBadStringFormat = errors.New("bad string format")
ErrBadStringFormat represents a error of input string's format is illegal .
var ErrEmptyString = errors.New("empty string")
ErrEmptyString represents a error of empty input string.
var ErrTypeUnsupport = errors.New("data type is unsupported")
Functions ¶
func BinaryStringToBytes ¶
BinaryStringToBytes get the binary bytes according to the input string which is in binary format.
func ByteToBinaryString ¶
ByteToBinaryString get the string in binary format of a byte or uint8.
func BytesToBinaryString ¶
BytesToBinaryString get the string in binary format of a []byte or []int8.
func DefaultCacheTemplateCacheWithResponse ¶
func DefaultCacheTemplateCacheWithResponse(w http.ResponseWriter, r *http.Request) bool
func DefaultCacheTemplateCacheWithoutResponse ¶
func DefaultCacheTemplateCacheWithoutResponse(w http.ResponseWriter, r *http.Request) bool
func DefaultModuleTemplate ¶
func DefaultModuleTemplate(w http.ResponseWriter, r *http.Request) bool
func DefaultPermissionTemplate ¶
func DefaultPermissionTemplate(w http.ResponseWriter, r *http.Request) (post bool)
func GetConnents ¶
func GetConnents() int32
func InitResponseCache ¶
func InitResponseCache(cache Cacher)
func JsonFile ¶
func JsonFile(jsonPath, url, host string, router *Router, schemes ...string) http.HandlerFunc
func PrettySlash ¶
func ReadBinaryString ¶
ReadBinaryString read the string in binary format into input data.
func RsaDecryptFromBase64 ¶
RSA解密
func RsaDecryptFromString ¶
RSA解密
func StartService ¶
func StartService()
func StopService ¶
func StopService()
func SubtractSliceMap ¶
func SubtractSliceMap[T comparable](a []T, b map[T]struct{}) []T
func ToBinaryString ¶
func ToBinaryString(v interface{}) (s string)
ToBinaryString get string in binary format according to input data. The input data can be diffrent kinds of basic data type.
func Uint16ToBinaryString ¶
Uint16ToBinaryString get the string of a uint16 number in binary format.
func Uint32ToBinaryString ¶
Uint32ToBinaryString get the string of a uint32 number in binary format.
func Uint64ToBinaryString ¶
Uint64ToBinaryString get the string of a uint64 number in binary format.
func UnescapeUnicode ¶
将前端传进来的部分中文被编译成unicode编码进行还原
Types ¶
type BaseWs ¶
func UpgradeWebSocket ¶
type CacheStatus ¶
type CacheStatus string
const ( NotFoundCache CacheStatus = "Not found cache" CacheIsUpdateing CacheStatus = "Cache is Updating" CacheNeedUpdate CacheStatus = "Cache need Updating" CacheHit CacheStatus = "cache hit" )
func GetCacheIfUpdating ¶
func GetCacheIfUpdating(key string) ([]byte, CacheStatus)
获取缓存,如果正在更新 如果返回 NotFoundCache 说明不存在这个缓存 如果返回 CacheIsUpdateing 说明当前还在更新中, 还不是最新的缓存 如果返回 CacheNeedUpdate 说明缓存需要更新 如果返回 CacheHit 说明是最新的,可以直接返回
type ContentType ¶
type ContentType string
const ( URLENCODED ContentType = "application/x-www-form-urlencoded" JSON ContentType = "application/json" FORM ContentType = "multipart/form-data" XML ContentType = "application/xml" )
func (ContentType) String ¶
func (ct ContentType) String() string
type Definition ¶
type FlowData ¶
type FlowData struct { Data interface{} // 处理后的数据 Response interface{} // 返回的数据结构 StatusCode int Body []byte CacheKey string // contains filtered or unexported fields }
func GetInstance ¶
func (*FlowData) GetConnectId ¶
func (*FlowData) GetFuncName ¶
func (*FlowData) GetPageKeys ¶
type MethodStrcut ¶
type MethodStrcut struct { Summary string `json:"summary,omitempty" yaml:"summary"` Parameters []Parameter `json:"parameters,omitempty" yaml:"parameters"` Responses map[string]Response `json:"responses,omitempty" yaml:"responses"` Produces []string `json:"produces,omitempty" yaml:"produces" required:""` Consumes []string `json:"consumes,omitempty" yaml:"consumes"` }
type MethodsRoute ¶
string 对应的是method
func (MethodsRoute) AddModule ¶
func (mr MethodsRoute) AddModule(handles ...func(http.ResponseWriter, *http.Request) bool) MethodsRoute
func (MethodsRoute) AddPageKeys ¶
func (mr MethodsRoute) AddPageKeys(pagekeys ...string) MethodsRoute
func (MethodsRoute) Bind ¶
func (mr MethodsRoute) Bind(dest interface{}) MethodsRoute
func (MethodsRoute) BindByContentType ¶
func (mr MethodsRoute) BindByContentType(dest interface{}) MethodsRoute
func (MethodsRoute) BindForm ¶
func (mr MethodsRoute) BindForm(dest interface{}) MethodsRoute
func (MethodsRoute) BindJson ¶
func (mr MethodsRoute) BindJson(dest interface{}) MethodsRoute
func (MethodsRoute) BindResponse ¶
func (mr MethodsRoute) BindResponse(dest interface{}) MethodsRoute
func (MethodsRoute) BindXml ¶
func (mr MethodsRoute) BindXml(dest interface{}) MethodsRoute
func (MethodsRoute) BindYaml ¶
func (mr MethodsRoute) BindYaml(dest interface{}) MethodsRoute
func (MethodsRoute) DelHeader ¶
func (mr MethodsRoute) DelHeader(key string) MethodsRoute
func (MethodsRoute) DelModule ¶
func (mr MethodsRoute) DelModule(handles ...func(http.ResponseWriter, *http.Request) bool) MethodsRoute
func (MethodsRoute) DelPageKeys ¶
func (mr MethodsRoute) DelPageKeys(pagekeys ...string) MethodsRoute
func (MethodsRoute) GetRoute ¶
func (mr MethodsRoute) GetRoute(method string) *Route
get route by method. if not found will return nil
func (MethodsRoute) SetHeader ¶
func (mr MethodsRoute) SetHeader(key, value string) MethodsRoute
type Parameter ¶
type Parameter struct { In ParameterType `json:"in,omitempty" yaml:"in"` Name string `json:"name,omitempty" yaml:"name"` Required bool `required:"in,omitempty" yaml:"required"` Type string `json:"type,omitempty" yaml:"type"` Schema map[string]string `json:"schema,omitempty" yaml:"schema"` Minimum int64 `json:"minimum,omitempty" yaml:"minimum"` Enum []string `json:"enum,omitempty" yaml:"enum"` Default any `json:"default,omitempty" yaml:"default"` Description string `json:"description,omitempty" yaml:"description"` }
type ParameterType ¶
type ParameterType string
const ( Query ParameterType = "query" Path ParameterType = "path" Header ParameterType = "header" Form ParameterType = "formData" )
type Route ¶
type Route struct {
// contains filtered or unexported fields
}
初始化临时使用, 最后会合并到 router
func (*Route) AddPageKeys ¶
func (*Route) BindByContentType ¶
func (*Route) BindResponse ¶
func (*Route) DelPageKeys ¶
func (*Route) SwaggerAddParameter ¶
func (*Route) SwaggerSummary ¶
这个路由的注释, 使用swagger加上这个字段才能显示执行的窗口
type RouteGroup ¶
type RouteGroup struct {
// contains filtered or unexported fields
}
服务启动前的操作, 所以里面的map 都是单线程不需要加锁的
func NewRouteGroup ¶
func NewRouteGroup() *RouteGroup
func Pprof ¶
func Pprof() *RouteGroup
func (*RouteGroup) AddGroup ¶
func (g *RouteGroup) AddGroup(group *RouteGroup) *RouteGroup
组路由添加到组路由
func (*RouteGroup) AddModule ¶
func (g *RouteGroup) AddModule(handles ...func(http.ResponseWriter, *http.Request) bool) *RouteGroup
func (*RouteGroup) AddPageKeys ¶
func (g *RouteGroup) AddPageKeys(pagekeys ...string) *RouteGroup
func (*RouteGroup) Any ¶
func (gr *RouteGroup) Any(pattern string, handler func(http.ResponseWriter, *http.Request)) MethodsRoute
func (*RouteGroup) BindResponse ¶
func (g *RouteGroup) BindResponse(response interface{}) *RouteGroup
func (*RouteGroup) Connect ¶
func (gr *RouteGroup) Connect(pattern string, handler func(http.ResponseWriter, *http.Request)) *Route
func (*RouteGroup) DebugAssignRoute ¶
func (g *RouteGroup) DebugAssignRoute(thisurl string)
func (*RouteGroup) DebugIncludeTpl ¶
func (g *RouteGroup) DebugIncludeTpl(pattern string)
func (*RouteGroup) DelHeader ¶
func (g *RouteGroup) DelHeader(headers ...string) *RouteGroup
func (*RouteGroup) DelModule ¶
func (g *RouteGroup) DelModule(handles ...func(http.ResponseWriter, *http.Request) bool) *RouteGroup
func (*RouteGroup) DelPageKeys ¶
func (g *RouteGroup) DelPageKeys(pagekeys ...string) *RouteGroup
func (*RouteGroup) DelPrefix ¶
func (g *RouteGroup) DelPrefix(prefixs ...string) *RouteGroup
func (*RouteGroup) Delete ¶
func (gr *RouteGroup) Delete(pattern string, handler func(http.ResponseWriter, *http.Request)) *Route
func (*RouteGroup) Get ¶
func (gr *RouteGroup) Get(pattern string, handler func(http.ResponseWriter, *http.Request)) *Route
func (*RouteGroup) Head ¶
func (gr *RouteGroup) Head(pattern string, handler func(http.ResponseWriter, *http.Request)) *Route
func (*RouteGroup) Options ¶
func (gr *RouteGroup) Options(pattern string, handler func(http.ResponseWriter, *http.Request)) *Route
func (*RouteGroup) Patch ¶
func (gr *RouteGroup) Patch(pattern string, handler func(http.ResponseWriter, *http.Request)) *Route
func (*RouteGroup) Post ¶
func (gr *RouteGroup) Post(pattern string, handler func(http.ResponseWriter, *http.Request)) *Route
func (*RouteGroup) Prefix ¶
func (g *RouteGroup) Prefix(prefixs ...string) *RouteGroup
func (*RouteGroup) Put ¶
func (gr *RouteGroup) Put(pattern string, handler func(http.ResponseWriter, *http.Request)) *Route
func (*RouteGroup) Request ¶
func (gr *RouteGroup) Request(pattern string, handler func(http.ResponseWriter, *http.Request), methods ...string) *Route
func (*RouteGroup) Requests ¶
func (gr *RouteGroup) Requests(pattern string, handler func(http.ResponseWriter, *http.Request), methods ...string) MethodsRoute
func (*RouteGroup) SetHeader ¶
func (g *RouteGroup) SetHeader(k, v string) *RouteGroup
func (*RouteGroup) Trace ¶
func (gr *RouteGroup) Trace(pattern string, handler func(http.ResponseWriter, *http.Request)) *Route
type Router ¶
type Router struct { MaxPrintLength int Exit func(time.Time, http.ResponseWriter, *http.Request) Enter func(http.ResponseWriter, *http.Request) bool // 当有请求进入时候的执行 ReadTimeout time.Duration HanleFavicon func(http.ResponseWriter, *http.Request) DisableOption bool // 禁止全局option HandleOptions func(http.ResponseWriter, *http.Request) // 预请求 处理函数, 如果存在, 优先处理, 前后端分离后, 前段可能会先发送一个预请求 HandleNotFound func(http.ResponseWriter, *http.Request) NotFoundRequireField func(string, http.ResponseWriter, *http.Request) bool UnmarshalError func(error, http.ResponseWriter, *http.Request) bool IgnoreSlash bool // 忽略地址多个斜杠, 默认不忽略 SwaggerTitle string SwaggerDescription string SwaggerVersion string // contains filtered or unexported fields }
func (*Router) AddGroup ¶
func (r *Router) AddGroup(group *RouteGroup) *Router
组路由添加到router里面, 挂载到group之前, 全局的变量已经挂载到route 里面了, 所以不用再管组变量了
func (*Router) AddPageKeys ¶
func (*Router) Any ¶
func (r *Router) Any(pattern string, handler func(http.ResponseWriter, *http.Request)) MethodsRoute
func (*Router) BindResponse ¶
func (*Router) DebugAssignRoute ¶
func (*Router) DebugIncludeTpl ¶
func (*Router) DebugRoute ¶
func (r *Router) DebugRoute()
func (*Router) Request ¶
func (r *Router) Request(pattern string, handler func(http.ResponseWriter, *http.Request), methods ...string) MethodsRoute
func (*Router) RunUnsafeTLS ¶
func (*Router) ShowSwagger ¶
func (r *Router) ShowSwagger(url, host string, schemes ...string) *RouteGroup
type Swagger ¶
type Swagger struct { Swagger string `json:"swagger" yaml:"swagger"` Info Info `json:"info" yaml:"info"` Host string `json:"host" yaml:"host"` BasePath string `json:"basePath,omitempty" yaml:"basePath"` Schemes []string `json:"schemes,omitempty" yaml:"schemes"` Paths map[string]map[string]MethodStrcut `json:"paths,omitempty" yaml:"paths"` Definitions map[string]Definition `json:"definitions,omitempty" yaml:"definitions"` Security []map[string][]string `json:"security,omitempty" yaml:"security"` SecurityDefinitions map[string]Type `json:"securityDefinitions,omitempty" yaml:"securityDefinitions"` }
type SwaggerUIOpts ¶
type SwaggerUIOpts struct { // BasePath for the UI path, defaults to: / SpecURL string // The three components needed to embed swagger-ui SwaggerURL string SwaggerPresetURL string SwaggerStylesURL string Favicon32 string Favicon16 string // Title for the documentation site, default to: API documentation Title string }
func DefaultEnsure ¶
func DefaultEnsure(jsonPath string) *SwaggerUIOpts
type UMR ¶
type UMR map[string]MethodsRoute
Source Files
¶
- api.go
- bind.go
- cache.go
- cachetable.go
- contentype.go
- copy.go
- css.go
- doc.go
- doctemplate.go
- group.go
- groupmethod.go
- instance.go
- js.go
- map.go
- match.go
- module.go
- mr.go
- opt.go
- pager.go
- pattern.go
- perm.go
- pprof.go
- proxy.go
- route.go
- router.go
- routermethod.go
- shutdown.go
- slice.go
- swagger.go
- template.go
- tls.go
- tobinary.go
- umr.go
- unicode.go
- var.go
- websocket.go