royalrick / weapp

微信小程序服务端 SDK (for Golang)
https://pkg.go.dev/github.com/medivhzhan/weapp/v3
Apache License 2.0
1.47k stars 281 forks source link

是否可以添加自定义 http client 的功能呢? #14

Closed huangjunwen closed 3 years ago

huangjunwen commented 5 years ago

现在库里的所有 http 请求都是直接调用 http.Get 或者 http.Post 的,如果想要在做这些请求前后做一些操作没法实现,所以希望能添加大致这样的功能:

// HTTPClient 是一个泛化的 http.Client
type HTTPClient interface {
    Do(req *http.Request) (*http.Response, error)
}

然后添加例如

LoginEx(client HTTPClient, appID, secret, code string) (lresp LoginResponse, err error)

Login 则改造成

func Login(appID, secret, code string) (lres LoginResponse, err error) {
    return LoginEx(http.DefaultClient, appID, secret, code)
}

如接受我可以提交 PR,谢谢

royalrick commented 5 years ago

想法不错👍,但是什么场景回使用到呢?

huangjunwen commented 5 years ago

我这里主要有两个场景会需要:

  1. 链路追踪(opentracing)希望也能追踪得到对外 api 请求(在这里就是微信接口)的状况,要实现这个功能需要传入 context,例如某个 http handler:
    func loginHandler(w http.ResponseWriter, r *http.Request) {
    // 目前是这样的,Login 这个操作没办法传入当前上下文 
    loginResp, err := weapp.Login(appId, appSecret, code)
    // ...
    }

若能添加自定义 HTTPClient,则我有很多方法可以实现,例如

type ctxClient struct {
    ctx context.Context
}

func (client *ctxClient) Do(req *http.Request) (*http.Response, error) {
    // 附着上下文然后请求
    return http.DefaultClient.Do(req.WithContext(client.ctx))
}

func loginHandler(w http.ResponseWriter, r *http.Request) {
    // ... 
    loginResp, err := weapp.LoginEx(&ctxClient{r.Context()}, appId, appSecret, code)
}

当然要实现这个的话还有另外一种更简单的方式,那就是直接给 Login 添加 context 参数,例如:

func loginHandler(w http.ResponseWriter, r *http.Request) {
    loginResp, err := weapp.LoginCtx(r.Context(), appId, appSecret, code)
    // ...
}
  1. 另外一个可能需要用到的是有些 api 我们希望能把它的请求和响应的原始内容记录到日志里备查(例如支付接口),这样修改全局的 DefaultClient 也不合适
chennqqi commented 3 years ago

复议,内置client每次请求都调用httpClient()创建,不能充分利用http keepalive特性

royalrick commented 3 years ago

复议,内置client每次请求都调用httpClient()创建,不能充分利用http keepalive特性

已经在筹划 v3 ,到时候会放进去;这个版本不太好改了。

royalrick commented 3 years ago

新版本v3已经添加