【问题标题】:Adding custom transport to a third party package将自定义传输添加到第三方包
【发布时间】:2018-07-23 07:07:47
【问题描述】:

我一直在我的 Go 应用程序中使用 GoRequest 作为包。

我使用它是因为它有助于使我需要的所有 API 调用变得更清洁 - 它缺少的一件事是我可以使用常规 http.Client 来实现对 @987654323 的出站速率限制@。

例如,在我的一个应用程序中,我使用了这个 -

type rateLimitTransport struct {
    limiter *rate.Limiter
    xport   http.RoundTripper
}

var _ http.RoundTripper = &rateLimitTransport{}

func newRateLimitTransport(r float64, xport http.RoundTripper) http.RoundTripper {
    return &rateLimitTransport{
        limiter: rate.NewLimiter(rate.Limit(r), 1),
        xport:   xport,
    }
}

func (t *rateLimitTransport) RoundTrip(r *http.Request) (*http.Response, error) {
    t.limiter.Wait(r.Context())
    return t.xport.RoundTrip(r)
}

var myClient = http.Client{
    // Use a rate-limiting transport which falls back to the default
    Transport: newRateLimitTransport(1, http.DefaultTransport),
}

这允许我创建一个客户端,即速率限制为每秒 1 个请求;每分钟 60 个请求。

我已经分叉了 GoRequest 包,并正在尝试向它添加一个名为 SetRateLimit() 的新方法,它应该将每秒速率作为参数并使用它来实现速率受限的传输。

到目前为止,我的尝试如下所示:

import (
    //...current imports
    "golang.org/x/time/rate"
)
//... Rest of the package
type rateLimitTransport struct {
    limiter *rate.Limiter
    xport   http.RoundTripper
}

var _ http.RoundTripper = &rateLimitTransport{}

func newRateLimitTransport(r float64, xport http.RoundTripper) http.RoundTripper {
    return &rateLimitTransport{
        limiter: rate.NewLimiter(rate.Limit(r), 1),
        xport:   xport,
    }
}

func (t *rateLimitTransport) RoundTrip(r *http.Request) (*http.Response, error) {
    t.limiter.Wait(r.Context())
    return t.xport.RoundTrip(r)
}

func (s *SuperAgent) SetRateLimit(limit float64) *SuperAgent {

    s.Transport = newRateLimitTransport(limit, http.DefaultTransport)
    return s
}

但是我在尝试构建时遇到错误:

不能使用 newRateLimitTransport(limit, http.DefaultTransport) (type http.RoundTripper) 作为 type *http.Transport in assignment: 需要类型断言

我已经看了好几个小时了,我不太明白这对于普通的 http.Client 是如何工作的,但不适用于这个包。

有人可以帮我解决上述问题并为此包添加速率限制吗?

更新 - SuperRequest 结构

// A SuperAgent is a object storing all request data for client.
type SuperAgent struct {
    Url               string
    Method            string
    Header            http.Header
    TargetType        string
    ForceType         string
    Data              map[string]interface{}
    SliceData         []interface{}
    FormData          url.Values
    QueryData         url.Values
    FileData          []File
    BounceToRawString bool
    RawString         string
    Client            *http.Client
    Transport         *http.Transport
    Cookies           []*http.Cookie
    Errors            []error
    BasicAuth         struct{ Username, Password string }
    Debug             bool
    CurlCommand       bool
    logger            Logger
    Retryable         struct {
        RetryableStatus []int
        RetryerTime     time.Duration
        RetryerCount    int
        Attempt         int
        Enable          bool
    }
    //If true prevents clearing Superagent data and makes it possible to reuse it for the next requests
    DoNotClearSuperAgent bool
}

【问题讨论】:

  • 能否提供SuperAgentstruct的代码?
  • @Anuruddha 现在已将此添加到问题中。

标签: http go transport roundtrip


【解决方案1】:

您看到的错误说明了问题。

不能使用 newRateLimitTransport(limit, http.DefaultTransport) (type http.RoundTripper) 作为类型 *http.Transport 赋值:需要类型 断言

SuperAgent.Transport 类型为 *http.Transport 但您正在尝试将 http.RoundTripper 分配给该字段

要解决此问题,您可以更改 SuperaAgent

type SuperAgent{
...
Transport  http.RoundTripper
...
}

【讨论】:

  • 这样做似乎破坏了对 SuperAgent.Transport 的所有引用。据我了解,http.Transporthttp.RoundTripper 的实现,我们应该可以换掉它。那么,如果不对包进行大量重写,也许真的不可能做到这一点?因为您必须提供一种方法来编辑往返程序上的代理之类的东西?
猜你喜欢
  • 1970-01-01
  • 2018-07-22
  • 1970-01-01
  • 2017-12-09
  • 1970-01-01
  • 1970-01-01
  • 2018-01-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多