我想定义一个http.Client自动将表单值附加到所有GET / POST请求的。
http.Client
我天真地尝试将其实现http.RoundTripper为从另一个库中复制/粘贴,并使用此技术为每个请求修改标头。
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
req.Form
panic: runtime error: assignment to entry in nil map
我尝试将其添加到中(t *Transport) RoundTrip,但没有运气:
(t *Transport) RoundTrip
err := req.ParseForm() misc.PanicIf(err)
我不知道我在做什么,有什么建议吗?
编辑:尝试复制方法中的req.Form值没有意义cloneRequest,因为r.Form无论如何都是空映射。
cloneRequest
r.Form
Form,PostForm和ParseForm()仅在收到请求时使用。发送请求时,传输程序期望对数据进行正确的编码。
Form
PostForm
ParseForm()
通过包装RoundTrip,您有一个正确的主意,但是您必须自己处理编码的数据。
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- data或application/x-www-form-urlencoded避免与其他类型的查询交互也可能是一个好主意。
url.Values
Content-Type
multipart/form- data
application/x-www-form-urlencoded