go 自定义http.Client – 动态修改请求Body
前言
在对接Alexa Smart Home时,有的请求Payload中需要传入Access Token,但是这个Token是由OAuth2 Client管理的,封装Payload时并不知道Access Token。
所以使用自定义RoundTripper,在请求前取出Header里的token,修改body,实现动态修改payload。
原理
go中可以使用http.DefaultClient进行http请求,也可以自己创建http.Client,传入自定义Transport可以实现对request的处理。
http.Client
// A Client is an HTTP client. Its zero value (DefaultClient) is a // usable client that uses DefaultTransport. // // The Client"s Transport typically has internal state (cached TCP // connections), so Clients should be reused instead of created as // needed. Clients are safe for concurrent use by multiple goroutines. // // A Client is higher-level than a RoundTripper (such as Transport) // and additionally handles HTTP details such as cookies and // redirects. // // When following redirects, the Client will forward all headers set on the // initial Request except: // // • when forwarding sensitive headers like "Authorization", // "WWW-Authenticate", and "Cookie" to untrusted targets. // These headers will be ignored when following a redirect to a domain // that is not a subdomain match or exact match of the initial domain. // For example, a redirect from "foo.com" to either "foo.com" or "sub.foo.com" // will forward the sensitive headers, but a redirect to "bar.com" will not. // // • when forwarding the "Cookie" header with a non-nil cookie Jar. // Since each redirect may mutate the state of the cookie jar, // a redirect may possibly alter a cookie set in the initial request. // When forwarding the "Cookie" header, any mutated cookies will be omitted, // with the expectation that the Jar will insert those mutated cookies // with the updated values (assuming the origin matches). // If Jar is nil, the initial cookies are forwarded without change. // type Client struct { // Transport specifies the mechanism by which individual // HTTP requests are made. // If nil, DefaultTransport is used. Transport RoundTripper // CheckRedirect specifies the policy for handling redirects. // If CheckRedirect is not nil, the client calls it before // following an HTTP redirect. The arguments req and via are // the upcoming request and the requests made already, oldest // first. If CheckRedirect returns an error, the Client"s Get // method returns both the previous Response (with its Body // closed) and CheckRedirect"s error (wrapped in a url.Error) // instead of issuing the Request req. // As a special case, if CheckRedirect returns ErrUseLastResponse, // then the most recent response is returned with its body // unclosed, along with a nil error. // // If CheckRedirect is nil, the Client uses its default policy, // which is to stop after 10 consecutive requests. CheckRedirect func(req *Request, via []*Request) error // Jar specifies the cookie jar. // // The Jar is used to insert relevant cookies into every // outbound Request and is updated with the cookie values // of every inbound Response. The Jar is consulted for every // redirect that the Client follows. // // If Jar is nil, cookies are only sent if they are explicitly // set on the Request. Jar CookieJar // Timeout specifies a time limit for requests made by this // Client. The timeout includes connection time, any // redirects, and reading the response body. The timer remains // running after Get, Head, Post, or Do return and will // interrupt reading of the Response.Body. // // A Timeout of zero means no timeout. // // The Client cancels requests to the underlying Transport // as if the Request"s Context ended. // // For compatibility, the Client will also use the deprecated // CancelRequest method on Transport if found. New // RoundTripper implementations should use the Request"s Context // for cancellation instead of implementing CancelRequest. Timeout time.Duration }