Elton

license Build Status

Elton的实现参考了koa以及echo,中间件的调整均为洋葱模型:请求由外至内,响应由内至外。主要特性如下:

  • 处理函数(中间件)均以返回error的形式响应出错,方便使用统一的出错处理中间件将出错统一转换为对应的输出(JSON),并根据出错的类型等生成各类统计分析
  • 成功响应数据直接赋值至Context.Body(interface{}),由统一的响应中间件将其转换为对应的输出(JSON,XML)

Hello, World!

下面我们来演示如何使用elton返回Hello, World!,并且添加了一些常用的中间件。

  1. package main
  2. import (
  3. "github.com/vicanso/elton"
  4. "github.com/vicanso/elton/middleware"
  5. )
  6. func main() {
  7. e := elton.New()
  8. // panic处理
  9. e.Use(middleware.NewRecover())
  10. // 出错处理
  11. e.Use(middleware.NewDefaultError())
  12. // 默认的请求数据解析
  13. e.Use(middleware.NewDefaultBodyParser())
  14. // not modified 304的处理
  15. e.Use(middleware.NewDefaultFresh())
  16. e.Use(middleware.NewDefaultETag())
  17. // 响应数据转换为json
  18. e.Use(middleware.NewDefaultResponder())
  19. e.GET("/", func(c *elton.Context) error {
  20. c.Body = &struct {
  21. Message string `json:"message,omitempty"`
  22. }{
  23. "Hello, World!",
  24. }
  25. return nil
  26. })
  27. e.GET("/books/{id}", func(c *elton.Context) error {
  28. c.Body = &struct {
  29. ID string `json:"id,omitempty"`
  30. }{
  31. c.Param("id"),
  32. }
  33. return nil
  34. })
  35. e.POST("/login", func(c *elton.Context) error {
  36. c.SetContentTypeByExt(".json")
  37. c.Body = c.RequestBody
  38. return nil
  39. })
  40. err := e.ListenAndServe(":3000")
  41. if err != nil {
  42. panic(err)
  43. }
  44. }
  1. go run main.go

之后在浏览器中打开http://localhost:3000/则能看到返回的Hello, World!

路由

elton每个路由可以添加多个中间件处理函数,根据路由与及HTTP请求方法指定不同的路由处理函数。而全局的中间件则可通过Use方法来添加。

  1. e.Use(...func(*elton.Context) error)
  2. e.Method(path string, ...func(*elton.Context) error)
  • eelton实例化对象
  • Method 为HTTP的请求方法,如:GET, PUT, POST等等
  • path 为HTTP路由路径
  • func(*elton.Context) error 为路由处理函数(中间件),当匹配的路由被请求时,对应的处理函数则会被调用

路由示例

elton的路由使用chi的路由简化而来,下面是两个简单的示例。

  1. // 带参数路由
  2. e.GET("/users/{type}", func(c *elton.Context) error {
  3. c.BodyBuffer = bytes.NewBufferString(c.Param("type"))
  4. return nil
  5. })
  6. // 复合参数
  7. e.GET("/books/{category:[a-z-]+}-{type}", func(c *elton.Context) error {
  8. c.BodyBuffer = bytes.NewBufferString(c.Param("category") + c.Param("type"))
  9. return nil
  10. })
  11. // 带中间件的路由配置
  12. e.GET("/users/me", func(c *elton.Context) error {
  13. c.Set("account", "tree.xie")
  14. return c.Next()
  15. }, func(c *elton.Context) error {
  16. c.BodyBuffer = bytes.NewBufferString(c.GetString("account"))
  17. return nil
  18. })

中间件

简单方便的中间件机制,依赖各类定制的中间件,通过各类中间件的组合,方便快捷实现各类HTTP服务,简单介绍数据响应与出错处理的中间件。

responder

HTTP请求响应数据时,需要将数据转换为Buffer返回,而在应用时响应数据一般为各类的struct或map等结构化数据,因此elton提供了Body(interface{})字段来保存这些数据,再使用自定义的中间件将数据转换为对应的字节数据,elton-responder提供了将struct(map)转换为json字节并设置对应的Content-Type,对于string([]byte)则直接输出。

  1. package main
  2. import (
  3. "github.com/vicanso/elton"
  4. "github.com/vicanso/elton/middleware"
  5. )
  6. func main() {
  7. e := elton.New()
  8. // 对响应数据 c.Body 转换为相应的json响应
  9. e.Use(middleware.NewDefaultResponder())
  10. getSession := func(c *elton.Context) error {
  11. c.Set("account", "tree.xie")
  12. return c.Next()
  13. }
  14. e.GET("/users/me", getSession, func(c *elton.Context) (err error) {
  15. c.Body = &struct {
  16. Name string `json:"name"`
  17. Type string `json:"type"`
  18. }{
  19. c.GetString("account"),
  20. "vip",
  21. }
  22. return
  23. })
  24. err := e.ListenAndServe(":3000")
  25. if err != nil {
  26. panic(err)
  27. }
  28. }

error

当请求处理失败时,直接返回error则可,elton从error中获取出错信息并输出。默认的出错处理并不适合实际应用场景,建议使用自定义出错类配合中间件,便于统一的错误处理,程序监控,下面是引入错误中间件将出错转换为json形式的响应。

  1. package main
  2. import (
  3. "github.com/vicanso/elton"
  4. "github.com/vicanso/elton/middleware"
  5. "github.com/vicanso/hes"
  6. )
  7. func main() {
  8. e := elton.New()
  9. // 指定出错以json的形式返回
  10. e.Use(middleware.NewError(middleware.ErrorConfig{
  11. ResponseType: "json",
  12. }))
  13. e.GET("/", func(c *elton.Context) (err error) {
  14. err = &hes.Error{
  15. StatusCode: 400,
  16. Category: "users",
  17. Message: "出错啦",
  18. }
  19. return
  20. })
  21. err := e.ListenAndServe(":3000")
  22. if err != nil {
  23. panic(err)
  24. }
  25. }

更多的中间件可以参考middlewares

bench

  1. goos: darwin
  2. goarch: amd64
  3. pkg: github.com/vicanso/elton
  4. BenchmarkRoutes-8 5569852 214 ns/op 152 B/op 3 allocs/op
  5. BenchmarkGetFunctionName-8 124616256 9.61 ns/op 0 B/op 0 allocs/op
  6. BenchmarkContextGet-8 13823508 84.1 ns/op 16 B/op 1 allocs/op
  7. BenchmarkContextNewMap-8 157319816 7.60 ns/op 0 B/op 0 allocs/op
  8. BenchmarkConvertServerTiming-8 1339969 1059 ns/op 360 B/op 11 allocs/op
  9. BenchmarkGetStatus-8 1000000000 0.282 ns/op 0 B/op 0 allocs/op
  10. BenchmarkStatic-8 20527 56061 ns/op 25975 B/op 628 allocs/op
  11. BenchmarkGitHubAPI-8 13024 92207 ns/op 33829 B/op 812 allocs/op
  12. BenchmarkGplusAPI-8 260158 4349 ns/op 2147 B/op 52 allocs/op
  13. BenchmarkParseAPI-8 135792 8433 ns/op 4288 B/op 104 allocs/op
  14. BenchmarkRWMutexSignedKeys-8 75854030 15.9 ns/op 0 B/op 0 allocs/op
  15. BenchmarkAtomicSignedKeys-8 833694663 1.43 ns/op 0 B/op 0 allocs/op
  16. PASS
  17. ok github.com/vicanso/elton 19.403s
  18. goos: darwin
  19. goarch: amd64
  20. pkg: github.com/vicanso/elton/middleware
  21. BenchmarkGenETag-8 244416 4521 ns/op 280 B/op 7 allocs/op
  22. BenchmarkMd5-8 196239 6011 ns/op 232 B/op 7 allocs/op
  23. BenchmarkProxy-8 14181 76270 ns/op 15840 B/op 105 allocs/op
  24. PASS
  25. ok github.com/vicanso/elton/middleware 5.429s