在Go中将表单值附加到GET/POST请求 [英] Appending form value to GET/POST Requests in Go
问题描述
我想定义一个 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屋!