• Stars
    star
    91
  • Rank 353,157 (Top 8 %)
  • Language
    Go
  • License
    MIT License
  • Created over 5 years ago
  • Updated 10 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

⚡ Rux is an simple and fast web framework. support route group, param route binding, middleware, compatible http.Handler interface. 简单且快速的 Go api/web 框架,支持路由分组,路由参数绑定,中间件,兼容 http.Handler 接口

Rux

GitHub go.mod Go version Actions Status GitHub tag (latest SemVer) GoDoc Coverage Status Go Report Card

Simple and fast web framework for build golang HTTP applications.

  • Fast route match, support route group
  • Support route path params and named routing
  • Support cache recently accessed dynamic routes
  • Support route middleware, group middleware, global middleware
  • Support quickly add a RESETFul or Controller style structs
  • Support generic http.Handler interface middleware
  • Support static file access handle
  • Support add handlers for handle NotFound and NotAllowed

中文说明请看 README.zh-CN

GoDoc

Install

go get github.com/gookit/rux

Quick start

NOTICE: v1.3.x is not fully compatible with v1.2.x version

package main

import (
	"github.com/gookit/rux"
)

func main() {
	r := rux.New()
	
	// Add Routes:
	r.GET("/", func(c *rux.Context) {
		c.Text(200, "hello")
	})
	r.GET("/hello/{name}", func(c *rux.Context) {
		c.Text(200, "hello " + c.Param("name"))
	})
	r.POST("/post", func(c *rux.Context) {
		c.Text(200, "hello")
	})
	// add multi method support for an route path
	r.Add("/post[/{id}]", func(c *rux.Context) {
		if c.Param("id") == "" {
			// do create post
			c.Text(200, "created")
			return
		}

		id := c.Params.Int("id")
		// do update post
		c.Text(200, "updated " + fmt.Sprint(id))
	}, rux.POST, rux.PUT)

	// Start server
	r.Listen(":8080")
	// can also
	// http.ListenAndServe(":8080", r)
}

Route Group

r.Group("/articles", func() {
    r.GET("", func(c *rux.Context) {
        c.Text(200, "view list")
    })
    r.POST("", func(c *rux.Context) {
        c.Text(200, "create ok")
    })
    r.GET(`/{id:\d+}`, func(c *rux.Context) {
        c.Text(200, "view detail, id: " + c.Param("id"))
    })
})

Path Params

You can add the path params like: {id} Or {id:\d+}

// can access by: "/blog/123"
r.GET(`/blog/{id:\d+}`, func(c *rux.Context) {
    c.Text(200, "view detail, id: " + c.Param("id"))
})

optional params, like /about[.html] or /posts[/{id}]:

// can access by: "/blog/my-article" "/blog/my-article.html"
r.GET(`/blog/{title:\w+}[.html]`, func(c *rux.Context) {
    c.Text(200, "view detail, id: " + c.Param("id"))
})

r.Add("/posts[/{id}]", func(c *rux.Context) {
    if c.Param("id") == "" {
        // do create post
        c.Text(200, "created")
        return
    }

    id := c.Params.Int("id")
    // do update post
    c.Text(200, "updated " + fmt.Sprint(id))
}, rux.POST, rux.PUT)

Use Middleware

rux support use middleware, allow:

  • global middleware
  • group middleware
  • route middleware

Call priority: global middleware -> group middleware -> route middleware

Examples:

package main

import (
	"fmt"

	"github.com/gookit/rux"
)

func main() {
	r := rux.New()
	
	// add global middleware
	r.Use(func(c *rux.Context) {
	    // do something ...
	})
	
	// add middleware for the route
	route := r.GET("/middle", func(c *rux.Context) { // main handler
		c.WriteString("-O-")
	}, func(c *rux.Context) { // middle 1
        c.WriteString("a")
        c.Next() // Notice: call Next()
        c.WriteString("A")
        // if call Abort(), will abort at the end of this middleware run
        // c.Abort() 
    })
	
	// add more by Use()
	route.Use(func(c *rux.Context) { // middle 2
		c.WriteString("b")
		c.Next()
		c.WriteString("B")
	})

	// now, access the URI /middle
	// will output: ab-O-BA
}
  • Call sequence: middle 1 -> middle 2 -> main handler -> middle 2 -> middle 1
  • Flow chart:
        +-----------------------------+
        | middle 1                    |
        |  +----------------------+   |
        |  | middle 2             |   |
 start  |  |  +----------------+  |   | end
------->|  |  |  main handler  |  |   |--->----
        |  |  |________________|  |   |    
        |  |______________________|   |  
        |_____________________________|

more please see middleware_test.go middleware tests

Use http.Handler

rux is support generic http.Handler interface middleware

You can use rux.WrapHTTPHandler() convert http.Handler as rux.HandlerFunc

package main

import (
	"net/http"
	
	"github.com/gookit/rux"
	// here we use gorilla/handlers, it provides some generic handlers.
	"github.com/gorilla/handlers"
)

func main() {
	r := rux.New()
	
	// create a simple generic http.Handler
	h0 := http.HandlerFunc(func (w http.ResponseWriter, r *http.Request) {
		w.Header().Set("new-key", "val")
	})
	
	r.Use(rux.WrapHTTPHandler(h0), rux.WrapHTTPHandler(handlers.ProxyHeaders()))
	
	r.GET("/", func(c *rux.Context) {
		c.Text(200, "hello")
	})
	// add routes ...
	
    // Wrap our server with our gzip handler to gzip compress all responses.
    http.ListenAndServe(":8000", handlers.CompressHandler(r))
}

More Usage

Static Assets

package main

import (
	"embed"	
	"net/http"

	"github.com/gookit/rux"
)

//go:embed static
var embAssets embed.FS

func main() {
	r := rux.New()

	// one file
	r.StaticFile("/site.js", "testdata/site.js")

	// allow any files in the directory.
	r.StaticDir("/static", "testdata")

	// file type limit in the directory
	r.StaticFiles("/assets", "testdata", "css|js")

	// go 1.16+: use embed assets. access: /embed/static/some.html
	r.StaticFS("/embed", http.FS(embAssets))
}

Name Route

In rux, you can add a named route, and you can get the corresponding route instance(rux.Route) from the router according to the name.

Examples:

	r := rux.New()
	
	// Method 1
	myRoute := rux.NewNamedRoute("name1", "/path4/some/{id}", emptyHandler, "GET")
	r.AddRoute(myRoute)

	// Method 2
	rux.AddNamed("name2", "/", func(c *rux.Context) {
		c.Text(200, "hello")
	})

	// Method 3
	r.GET("/hi", func(c *rux.Context) {
		c.Text(200, "hello")
	}).NamedTo("name3", r)
	
	// get route by name
	myRoute = r.GetRoute("name1")

Redirect

redirect to other page

r.GET("/", func(c *rux.Context) {
    c.AbortThen().Redirect("/login", 302)
})

// Or
r.GET("/", func(c *rux.Context) {
    c.Redirect("/login", 302)
    c.Abort()
})

r.GET("/", func(c *rux.Context) {
    c.Back()
    c.Abort()
})

Cookies

you can quick operate cookies by FastSetCookie() DelCookie()

Note: You must set or delete cookies before writing BODY content

r.GET("/setcookie", func(c *rux.Context) {
    c.FastSetCookie("rux_cookie2", "test-value2", 3600)
    c.SetCookie("rux_cookie", "test-value1", 3600, "/", c.Req.URL.Host, false, true)
	c.WriteString("hello, in " + c.URL().Path)
})

r.GET("/delcookie", func(c *rux.Context) {
	val := ctx.Cookie("rux_cookie") // "test-value1"
	c.DelCookie("rux_cookie", "rux_cookie2")
})

Multi Domains

code is refer from julienschmidt/httprouter

package main

import (
	"log"
	"net/http"

	"github.com/gookit/rux"
)

type HostSwitch map[string]http.Handler

// Implement the ServeHTTP method on our new type
func (hs HostSwitch) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// Check if a http.Handler is registered for the given host.
	// If yes, use it to handle the request.
	if router := hs[r.Host]; router != nil {
		router.ServeHTTP(w, r)
	} else {
		// Handle host names for which no handler is registered
		http.Error(w, "Forbidden", 403) // Or Redirect?
	}
}

func main() {
	// Initialize a router as usual
	router := rux.New()
	router.GET("/", Index)
	router.GET("/hello/{name}", func(c *rux.Context) {})

	// Make a new HostSwitch and insert the router (our http handler)
	// for example.com and port 12345
	hs := make(HostSwitch)
	hs["example.com:12345"] = router

	// Use the HostSwitch to listen and serve on port 12345
	log.Fatal(http.ListenAndServe(":12345", hs))
}

RESETFul Style

package main

import (
	"log"
	"net/http"

	"github.com/gookit/rux"
)

type Product struct {
}

// Uses middlewares [optional]
func (Product) Uses() map[string][]rux.HandlerFunc {
	return map[string][]rux.HandlerFunc{
		// function name: handlers
		"Delete": []rux.HandlerFunc{
			handlers.HTTPBasicAuth(map[string]string{"test": "123"}),
			handlers.GenRequestID(),
		},
	}
}

// all products [optional]
func (p *Product) Index(c *rux.Context) {
	// do something
}

// create product [optional]
func (p *Product) Create(c *rux.Context) {
	// do something
}

// save new product [optional]
func (p *Product) Store(c *rux.Context) {
	// do something
}

// show product with {id} [optional]
func (p *Product) Show(c *rux.Context) {
	// do something
}

// edit product [optional]
func (p *Product) Edit(c *rux.Context) {
	// do something
}

// save edited product [optional]
func (p *Product) Update(c *rux.Context) {
	// do something
}

// delete product [optional]
func (p *Product) Delete(c *rux.Context) {
	// do something
}

func main() {
	router := rux.New()

	// methods	Path	Action	Route Name
    // GET	/product	index	product_index
    // GET	/product/create	create	product_create
    // POST	/product	store	product_store
    // GET	/product/{id}	show	product_show
    // GET	/product/{id}/edit	edit	product_edit
    // PUT/PATCH	/product/{id}	update	product_update
    // DELETE	/product/{id}	delete	product_delete
    // resetful style
	router.Resource("/", new(Product))

	log.Fatal(http.ListenAndServe(":12345", router))
}

Controller Style

package main

import (
	"log"
	"net/http"

	"github.com/gookit/rux"
)

// News controller
type News struct {
}

func (n *News) AddRoutes(g *rux.Router) {
	g.GET("/", n.Index)
	g.POST("/", n.Create)
	g.PUT("/", n.Edit)
}

func (n *News) Index(c *rux.Context) {
	// Do something
}

func (n *News) Create(c *rux.Context) {
	// Do something
}

func (n *News) Edit(c *rux.Context) {
	// Do something
}

func main() {
	router := rux.New()

	// controller style
	router.Controller("/news", new(News))

	log.Fatal(http.ListenAndServe(":12345", router))
}

Build URL

package main

import (
	"log"
	"net/http"

	"github.com/gookit/rux"
)

func main() {
	// Initialize a router as usual
	router := rux.New()
	router.GET(`/news/{category_id}/{new_id:\d+}/detail`, func(c *rux.Context) {
		var u = make(url.Values)
        u.Add("username", "admin")
        u.Add("password", "12345")
		
		b := rux.NewBuildRequestURL()
        // b.Scheme("https")
        // b.Host("www.mytest.com")
        b.Queries(u)
        b.Params(rux.M{"{category_id}": "100", "{new_id}": "20"})
		// b.Path("/dev")
        // println(b.Build().String())
        
        println(c.Router().BuildRequestURL("new_detail", b).String())
		// result:  /news/100/20/detail?username=admin&password=12345
		// get current route name
		if c.MustGet(rux.CTXCurrentRouteName) == "new_detail" {
            // post data etc....
        }
	}).NamedTo("new_detail", router)

	// Use the HostSwitch to listen and serve on port 12345
	log.Fatal(http.ListenAndServe(":12345", router))
}

Help

  • lint
golint ./...
  • format check
# list error files
gofmt -s -l ./
# fix format and write to file
gofmt -s -w some.go
  • unit test
go test -cover ./...

Gookit Packages

  • gookit/ini Go config management, use INI files
  • gookit/rux Simple and fast request router for golang HTTP
  • gookit/gcli build CLI application, tool library, running CLI commands
  • gookit/slog Concise and extensible go log library
  • gookit/event Lightweight event manager and dispatcher implements by Go
  • gookit/cache Generic cache use and cache manager for golang. support File, Memory, Redis, Memcached.
  • gookit/config Go config management. support JSON, YAML, TOML, INI, HCL, ENV and Flags
  • gookit/color A command-line color library with true color support, universal API methods and Windows support
  • gookit/filter Provide filtering, sanitizing, and conversion of golang data
  • gookit/validate Use for data validation and filtering. support Map, Struct, Form data
  • gookit/goutil Some utils for the Go: string, array/slice, map, format, cli, env, filesystem, test and more
  • More please see https://github.com/gookit

See also

License

MIT

More Repositories

1

goutil

💪 Helper Utils(700+): int, byte, string, array/slice, map, struct, dump, convert/format, error, web/http, cli/flag, OS/ENV, filesystem, system, test/assert, time and more. Go 常用的一些工具函数:数字,字符串,数组,Map,结构体,反射,文本,文件,错误,时间日期,特殊处理,格式化,常用信息获取等等
Go
1,480
star
2

color

🎨 Terminal color rendering library, support 8/16 colors, 256 colors, RGB color rendering output, support Print/Sprintf methods, compatible with Windows. GO CLI 控制台颜色渲染工具库,支持16色,256色,RGB色彩渲染输出,使用类似于 Print/Sprintf,兼容并支持 Windows 环境的色彩渲染
Go
1,342
star
3

validate

⚔ Go package for data validation and filtering. support Map, Struct, Form data. Go通用的数据验证与过滤库,使用简单,内置大部分常用验证、过滤器,支持自定义验证器、自定义消息、字段翻译。
Go
904
star
4

config

📝 Go configuration manage(load,get,set,export). support JSON, YAML, TOML, Properties, INI, HCL, ENV and Flags. Multi file load, data override merge, parse ENV var. Go应用配置加载管理,支持多种格式,多文件加载,远程文件加载,支持数据合并,解析环境变量名
Go
471
star
5

event

📢 Lightweight event manager and dispatcher implements by Go. Go实现的轻量级的事件管理、调度程序库, 支持设置监听器的优先级, 支持使用通配符来进行一组事件的监听
Go
395
star
6

gcli

🖥 Go CLI application, tool library, running CLI commands, support console color, user interaction, progress display, data formatting display, generate bash/zsh completion add more features. Go的命令行应用,工具库,运行CLI命令,支持命令行色彩,用户交互,进度显示,数据格式化显示,生成bash/zsh命令补全脚本
Go
314
star
7

slog

📑 Lightweight, configurable, extensible logging library written in Go. Support multi level, multi outputs and built-in multi file logger, buffers, clean, rotate-file handling.一个易于使用的,轻量级、可配置、可扩展的日志库。支持多个级别,输出到多文件;内置文件日志处理、自动切割、清理、压缩等增强功能
Go
266
star
8

cache

🗃 Generic cache use and cache manage. Provide a unified usage API by packaging various commonly used drivers. Support File, Memory, Redis, Memcached and more. Go 通用的缓存使用库,通过包装各种常用的驱动,来提供统一的使用API,便于使用。
Go
166
star
9

filter

⏳ Provide filtering, sanitizing, and conversion of Golang data. 提供对Golang数据的过滤,净化,转换。
Go
131
star
10

ini

📝 Go INI config management. support multi file load, data override merge. parse ENV variable, parse variable reference. Dotenv file parse and loader. INI配置读取管理,支持多文件加载,数据覆盖合并, 解析ENV变量, 解析变量引用。DotEnv 解析加载
Go
73
star
11

gitw

🛠 Git command wrapper, git emojis, generate changelog, get repo, branch, remote information and some git command tools. Git 命令包装器,生成 git 变更记录日志,获取 repo,branch,remote 信息和一些 git 命令工具。
Go
26
star
12

i18n

🏳️An simple i18n messages manage implement, use INI files. 使用INI格式文件,实现的简单方便的语言加载与管理
Go
16
star
13

properties

📝 Java Properties format contents parse, marshal and unmarshal library. Java Properties 格式内容的解析器,编码解码库
Go
8
star
14

nako

A lightweight go web framework.
Go
5
star
15

greq

🛠 greq is a simple http client request builder and sender.
Go
5
star
16

di

Lightweight dependency injection container implements by Go
Go
4
star
17

easytpl

A simple view renderer based on the `html/template`, but much simpler to use. support layout rendering, including templates. 简单的视图渲染工具包,基于原生的 html/template 包,支持布局文件渲染,支持加载多目录,多文件,渲染字符串模板等。
Go
4
star
18

gsr

Go Standards Recommendations - common interfaces. e.g: cache, logger. Golang 一些通用的接口定义
Go
3
star
19

lako

A lightweight go web framework.
Go
3
star
20

chain

A simple HTTP middleware chain implement. 一个简单的HTTP中间件chain实现。
Go
2
star
21

gookit.github.io

Some useful libs for the Golang: router, DI, log, config, cache, event, validate, filter, CLI, i18n, respond-data, view-render
HTML
2
star
22

webproxy

Go
2
star
23

respond

respond Text, HTML, XML, JSON, JSONP data to http.ResponseWriter. 响应不同格式的数据到HTTP客户端
Go
2
star
24

rux-middles

1
star
25

golib

go lib projects
Go
1
star
26

.github

.github common template files for the organization
1
star