为REST API编写客户端不仅可以帮助你更好地理解相关API,还可以为使用该API的所有应用程序提供有用的工具。本节将探索构建客户端并展示一些在日常开发中可以使用的策略。

本节我们假设身份验证由基本auth处理,同时也支持token令牌。为简单起见,假设我们的API公开了一个端点GetGoogle(),该端点将执行GET获得的状态码返回给https//www.google.com。

实践

建立 client.go:

package rest

import "net/http"

// APIClient是我们自定义的client
type APIClient struct {
    *http.Client
}

// NewAPIClient 使用自定义的Transport初始化client
func NewAPIClient(username, password string) *APIClient {
    t := http.Transport{}
    return &APIClient{
        Client: &http.Client{
            Transport: &APITransport{
                Transport: &t,
                username:  username,
                password:  password,
            },
        },
    }
}

// GetGoogle 是一个API调用 我们抽象出API操作
func (c *APIClient) GetGoogle() (int, error) {
    resp, err := c.Get("http://www.google.com")
    if err != nil {
        return 0, err
    }
    return resp.StatusCode, nil
}

建立 transport.go:

package rest

import "net/http"

// APITransport 为每个请求执行SetBasicAuth函数
// 实现了RoundTripper接口
type APITransport struct {
    *http.Transport
    username, password string
}

// RoundTrip 在默认传输之前添加基础的auth
func (t *APITransport) RoundTrip(req *http.Request) (*http.Response, error) {
    req.SetBasicAuth(t.username, t.password)
    return t.Transport.RoundTrip(req)
}

建立 exec.go:

package rest

import "fmt"

// Exec 创建API客户端并使用其GetGoogle方法,然后打印结果
func Exec() error {
    c := NewAPIClient("username", "password")

    StatusCode, err := c.GetGoogle()
    if err != nil {
        return err
    }
    fmt.Println("Result of GetGoogle:", StatusCode)
    return nil
}

建立 main.go:

package main

import "github.com/agtorre/go-cookbook/chapter6/rest"

func main() {
    if err := rest.Exec(); err != nil {
        panic(err)
    }
}

这会输出:

Result of GetGoogle: 200

说明

本节演示了如何使用Transport接口隐藏诸如身份验证,令牌刷新等逻辑。它还演示了通过方法公开API调用。 如果我们需要实现用户API这样的东西,可以考虑:

type API interface{
    GetUsers() (Users, error)
    CreateUser(User) error
    UpdateUser(User) error
    DeleteUser(User)
}

如果你已经读过第5章的”创建存储接口以实现数据可移植性”,会发现可以考虑使用同样的方式进行思考。通过接口,特别是常见的接口,如RoundTripper接口,这种组合为编写API提供了很大的灵活性。此外,像我们之前所做的那样编写顶级接口并直接传递接口而不是client可能很有用。

最后编辑: kuteng  文档更新时间: 2021-01-03 15:03   作者:kuteng