当前位置: 首页 > 文档资料 > Go Macaron 文档 >

中间件模块 - 核心服务

优质
小牛编辑
127浏览
2023-12-01

Macaron 会注入一些默认服务来驱动您的应用,这些服务被称之为 核心服务。也就是说,您可以直接使用它们作为处理器参数而不需要任何附加工作。

请求上下文(Context)

该服务通过类型 *macaron.Context 来体现。这是 Macaron 最为核心的服务,您的任何操作都是基于它之上。该服务包含了您所需要的请求对象、响应流、模板引擎接口、数据存储和注入与获取其它服务。

使用方法:

  1. package main
  2. import "gopkg.in/macaron.v1"
  3. func Home(ctx *macaron.Context) {
  4. // ...
  5. }

Next()

方法 Context.Next 是一个可选的功能,它可以用于中间件处理器暂时放弃执行,等待其他的处理器都执行完毕后继续执行。这样就可以很好的处理在 HTTP 请求完成后需要做的操作:

  1. // log before and after a request
  2. m.Use(func(ctx *macaron.Context, log *log.Logger){
  3. log.Println("before a request")
  4. ctx.Next()
  5. log.Println("after a request")
  6. })

Cookie

最基本的 Cookie 用法:

  • *macaron.Context.SetCookie
  • *macaron.Context.GetCookie*macaron.Context.GetCookieInt*macaron.Context.GetCookieInt64*macaron.Context.GetCookieFloat64

使用方法:

  1. // ...
  2. m.Get("/set", func(ctx *macaron.Context) {
  3. ctx.SetCookie("user", "Unknwon", 1)
  4. })
  5. m.Get("/get", func(ctx *macaron.Context) string {
  6. return ctx.GetCookie("user")
  7. })
  8. // ...

使用以下顺序的参数来设置更多的属性:SetCookie(<name>, <value>, <max age>, <path>, <domain>, <secure>, <http only>)

因此,设置 Cookie 最完整的用法为:SetCookie("user", "unknwon", 999, "/", "localhost", true, true)

需要注意的是,参数的顺序是固定的。

如果需要更加安全的 Cookie 机制,可以先使用 macaron.SetDefaultCookieSecret 设定密钥,然后使用:

  • *macaron.Context.SetSecureCookie
  • *macaron.Context.GetSecureCookie

这两个方法将会自动使用您设置的默认密钥进行加密/解密 Cookie 值。

使用方法:

  1. // ...
  2. m.SetDefaultCookieSecret("macaron")
  3. m.Get("/set", func(ctx *macaron.Context) {
  4. ctx.SetSecureCookie("user", "Unknwon", 1)
  5. })
  6. m.Get("/get", func(ctx *macaron.Context) string {
  7. name, _ := ctx.GetSecureCookie("user")
  8. return name
  9. })
  10. // ...

对于那些对安全性要求特别高的应用,可以为每次设置 Cookie 使用不同的密钥加密/解密:

  • *macaron.Context.SetSuperSecureCookie
  • *macaron.Context.GetSuperSecureCookie

使用方法:

  1. // ...
  2. m.Get("/set", func(ctx *macaron.Context) {
  3. ctx.SetSuperSecureCookie("macaron", "user", "Unknwon", 1)
  4. })
  5. m.Get("/get", func(ctx *macaron.Context) string {
  6. name, _ := ctx.GetSuperSecureCookie("macaron", "user")
  7. return name
  8. })
  9. // ...

其它辅助方法

  • 设置/获取 URL 参数:ctx.SetParams / ctx.Paramsctx.ParamsEscapectx.ParamsIntctx.ParamsInt64ctx.ParamsFloat64
  • 获取查询参数:ctx.Queryctx.QueryEscapectx.QueryIntctx.QueryInt64ctx.QueryFloat64ctx.QueryStringsctx.QueryTrim
  • 服务内容或文件:ctx.ServeContentctx.ServeFilectx.ServeFile, ctx.ServeFileContent
  • 获取远程 IP 地址:ctx.RemoteAddr

路由日志

该服务可以通过函数 macaron.Logger 来注入。该服务主要负责应用的路由日志。

使用方法:

  1. package main
  2. import "gopkg.in/macaron.v1"
  3. func main() {
  4. m := macaron.New()
  5. m.Use(macaron.Logger())
  6. // ...
  7. }

备注 当您使用 macaron.Classic 时,该服务会被自动注入。

从 Peach 项目中提取的样例输出:

  1. [Macaron] Started GET /docs/middlewares/core.html for [::1]
  2. [Macaron] Completed /docs/middlewares/core.html 200 OK in 2.114956ms

容错恢复

该服务可以通过函数 macaron.Recovery 来注入。该服务主要负责在应用发生恐慌(panic)时进行恢复。

使用方法:

  1. package main
  2. import "gopkg.in/macaron.v1"
  3. func main() {
  4. m := macaron.New()
  5. m.Use(macaron.Recovery())
  6. // ...
  7. }

备注 当您使用 macaron.Classic 时,该服务会被自动注入。

静态文件

该服务可以通过函数 macaron.Static 来注入。该服务主要负责应用静态资源的服务,当您的应用拥有多个静态目录时,可以对其进行多次注入。

使用方法:

  1. package main
  2. import "gopkg.in/macaron.v1"
  3. func main() {
  4. m := macaron.New()
  5. m.Use(macaron.Static("public"))
  6. m.Use(macaron.Static("assets"))
  7. // ...
  8. }

备注 当您使用 macaron.Classic 时,该服务会以 public 为静态目录被自动注入。

默认情况下,当您请求一个目录时,该服务不会列出目录下的文件,而是去寻找 index.html 文件。

从 Peach 项目中提取的样例输出:

  1. [Macaron] Started GET /css/prettify.css for [::1]
  2. [Macaron] [Static] Serving /css/prettify.css
  3. [Macaron] Completed /css/prettify.css 304 Not Modified in 97.584us
  4. [Macaron] Started GET /imgs/macaron.png for [::1]
  5. [Macaron] [Static] Serving /imgs/macaron.png
  6. [Macaron] Completed /imgs/macaron.png 304 Not Modified in 123.211us
  7. [Macaron] Started GET /js/gogsweb.min.js for [::1]
  8. [Macaron] [Static] Serving /js/gogsweb.min.js
  9. [Macaron] Completed /js/gogsweb.min.js 304 Not Modified in 47.653us
  10. [Macaron] Started GET /css/main.css for [::1]
  11. [Macaron] [Static] Serving /css/main.css
  12. [Macaron] Completed /css/main.css 304 Not Modified in 42.58us

使用示例

假设您的应用拥有以下目录结构:

  1. public/
  2. |__ html
  3. |__ index.html
  4. |__ css/
  5. |__ main.css

响应结果:

请求 URL匹配文件
/html/main.html匹配失败
/html/index.html
/css/main.cssmain.css

自定义选项

该服务允许接受第二个参数来进行自定义选项操作(macaron.StaticOptions):

  1. package main
  2. import "gopkg.in/macaron.v1"
  3. func main() {
  4. m := macaron.New()
  5. m.Use(macaron.Static("public",
  6. macaron.StaticOptions{
  7. // 请求静态资源时的 URL 前缀,默认没有前缀
  8. Prefix: "public",
  9. // 禁止记录静态资源路由日志,默认为不禁止记录
  10. SkipLogging: true,
  11. // 当请求目录时的默认索引文件,默认为 "index.html"
  12. IndexFile: "index.html",
  13. // 用于返回自定义过期响应头,默认为不设置
  14. // https://developers.google.com/speed/docs/insights/LeverageBrowserCaching
  15. Expires: func() string {
  16. return time.Now().Add(24 * 60 * time.Minute).UTC().Format("Mon, 02 Jan 2006 15:04:05 GMT")
  17. },
  18. }))
  19. // ...
  20. }

注册多个静态处理器

如果您需要一次注册多个静态处理器,可以使用方法 macaron.Statics 来简化您的工作。

使用方法:

  1. // ...
  2. m.Use(macaron.Statics(macaron.StaticOptions{}, "public", "views"))
  3. // ...

这样,就可以同时注册 publicviews 为静态目录了。

其它服务

全局日志

该服务通过类型 *log.Logger 来体现。该服务为可选,只是为没有日志器的应用提供一定的便利。

使用方法:

  1. package main
  2. import (
  3. "log"
  4. "gopkg.in/macaron.v1"
  5. )
  6. func main() {
  7. m := macaron.Classic()
  8. m.Get("/", myHandler)
  9. m.Run()
  10. }
  11. func myHandler(ctx *macaron.Context, logger *log.Logger) string {
  12. logger.Println("the request path is: " + ctx.Req.RequestURI)
  13. return "the request path is: " + ctx.Req.RequestURI
  14. }

备注 所有 Macaron 实例 都会自动注册该服务。

响应流

该服务通过类型 http.ResponseWriter 来体现。该服务为可选,一般情况下可直接使用 *macaron.Context.Resp

使用方法:

  1. package main
  2. import (
  3. "gopkg.in/macaron.v1"
  4. )
  5. func main() {
  6. m := macaron.Classic()
  7. m.Get("/", myHandler)
  8. m.Run()
  9. }
  10. func myHandler(ctx *macaron.Context) {
  11. ctx.Resp.Write([]byte("the request path is: " + ctx.Req.RequestURI))
  12. }

备注 所有 Macaron 实例 都会自动注册该服务。

请求对象

该服务通过类型 *http.Request 来体现。该服务为可选,一般情况下可直接使用 *macaron.Context.Req

除此之外,该服务还提供了 3 个便利的方法来获取请求体:

  • *macaron.Context.Req.Body().String():获取 string 类型的请求体
  • *macaron.Context.Req.Body().Bytes():获取 []byte 类型的请求体
  • *macaron.Context.Req.Body().ReadCloser():获取 io.ReadCloser 类型的请求体

使用方法:

  1. package main
  2. import (
  3. "gopkg.in/macaron.v1"
  4. )
  5. func main() {
  6. m := macaron.Classic()
  7. m.Get("/body1", func(ctx *macaron.Context) {
  8. reader, err := ctx.Req.Body().ReadCloser()
  9. // ...
  10. })
  11. m.Get("/body2", func(ctx *macaron.Context) {
  12. data, err := ctx.Req.Body().Bytes()
  13. // ...
  14. })
  15. m.Get("/body3", func(ctx *macaron.Context) {
  16. data, err := ctx.Req.Body().String()
  17. // ...
  18. })
  19. m.Run()
  20. }

需要注意的是,请求体在每个请求中只能被读取一次。

有时您需要传递类型为 *http.Request 的参数,则应该使用 *macaron.Context.Req.Request

备注 所有 Macaron 实例 都会自动注册该服务。