歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> 擁抱 Go 的 HTTP 工具

擁抱 Go 的 HTTP 工具

日期:2017/3/1 9:49:51   编辑:Linux編程

不久前我發布了nosurf,這是Go語言的一個CSRF跨站請求偽造(Cross-Site Request Forgery)中間件。編寫一個看起來簡單並且小巧的包就足以讓你愛上Go處理HTTP的方式。然而,這卻取決於我們擁抱標准的HTTP設施或者是粉碎它,犧牲可組性和模塊化。

http.Handler是接口

與此同時,在Go語言中,唯一需要的接口自2009年就一直在發展中,盡管它從那時起經歷了許多嚴重的改變,但是在2011年末,Go 1.0發布前的幾個月,它已經變得非常穩定。

當然,我說的是mightyhttp.Handler。

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

為了能夠處理HTTP請求,你的類型僅僅需要實現這個方法就可以了。這個方法從給定的*Request讀取請求信息,並且將響應信息寫在給定的ResponseWriter中。看起來很簡單,是吧?

補充它,但不能取代它

然而,在此基礎之上的建立抽象時,有些東西弄錯了。舉個例子,Mango,被它的作者描述為“一個模塊化的Go語言Web應用程序框架,靈感來自Rack和PEP333”。
這是一個Mango應用程序的樣子:

func Hello(env mango.Env) (mango.Status, mango.Headers, mango.Body) {
return 200, mango.Headers{}, mango.Body("Hello World!")
}

看起來簡單,簡潔,並且非常類似於WSGI或者Rack,對不對?除了一件事情。在使用動態/鴨式類型時,你可以在任何一個body上用上迭代,這裡的mango.Body只是一個簡單的字符串。從本質上講,這樣就丟掉了做任何形式的流式響應的能力。即便是暴露一個ResponseWriter,任何寫入它的東西都將與返回的值沖突,因為它們只在函數結束時返回,在已經調用了ResponseWriter之後。

這不好。你是否需要基於現有的net/http的另外一個接口,只是你的口味問題,但即使你這樣做了,它也不應該拿掉其它的功能。一個接口,在其上的編寫代碼感覺更棒,但是它帶走了重要的功能,顯然就遜色了。

正確的方法

現在流行的一個“微型”Web框架web.go使用了一種簡單,但更好的方法。它的處理程序使用一個指向web.Contextas的指針作為可選的第一個參數。

type Context struct {
Request *http.Request
Params map[string]string
Server *Server
http.ResponseWriter
}
// ...
func hello(ctx *web.Context, val string) string {
return "hello " + val
}

web.Context不再采取標准的HTTP處理程序結構。相反,Request參數可作為結構成員和Context,實現ResponseWriter所需要的方法,故而就讓它自身就嵌入了原來的ResponseWriter。你從函數返回字符串(如果有的話)只是簡單的追加到了response上。

這是一個很好的設計選擇,我認為它能迎合Go的理念。盡管你得到一個不錯的更高級別的API,但你不必犧牲對請求處理的底層控制。

現在開始

Go的HTTP庫基礎設施,盡管增長迅速,卻仍然有一些空白需要填補。但是我們需要注意的最後一件事是碎片與惱人的不兼容性,這是由於糟糕的設計和實際上帶走許多功能的抽象所導致。依我之見,擁抱和支持標准的Go HTTP設施就是,最直接地擁有功能化和模塊化的第三方HTTP工具。

Copyright © Linux教程網 All Rights Reserved