RoundTripper is an interface representing the ability to execute a single HTTP transaction, obtaining the Response for a given Request.
對於http用戶端,可以使用不同的實現了 RoundTripper
介面的Transport
實現來配置它的行為
RoundTripper
有點像 http.Client
的中介軟體
介面定義
type RoundTripper interface { RoundTrip(*Request) (*Response, error)}
需要實現RoundTrip函數
type SomeClient struct {}func (s *SomeClient) RoundTrip(r *http.Request)(*Response, error) { //Something comes here...Maybe}
情境
原文: https://lanre.wtf/blog/2017/0...
實際的例子
實現http.RoundTripper
緩衝 http response的邏輯。
一個http server的實現
import ( "fmt" "net/http")func main() { // server/main.go mux := http.NewServeMux() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { // This is here so we can actually see that the responses that have been cached don't get here fmt.Println("The request actually got here") w.Write([]byte("You got here")) }) http.ListenAndServe(":8000", mux)}
http client中建立新的 http.Transport
實現 http.RoundTripper
介面
主程式main實現
https://github.com/adelowo/ro...
func main() { cachedTransport := newTransport() // cachedTransport 是自訂實現http.RoundTripper介面的 Transport client := &http.Client{ Transport: cachedTransport, Timeout: time.Second * 5, } // 每5秒清除緩衝 cacheClearTicker := time.NewTicker(time.Second * 5) //每秒請求一次,可以看出response是從緩衝擷取還是從伺服器請求 reqTicker := time.NewTicker(time.Second * 1) terminateChannel := make(chan os.Signal, 1) signal.Notify(terminateChannel, syscall.SIGTERM, syscall.SIGHUP) req, err := http.NewRequest(http.MethodGet, "http://localhost:8000", strings.NewReader("")) if err != nil { panic("Whoops") } for { select { case <-cacheClearTicker.C: // Clear the cache so we can hit the original server cachedTransport.Clear() case <-terminateChannel: cacheClearTicker.Stop() reqTicker.Stop() return case <-reqTicker.C: resp, err := client.Do(req) if err != nil { log.Printf("An error occurred.... %v", err) continue } buf, err := ioutil.ReadAll(resp.Body) if err != nil { log.Printf("An error occurred.... %v", err) continue } fmt.Printf("The body of the response is \"%s\" \n\n", string(buf)) } }}
cacheTransport 中 RoundTrip 函數實現讀取緩衝中的reponse
func (c *cacheTransport) RoundTrip(r *http.Request) (*http.Response, error) { // Check if we have the response cached.. // If yes, we don't have to hit the server // We just return it as is from the cache store. if val, err := c.Get(r); err == nil { fmt.Println("Fetching the response from the cache") return cachedResponse([]byte(val), r) } // Ok, we don't have the response cached, the store was probably cleared. // Make the request to the server. resp, err := c.originalTransport.RoundTrip(r) if err != nil { return nil, err } // Get the body of the response so we can save it in the cache for the next request. buf, err := httputil.DumpResponse(resp, true) if err != nil { return nil, err } // Saving it to the cache store c.Set(r, string(buf)) fmt.Println("Fetching the data from the real source") return resp, nil}
運行結果
links:
- https://lanre.wtf/blog/2017/0...
- https://golang.org/pkg/net/ht...
- https://www.jianshu.com/p/dd0...
- https://github.com/linki/inst...
- https://github.com/bradleyfal...
- https://github.com/adelowo/ro...
- https://gist.github.com/lidas...