2014-12-04 70 views
1

我想定義一個http.Client,它自動將表單值附加到所有GET/POST請求。將表格值附加到GET/POST請求中去

我天真地嘗試實施http.RoundTripper從另一個庫複製/粘貼使用此技術來修改每個請求的標頭。

type Transport struct { 
    // Transport is the HTTP transport to use when making requests. 
    // It will default to http.DefaultTransport if nil. 
    // (It should never be an oauth.Transport.) 
    Transport http.RoundTripper 
} 

// Client returns an *http.Client that makes OAuth-authenticated requests. 
func (t *Transport) Client() *http.Client { 
    return &http.Client{Transport: t} 
} 

func (t *Transport) transport() http.RoundTripper { 
    if t.Transport != nil { 
     return t.Transport 
    } 
    return http.DefaultTransport 
} 

func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) { 
    // To set the Authorization header, we must make a copy of the Request 
    // so that we don't modify the Request we were given. 
    // This is required by the specification of http.RoundTripper. 
    req = cloneRequest(req) 
>> req.Form.Set("foo", bar) 

    // Make the HTTP request. 
    return t.transport().RoundTrip(req) 
} 

// cloneRequest returns a clone of the provided *http.Request. 
// The clone is a shallow copy of the struct and its Header map. 
func cloneRequest(r *http.Request) *http.Request { 
    // shallow copy of the struct 
    r2 := new(http.Request) 
    *r2 = *r 
    // deep copy of the Header 
    r2.Header = make(http.Header) 
    for k, s := range r.Header { 
     r2.Header[k] = s 
    } 
    return r2 
} 

但是這不起作用。該req.Form值映射似乎並不在此階段存在,所以我得到了恐慌: panic: runtime error: assignment to entry in nil map

我嘗試添加該到(t *Transport) RoundTrip,但沒有運氣:

err := req.ParseForm() 
misc.PanicIf(err) 

我不知道我在做什麼,有什麼提示?

編輯:有是在試圖cloneRequest方法複製req.Form值是沒有意義的,因爲r.Form是空的地圖呢。

+0

是否要添加請求參數或修改表單主體? – JimB 2014-12-04 19:07:47

+0

@JimB我想將請求參數添加到每個請求。 – 2014-12-04 19:14:51

+0

但是當有'multipart/form-data'或'application/x-www-form-urlencoded'時你打算做什麼?你還想要爲url添加一個參數嗎? – JimB 2014-12-04 19:24:14

回答

2

Form,PostFormParseForm()僅在接收請求時使用。在發送請求時,Transport希望數據被正確編碼。

你有正確的想法,通過包裝RoundTrip,但你必須自己處理編碼的數據。

if req.URL.RawQuery == "" { 
    req.URL.RawQuery = "foo=bar" 
} else { 
    req.URL.RawQuery = req.URL.RawQuery + "&" + "foo=bar" 
} 

或者:

form, _ = url.ParseQuery(req.URL.RawQuery) 
form.Add("boo", "far") 
req.URL.RawQuery = form.Encode() 

您也可以選擇檢查url.Values提前,如果你想避免重複鍵。檢查Content-Type標頭爲multipart/form-dataapplication/x-www-form-urlencoded以避免與其他類型的查詢交互可能是一個好主意。

+0

工程就像一個魅力。我也處理了'content-type'。 – 2014-12-04 22:12:19