将表单值附加到Go中的GET / POST请求

时间:2014-12-04 18:13:10

标签: go

我想定义一个http.Client,它会自动将表单值附加到所有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)

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

编辑:尝试在req.Form方法中复制cloneRequest值没有意义,因为r.Form无论如何都是空地图。

1 个答案:

答案 0 :(得分:2)

FormPostFormParseForm()仅在收到请求时使用。发送请求时,传输期望数据被正确编码。

通过包装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-Typemultipart/form-data的{​​{1}}标头以避免与其他类型的查询进行互动也是一个好主意。