首页
学习
活动
专区
圈层
工具
发布
16 篇文章
1
Go 语言 Web 编程系列(一)—— 快速入门:创建第一个 Web 应用
2
Go 语言 Web 编程系列(二)—— HTTP 请求处理的底层运行机制
3
Go 语言 Web 编程系列(三)—— 基于官方标准库自定义路由处理器
4
Go 语言 Web 编程系列(四)—— 基于 gorilla/mux 包实现路由定义:基本使用篇
5
Go 语言 Web 编程系列(五)—— 基于 gorilla/mux 包实现路由匹配:进阶使用篇
6
Go 语言 Web 编程系列(六)—— 基于 gorilla/mux 包实现路由匹配:路由中间件
7
Go 语言 Web 编程系列(七)—— 基于 gorilla/mux 包实现路由匹配:处理静态资源响应
8
Go 语言 Web 编程系列(八)—— 基于 gorilla/mux 包实现路由匹配:服务 SPA 应用
9
Go 语言 Web 编程系列(九)—— 基于 gorilla/mux 包实现路由匹配:通过 CORS 处理跨域请求
10
Go 语言 Web 编程系列(十)—— 基于 gorilla/mux 包实现路由匹配:健康检查与接口测试
11
Go 语言 Web 编程系列(十一)—— 仿照 Laravel 框架对 Go 路由代码进行拆分
12
Go 语言 Web 编程系列(十二)—— 通过 Request 读取 HTTP 请求报文
13
Go 语言 Web 编程系列(十三)—— 获取用户请求数据(上)
14
Go 语言 Web 编程系列(十四)—— 获取用户请求数据(下)
15
Go 语言 Web 编程系列(十五)—— 通过 ResponseWriter 接口创建 HTTP 响应
16
Go 语言 Web 编程系列(十六)—— 设置、读取和删除 Cookie

Go 语言 Web 编程系列(六)—— 基于 gorilla/mux 包实现路由匹配:路由中间件

和 Laravel 路由一样,Mux 也支持在路由中使用中间件,并且按照顺序匹配执行。如果你对中间件不太了解,可以先去看下我们在 Laravel 中间件文档中的简单介绍:https://xueyuanjun.com/post/19926。和 Laravel 一样,在 Go Web 编程中,中间件的典型使用场景包括认证、日志、请求头操作和 ResponseWriter “劫持”等。

一个典型的 Mux 路由中间件通常通过一个闭包来定义,我们可以在闭包函数中处理传入的请求和响应实例或增加额外业务逻辑,然后调用传入的处理器继续后续请求处理(可能是下一个中间件或者最终的路由处理器)。比如,我们可以这样定义一个日志中间件:

代码语言:javascript
复制
func loggingMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // Do stuff here
        log.Println(r.RequestURI)
        // Call the next handler, which can be another middleware in the chain, or the final handler.
        next.ServeHTTP(w, r)
    })
}
代码语言:javascript
复制

这个实现和 Laravel 中间件非常相似,通过类比的方式很容易理解:

代码语言:javascript
复制
代码语言:javascript
复制
<?php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Log;

class RequestLog
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
{
        Log::info(request()->url());
        return $next($request);
    }
}

如果要将上述 Mux 日志中间件应用到所有路由,可以通过 Use 方法实现:

代码语言:javascript
复制
代码语言:javascript
复制
r := mux.NewRouter()
r.Use(loggingMiddleware)

还可以将其批量应用到子路由,以便限定其作用范围:

代码语言:javascript
复制
代码语言:javascript
复制
postRouter := r.PathPrefix("/posts").Subrouter()
postRouter.Use(loggingMiddleware)

当然,上述日志中间件的定义非常简单,没有涉及请求处理和异常中断,我们可以仿照 Laravel 中间件文档中的 CheckToken 示例实现 Mux 版本的令牌检查中间件:

代码语言:javascript
复制
代码语言:javascript
复制
func checkToken(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // Do stuff here
        token := r.FormValue("token")
        if token == "xueyuanjun.com" {
            log.Printf("Token check success: %s\n", r.RequestURI)
            // Call the next handler, which can be another middleware in the chain, or the final handler.
            next.ServeHTTP(w, r)
        } else {
            http.Error(w, "Forbidden", http.StatusForbidden)
        }
    })
}

我们将其应用到 postRouter 子路由:

代码语言:javascript
复制
postRouter := r.PathPrefix("/posts").Subrouter()
postRouter.Use(checkToken)

重新启动 Go HTTP 服务器,访问任意 posts 子路由,就会被拒绝访问:

只有传递了正确的 token 参数才可以正常访问:

如果我们将日志中间件应用到全局路由器的话,此时可以在日志输出中看到所有请求的日志信息:

关于 Mux 路由中间件我们就简单介绍到这里,下一篇教程,我们继续探索 Mux 路由的其它用法,比如处理静态文件和单页面应用。

下一篇
举报
领券