doukang7486 2014-12-04 18:13
浏览 55
已采纳

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

I would like to define a http.Client that automatically appends a form value to all GET/POST requests.

I naively tried implementing http.RoundTripper as copy/pasted from another library uses this technique to modify headers for every request.

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
}

This however does not work. The req.Form values map doesn't seem to exist at this stage, so I get the panic: panic: runtime error: assignment to entry in nil map

I tried adding this to the (t *Transport) RoundTrip, but no luck:

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

I've no idea what I'm doing, any tips?

EDIT: There is no point in trying to copy req.Form values in cloneRequest method, since r.Form is empty map anyway.

  • 写回答

1条回答 默认 最新

  • dongtao4787 2014-12-04 19:54
    关注

    Form, PostForm, and ParseForm() are only used when receiving a request. When sending a request, the Transport expects the data to be properly encoded.

    You have the right idea by wrapping RoundTrip, but you have to handle the encoded data yourself.

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

    or alternatively:

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

    You could also choose to check the url.Values beforehand, if you want to avoid duplicating keys. Checking the Content-Type header for multipart/form-data or application/x-www-form-urlencoded to avoid interaction with other types of queries may be a good idea too.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料