选择了一个侧面项目(围绕第三方API构建包装器),我被困住了。我正在使用sling撰写我的HTTP请求。
因此,客户的部分内容如下:
type Client struct {
// some services etc..
sling *sling.Sling <-- this is initialized with *http.Client
}
func NewClient(httpClient *http.Client) *Client {
sling := sling.New().Client(httpClient).Base(BaseURL)
}
//....
我遵循与go-github和go-twitter相同的原则,我的库不应该处理身份验证,而是使用golangs oauth1 / 2包。
由于API提供应用程序和用户级别身份验证,而某些工作流程需要初始应用程序级别身份验证,然后需要用户级别身份验证,我的问题是,如果有任何方法可以更改*http.Transport
以便更改基于客户端的身份验证标头。
到目前为止,我还没有找到办法。
答案 0 :(得分:4)
http.Client
有一个Transport
字段,您可以使用该字段“根据客户端更改身份验证标头”,如果这是您想要的。 Transport
字段的类型为http.RoundTripper
,这是一个方法接口,因此您需要做的就是使用RoundTrip
方法的实现来定义传输。
type MyTransport struct {
apiKey string
// keep a reference to the client's original transport
rt http.RoundTripper
}
func (t *MyTransport) RoundTrip(r *http.Request) (*http.Response, error) {
// set your auth headers here
r.Header.Set("Auth", t.apiKey)
return t.rt.RoundTrip(r)
}
现在,您可以使用此类型的实例在Transport
上设置http.Client
字段。
var client *http.Client = // get client from somewhere...
// set the transport to your type
client.Transport = &MyTransport{apiKey: "secret", tr: client.Transport}
根据您获取客户端的方式和位置,可能尚未设置其Transport
字段,因此在这种情况下确保您的类型使用默认传输可能是个好主意。
func (t *MyTransport) transport() http.RoundTripper {
if t.rt != nil {
return t.rt
}
return http.DefaultTransport
}
// update your method accordingly
func (t *MyTransport) RoundTrip(r *http.Request) (*http.Response, error) {
// set your auth headers here
r.Header.Set("Auth", t.apiKey)
return t.transport().RoundTrip(r)
}
值得注意的是,Go documentation建议不要修改*http.Request
方法中的RoundTrip
,以便您可以执行的操作以及go-github打包的内容链接到正在做的,是创建请求的副本,在其上设置auth标头,并将其传递给基础Transport
。见这里:https://github.com/google/go-github/blob/master/github/github.go#L841-L875