• 在Go中简单实现HTTP服务中间件


    通常一个简单http服务框架,就是注册一堆路由,然后根据路由调用不同的逻辑去处理。

    但实际上可能有一些统一的处理对几乎所有的路由都涉及到,比如日志,比如权限等等。

    那么这个时候搞一个中间做预处理,是一个不错的想法。

    定义一个中间件单元:

     1 package main
     2 
     3 import (
     4     "net/http"
     5 )
     6 
     7 // AdaptorHandle middleware func type
     8 type AdaptorHandle func(w http.ResponseWriter, r *http.Request) (next bool, err error)
     9 
    10 // MiddleWareAdaptor router middlewares mapped by url
    11 type MiddleWareAdaptor struct {
    12     URLs map[string][]AdaptorHandle
    13 }
    14 
    15 // MakeMiddleWareAdaptor make a middleware adaptor
    16 func MakeMiddleWareAdaptor() *MiddleWareAdaptor {
    17     mwa := &MiddleWareAdaptor{
    18         URLs: make(map[string][]AdaptorHandle),
    19     }
    20 
    21     return mwa
    22 }
    23 
    24 // Regist regist a adaptor
    25 func (mw *MiddleWareAdaptor) Regist(url string, Adaptor ...AdaptorHandle) {
    26     for _, adp := range Adaptor {
    27         mw.URLs[url] = append(mw.URLs[url], adp)
    28         // mw.URLs[url] = adp
    29     }
    30 }
    31 
    32 // Exec exec middleware adaptor funcs...
    33 func (mw *MiddleWareAdaptor) Exec(url string, w http.ResponseWriter, r *http.Request) (bool, error) {
    34     if adps, ok := mw.URLs[url]; ok {
    35         for _, adp := range adps {
    36             if next, err := adp(w, r); !next || (err != nil) {
    37                 return next, err
    38             }
    39         }
    40     }
    41     return true, nil
    42 }

    然后将路由处理函数用中间件入口包裹起来:

     1 func middlewareHandler(next http.Handler) http.Handler {
     2     return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
     3         // before call handler
     4         start := time.Now()
     5         do, _ := mwa.Exec(r.URL.Path, w, r) // exec middleware
     6         // call next handler
     7         if do {
     8             log.Println("middleware done. next...")
     9             next.ServeHTTP(w, r)
    10         } else {
    11             log.Println("middleware done.break...")
    12         }
    13         // after call handle
    14         log.Printf("Comleted %s in %v", r.URL.Path, time.Since(start))
    15     })
    16 }
    17 
    18 mux.Handle("/", middlewareHandler(&uPlusRouterHandler{}))
    19 
    20 type uPlusRouterHandler struct {
    21 }
    22 
    23 func (rh *uPlusRouterHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    24 ...
    25 }
     

    最后注册你需要的中间件即可:

    mwa = MakeMiddleWareAdaptor() // init middleware
    mwa.Regist("/", testMWAfunc, testMWAfunc2) // regist middleware
    ...
    func testMWAfunc(w http.ResponseWriter, r *http.Request) (bool, error) {
        log.Println("我是第一个中间件...")
        log.Printf("Started %s %s", r.Method, r.URL.Path)
        return true, nil
    }
    
    func testMWAfunc2(w http.ResponseWriter, r *http.Request) (bool, error) {
        log.Println("我是第二个中间件...")
        return false, nil // return false,break follow-up actions.
    }

    代码虽然简单,记录一个思路。

  • 相关阅读:
    js 文件的操作
    js重点基础知识 以及小案例_最简单的轮播图 简单的动态表格( encodeURIComponent()编码比 encodeURI()编码)
    2阶——数据库连接池 c3p0 , druid, dbcp (其实所有的连接池都实现了dataSource接口,就可以调用getconnection方法)
    2阶——JDBC,JDBCTemplate(操作数据库)
    vue + django 批量删除
    简单的模糊搜索 Vue + django
    vue 父子组件传参简单的分页
    vue 多对多反序列化上传图片
    模型里的 抽象类 表继承
    django 多对多反序列添加
  • 原文地址:https://www.cnblogs.com/codingnote/p/11265527.html
Copyright © 2020-2023  润新知