feat(ooapi): add toplevel client and simplify API (#248)
* feat(ooapi): add toplevel client and simplify API This diff should simplify using ooapi from other packages by adding more abstraction that wraps the existing code. Part of https://github.com/ooni/probe/issues/1355. * fix(ooapi): use correct comment for cloners See https://github.com/ooni/probe-cli/pull/248#discussion_r590663843 * fix(ooapi): make sure the documentation is current See https://github.com/ooni/probe-cli/pull/248#discussion_r590665773 * fix(ooapi): automate copying APIs See https://github.com/ooni/probe-cli/pull/248#discussion_r590665837 * feat(ooapi): add unit tests for clientcall.go See https://github.com/ooni/probe-cli/pull/248#discussion_r590666297 * fix(ooapi): rewrite integration tests to use toplevel API See https://github.com/ooni/probe-cli/pull/248#discussion_r590665084
This commit is contained in:
parent
c22828d369
commit
28ce79eff1
33 changed files with 2090 additions and 795 deletions
|
|
@ -1,108 +1,19 @@
|
|||
// Package ooapi contains clients for the OONI API. We
|
||||
// automatically generate the code in this package from
|
||||
// the apimodel and internal/generator packages. For
|
||||
// each OONI API, we define up to three data structures:
|
||||
// Package ooapi contains a client for the OONI API. We
|
||||
// automatically generate the code in this package from the
|
||||
// apimodel and internal/generator packages.
|
||||
//
|
||||
// 1. a data structure representing the API;
|
||||
// Usage
|
||||
//
|
||||
// 2. a caching data structure, if the API
|
||||
// supports caching;
|
||||
// You need to create a Client. Make sure you set all
|
||||
// the mandatory fields. You will then have a function
|
||||
// for every supported OONI API. This function will
|
||||
// take in input a context and a request. You need to
|
||||
// fill the request, of course. The return value is
|
||||
// either a response or an error.
|
||||
//
|
||||
// 3. an auto-login data structure, if the API
|
||||
// requires login.
|
||||
//
|
||||
// The rest of this documentation page describes these
|
||||
// three data structures and the design and architecture
|
||||
// of this package. Refer to subpackages for more
|
||||
// information on how to specify an API.
|
||||
//
|
||||
// API data structure
|
||||
//
|
||||
// For each API, this package defines a data structure
|
||||
// representing the API. For example, for the TorTargets API,
|
||||
// we define the TorTargetsAPI data structure.
|
||||
//
|
||||
// The API data structure defines a method named Call that
|
||||
// allows calling the specified API. Call takes as arguments
|
||||
// a context and the request for the API and returns the
|
||||
// API response or an error.
|
||||
//
|
||||
// Request and response messages live inside the apimodel
|
||||
// subpackage. We name them after the API. Thus, for
|
||||
// the TorTargets API, the request is TorTargetsRequest,
|
||||
// and the response is TorTargetsResponse.
|
||||
//
|
||||
// API data structures are cheap to create and do not
|
||||
// mutate. They should be used in place and then forgotten
|
||||
// off once the API call is complete.
|
||||
//
|
||||
// Unless explicitly indicated, the zero value of every
|
||||
// API data structure is a valid API data structure.
|
||||
//
|
||||
// In terms of dependencies, APIs certainly need an http.Client
|
||||
// to communicate with the OONI backend. To represent such a
|
||||
// client, we use the HTTPClient interface. If you do not tell
|
||||
// an API which http.Client to use, we will default to the
|
||||
// standard library's http.DefaultClient.
|
||||
//
|
||||
// An API also depends on a JSONCodec. That is, on a data
|
||||
// structures that encodes data to/from JSON. If you do not
|
||||
// specify explicitly a JSONCodec, we will use the Go
|
||||
// standard library's JSON implementation.
|
||||
//
|
||||
// When an API requires authentication, you need to tell
|
||||
// it which authentication token to use. This gives you
|
||||
// control over obtaining the token and is the low-level
|
||||
// way of interacting with authenticated APIs. We recommend
|
||||
// using the auto-login wrappers instead (see below).
|
||||
//
|
||||
// Authenticated APIs also define the WithToken method. This
|
||||
// method takes as argument a token and returns a copy of the
|
||||
// original API using the given token. We use this method
|
||||
// to implement auto-login wrappers.
|
||||
//
|
||||
// For each API, we also define two interfaces:
|
||||
//
|
||||
// 1. the Caller interface represents the possibility of
|
||||
// calling a specific API with the correct arguments;
|
||||
//
|
||||
// 2. the Cloner interface represents the possibility of
|
||||
// calling WithToken on the given API.
|
||||
//
|
||||
// They abstract the interaction between the API type and
|
||||
// its caching and auto-login wrappers.
|
||||
//
|
||||
// Caching
|
||||
//
|
||||
// If an API supports caching, we define a type whose name
|
||||
// ends in Cache. The TorTargets API cache, for example,
|
||||
// is TorTargetsCache. These caching types wrap the API type
|
||||
// and provide the caching functionality.
|
||||
//
|
||||
// Because the cache needs to read from and write to the
|
||||
// disk, a caching type needs a KVStore. A KVStore is
|
||||
// an interface that allow you to bind a specific key to
|
||||
// a given blob of bytes and to retrieve such bytes later.
|
||||
//
|
||||
// Caches use the gob data format from the Go standard
|
||||
// library (`encoding/gob`). We abstract this dependency
|
||||
// using the GobCodec interface. By default, when you
|
||||
// do not specify a GobCodec we use the implementation
|
||||
// of gob from the Go standard library.
|
||||
//
|
||||
// See the example describing caching for more information
|
||||
// on how to use caching.
|
||||
//
|
||||
// Auto-login
|
||||
//
|
||||
// If an API supports auto-login, we define a type whose
|
||||
// name ends with WithLogin. The TorTargets auto-login struct,
|
||||
// for example, is called TorTargetsAPIWithLogin.
|
||||
//
|
||||
// Auto-login wrappers need to store persistent data. We
|
||||
// use a KVStore for that (see above). We encode login data
|
||||
// using JSON. To this end, we use a JSONCodec (also
|
||||
// described above).
|
||||
// If an API requires login, we will automatically
|
||||
// perform the login. If an API uses caching, we will
|
||||
// automatically use the cache.
|
||||
//
|
||||
// See the example describing auto-login for more information
|
||||
// on how to use auto-login.
|
||||
|
|
@ -142,22 +53,4 @@
|
|||
// The ./internal/generator contains code to generate most
|
||||
// code in this package. In particular, the spec.go file is
|
||||
// the specification of the APIs.
|
||||
//
|
||||
// Notable generated files
|
||||
//
|
||||
// - apis.go: contains APIs (e.g., TorTargetsAPI);
|
||||
//
|
||||
// - caching.go: contains caching wrappers for every API
|
||||
// that declares that it needs a cache (e.g., TorTargetsCache);
|
||||
//
|
||||
// - callers.go: contains Callers;
|
||||
//
|
||||
// - cloners.go: contains the Cloners;
|
||||
//
|
||||
// - login.go: contains auto-login wrappers (e.g.,
|
||||
// TorTargetsAPIWithLogin);
|
||||
//
|
||||
// - requests.go: contains code to generate http.Requests.
|
||||
//
|
||||
// - responses.go: code to parse http.Responses.
|
||||
package ooapi
|
||||
|
|
|
|||
Loading…
Reference in a new issue