這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
nosurf,這是Go語言的一個CSRF跨站請求偽造(Cross-Site Request Forgery)中介軟體。編寫一個看起來簡單並且小巧的包就足以讓你愛上Go處理HTTP的方式。然而,這卻取決於我們擁抱標準的HTTP設施或者是粉碎它,犧牲可組性和模組化。
http.Handler是介面
使用特定程式設計語言編寫的web應用程式中的統一HTTP介面,如Python中的WSGI和Ruby中的Rack都是一種很好的想法,但是它們卻不總是在一起,例如,Rack在2007年出現的時候,Rails就已經很健壯並且風靡了好一陣子。
與此同時,在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工具。
轉自:http://www.oschina.net/translate/embrace-gos-http-tools
原文:http://justinas.org/embrace-gos-http-tools/