在Go中将表单值附加到GET/POST请求 [英] Appending form value to GET/POST Requests in Go

查看:44
本文介绍了在Go中将表单值附加到GET/POST请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想定义一个 http.Client ,该代码会自动将表单值附加到所有GET/POST请求中.

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

我天真地尝试将 http.RoundTripper 实现为从另一个库中复制/粘贴,并使用此技术为每个请求修改标头.

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
}

但是,这不起作用. req.Form 值映射在现阶段似乎不存在,所以我感到恐慌: panic:运行时错误:分配给nil映射中的条目

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

我尝试将其添加到(t * Transport)RoundTrip 中,但没有运气:

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?

尝试复制 cloneRequest 方法中的 req.Form 值没有意义,因为 r.Form 始终为空映射

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

推荐答案

Form PostForm ParseForm()仅在以下情况下使用收到请求.发送请求时,传输程序会期望对数据进行正确的编码.

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

通过包装 RoundTrip ,您有一个正确的主意,但是您必须自己处理编码的数据.

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"
}

或者:

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 ,以避免与其他类型的查询可能也是个好主意.

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.

这篇关于在Go中将表单值附加到GET/POST请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆