Golang web filter 輕量級實現

怪咖_OOP發表於2018-08-02

前言

golang web 通過http handle模組進行restful介面與請求處理繫結;既然用了restful每個公司或專案都會制定自己的設計原則和約束條件。在日常開發中通常會根據uri匹配規則在請求進入controller之前進行一些特殊處理(許可權、功能驗證...);在Java web程式設計中 servlet filter幫助我們實現了這樣的功能,golang web通過擴充套件http handle即可實現

案例:

/safe /safe/user

假定: 以/safe開頭的請求對客戶端請求引數進行解密 以/safe/user開頭的請求不僅要對客戶端請求引數進行解密還要驗證當前請求使用者是否線上

實現思路:

定義FilterHandle、WebHandle型別

type FilterHandle func(rw http.ResponseWriter,r *http.Request) error

type WebHandle func(rw http.ResponseWriter,r *http.Request) error
複製程式碼

FilterHandle 攔截器處理函式 WebHandle 客戶端請求處理函式

http handle模組與攔截器處理函式繫結 在攔截器處理函式中通過閉包回撥WebHandle

註冊攔截器處理函式 func Register(uriRule string,fh FilterHandle)

uri 路徑匹配規則

★★★★★ 攔截器註冊在http server 啟動前

web filter程式碼示例:

/**
 * Created with IntelliJ IDEA.
 * Description: 
 * User: yangzhao
 * Date: 2018-08-02
 * Time: 11:01
 */
package web_filter

import (
	"net/http"
	"strings"
)

type FilterHandle func(rw http.ResponseWriter,r *http.Request) error

//攔截uri對映處理
var filterMapping = make(map[string]FilterHandle,0)
//保證有序uri
var uriArray = make([]string,0)

/**
	uriRule 路徑匹配規則
	fh 攔截器處理函式
 */
func Register(uriRule string,fh FilterHandle)  {
	uriRule = uriRule[:len(uriRule)-2]
	filterMapping[uriRule]=fh
	uriArray = append(uriArray,uriRule)
}

type WebHandle func(rw http.ResponseWriter,r *http.Request) error

func Handle(webHandle WebHandle) func(rw http.ResponseWriter,r *http.Request) {

	return func(rw http.ResponseWriter,r *http.Request){
		var uri=r.RequestURI
		uri+="/"
		for _,v:=range uriArray{
			if strings.Contains(uri,v) {
				e := filterMapping[v](rw, r)
				if e != nil {
					rw.Write([]byte(e.Error()))
					return
				}

			}
		}
		err := webHandle(rw, r)
		if err != nil {
			rw.Write([]byte(err.Error()))
		}
	}
}

複製程式碼

測試demo

/**
 * Created with IntelliJ IDEA.
 * Description: 
 * User: yangzhao
 * Date: 2018-08-01
 * Time: 16:16
 */
package test

import (
	"net/http"
	"log"
	"errors"
	"testing"
	"common-go/web/filter"
	"fmt"
)

type HttpServer struct {
	
	http.Server
	
}

func (server *HttpServer) StartServer()  {
	log.Println("web server start "+server.Addr)
	err := server.ListenAndServe()
	if err != nil {
		log.Panic(err)
	}
}

func (server *HttpServer)ServeHTTP(wr http.ResponseWriter, r *http.Request)()  {
	fmt.Println("測試")
}

func TestWebFilter(t *testing.T) {
	web_filter.Register("/safe/**", func(rw http.ResponseWriter, r *http.Request)error {
		return errors.New("解密失敗")
		//return nil
	})
	web_filter.Register("/safe/user/**", func(rw http.ResponseWriter, r *http.Request)error {
		return errors.New("請登入")
		//return nil
	})
	http.HandleFunc("/safe", web_filter.Handle(func(wr http.ResponseWriter,req *http.Request) error{
		wr.Write([]byte(req.RequestURI))
		return nil
	}))

	http.HandleFunc("/safe/user/test", web_filter.Handle(func(wr http.ResponseWriter,req *http.Request) error{
		wr.Write([]byte(req.RequestURI))
		return nil
	}))

	http.HandleFunc("/safe/user", web_filter.Handle(func(wr http.ResponseWriter,req *http.Request) error{
		wr.Write([]byte(req.RequestURI))
		return nil
	}))

	server := &HttpServer{}
	server.Addr=":8080"
	server.StartServer()
}
複製程式碼

以上屬於原創文章,轉載請註明作者@怪咖

QQ:208275451

相關文章