1. 程式人生 > >Golang Http Handlers as Middleware

Golang Http Handlers as Middleware

From: http://capotej.com/

轉者按:本文介紹瞭如何hook一個http的處理函式,從而加入自定義的內容。

Most modern web stacks allow the “filtering” of requests via stackable/composable middleware, allowing you to cleanly separate cross-cutting concerns from your web application. This weekend I needed to hook into go’shttp.FileServer and was pleasantly surprised how easy it was to do.

Let’s start with a basic file server for /tmp

:

main.go
1
2
3
func main() {
    http.ListenAndServe(":8080", http.FileServer(http.Dir("/tmp")))
}

This starts up a local file server at :8080. How can we hook into this so we can run some code before file requests are served? Let’s look at the method signature for http.ListenAndServe:

1
func
ListenAndServe(addr string, handler Handler) error

So it looks like http.FileServer returns a Handler that knows how to serve files given a root directory. Now let’s look at the Handler interface:

1
2
3
type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}

Because of go’s granular interfaces, any object can be a Handler

 so long as it implements ServeHTTP. It seems all we need to do is construct our own Handler that wraps http.FileServer’s handler. There’s a built in helper for turning ordinary functions into handlers called http.HandlerFunc:

1
type HandlerFunc func(ResponseWriter, *Request)

Then we just wrap http.FileServer like so:

main.go
1
2
3
4
5
6
7
8
9
10
11
12
func OurLoggingHandler(h http.Handler) http.Handler {
  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    fmt.Println(*r.URL)
    h.ServeHTTP(w, r)
  })
}
func main() {
    fileHandler := http.FileServer(http.Dir("/tmp"))
    wrappedHandler := OurLoggingHandler(fileHandler)
    http.ListenAndServe(":8080", wrappedHandler)
}

Go has a bunch of other builtin handlers like TimeoutHandler and RedirectHandler that can be mixed and matched the same way.

type TraceHandler struct {
        h http.Handler
        n int
}

func (r *TraceHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
        r.n++
        fmt.Printf("counter = %d\n", r.n) //why counter always zero
        fmt.Println("get", req.URL.Path, " from ", req.RemoteAddr)
        r.h.ServeHTTP(w, req)
}

func main() {
        port := "9090" //Default port
        if len(os.Args) > 1 {
                port = strings.Join(os.Args[1:2], "")
        }
        h := http.StripPrefix("/icclogs/", http.FileServer(http.Dir("./logs/")))
        http.Handle("/icclogs/", &TraceHandler{h: h, n: 0})

        println("Listening on port ", port, "...")
        err := http.ListenAndServe(":"+port, nil) //設定監聽的埠

        if err != nil {
                log.Fatal("ListenAndServe: ", err)
        }
}

相關推薦

Golang Http Handlers as Middleware

From: http://capotej.com/ 轉者按:本文介紹瞭如何hook一個http的處理函式,從而加入自定義的內容。 Most modern web stacks allow the “filtering” of requests via stackabl

Golang Http Middleware 判斷 增加cookie

原始碼: package main import ( "fmt" "net/http" . "github.com/soekchl/myUtils" ) func main() { finalHandler := http.HandlerFunc(final

golang http服務器跨域問題解決

font and http服務器 -s 客戶 run style header() client func main() { openHttpListen() } func openHttpListen() { http.HandleFunc("/

golang http伺服器跨域問題解決

func main() { openHttpListen() } func openHttpListen() { http.HandleFunc("/", receiveClientRequest) fmt.Println("go server start running

golang http clietn 上傳檔案

今天使用網上無意間看到了搜狗圖片上傳,使用瀏覽器的方式實現的。於是就用go嘗試了下 //上傳檔案的api uploadUrl := "http://" file, err := os.OpenFile("QQ20180817-202205.png", os.O_RDONLY, os

golang http gzip

當我們用http傳送訊息時,可以指定為gzip壓縮,對資料進行壓縮後再傳輸不僅可以節省頻寬還可以加快傳輸速度,對於雙方而言都是一件能夠取得更大收益的事情。 廢話不多說,直接上程式碼 http_server.go 1 package main 2 3 import ( 4 "com

Golang http 開啟 gzip

一. 測試程式碼 1.1. http 開啟 gzip 資料大小對比 1.2. http 開啟 gzip benchmark 對比 參考 一. 測試程式碼

golang Http服務淺析

golang的HTTP包提供了了很強大的功能,開發人員即使不使用框架也可以很方便的進行開發。下面就簡單說一下開發web應用時HTTP包都做了哪些工作。 我們在建立一個WEB應用的時候經常會這樣使用: ```golang     http.HandleFunc("/hel

Go語言之Golang http請求第三方庫HttpRequest

Golang的第三方http請求包 https://github.com/kirinlabs/HttpRequest 具有快速構建Headers、Cookies、設定超時時間、請求耗時等功能 不管是Get還是Post請求都可以快速構建併發送請求,甚至還支援Put和Dele

Golang http短連線

客戶端關閉Http連線 在客戶端關閉 http 連線 直接在請求後關閉連線 func main() { req, err := http.NewRequest("GET", "http://localhost",nil ) if err !

golang http 伺服器程式設計

golang http 伺服器程式設計 1. 初識 http 是典型的 C/S 架構,客戶端向服務端傳送請求(request),服務端做出應答(response)。 golang 的標準庫 net/http 提供了 http 程式設計有關的介面,封裝了內部TCP連線和報文解析的複雜瑣碎的細節,使

[Tutorial, Part 1] How to develop Go gRPC microservice with HTTP/REST endpoint, middleware

[Tutorial, Part 1] How to develop Go gRPC microservice with HTTP/REST endpoint, middleware, Kubernetes deployment, etc.There are a lot of article how to cr

記錄一下golang http-server的處理流程。

原始碼位於go標準庫的net/http/server.go中。 1:從入口點http.ListenAndServe跟程式碼 func (srv *Server) ListenAndServe() error { addr := srv.Addr //獲取地址

docker(8):使用alpinelinux 構建 golang http 看看能有多小

1,alpine linux 非常小 首先 alpine 非常的小,安裝上了bash 之後也才 5mb。 golang 不需要其他的依賴,想看看是不是能在 alpine 上面跑呢。 搭建一個golang的環境,而不是把golang的環境放到alpine

golang http server原始碼解讀

1. 初識 http 是典型的 C/S 架構,客戶端向服務端傳送請求(request),服務端做出應答(response)。 golang 的標準庫 net/http 提供了 http 程式設計有關的介面,封裝了內部TCP連線和報文解析的複雜瑣碎的細節,使用者只需要和

golang http 中介軟體

Processing HTTP requests with Go is primarily about two things: ServeMuxes and Handlers. A ServeMux is essentially a HTTP request route

golang http獲取上傳檔案 小記

r.ParseMultipartForm(32 << 20) //分配獲取資訊記憶體 file, handler, err := r.FormFile("uploadfile") //name的欄位 if err !=

golang http 程式設計-1(伺服器程式設計)

http 程式設計 http常見請求方法 1. Get 請求,請求一個頁面或者資訊 2. Post 請求, 提交一個表單給伺服器使用 3. Put 請求,建立一個資源,一般上傳檔案使用該方法 4. Delete請求,刪除一個資訊使用

golang http 連線超時和傳輸超時

golang 測試程式碼 package main import ( "net/http" "net/url" "fmt" "io/ioutil" "time

golang http.FileServer 遇到的坑

上次寫了一個2行實現一個靜態伺服器的 文章 今天群裡有個哥們是這麼寫居然返回的是404 見鬼了嘛?? http.handle("/js", http.FileServer(http.Dir("js")) http.ListenAndServe("8080",