ooapi

package
v3.8.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 15, 2021 License: BSD-3-Clause Imports: 18 Imported by: 0

README

Package ./internal/engine/ooapi

Automatically generated API clients for speaking with OONI servers.

Please, run go doc ./internal/engine/ooapi to see API documentation.

Documentation

Overview

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:

1. a data structure representing the API;

2. a caching data structure, if the API supports caching;

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).

See the example describing auto-login for more information on how to use auto-login.

Design

Most of the code in this package is auto-generated from the data model in ./apimodel and the definition of APIs provided by ./internal/generator/spec.go.

We keep the generated files up-to-date by running

go generate ./...

We have tests that ensure that the definition of the API used here is reasonably close to the server's one.

Testing

The following command

go test ./...

will, among other things, ensure that the our API spec is consistent with the server's one. Running

go test -short ./...

will exclude most (slow) integration tests.

Architecture

The ./apimodel package contains the definition of request and response messages. We rely on tagging to specify how we should encode and decode messages.

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.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrEmptyField      = errors.New("apiclient: empty field")
	ErrHTTPFailure     = errors.New("apiclient: http request failed")
	ErrJSONLiteralNull = errors.New("apiclient: server returned us a literal null")
	ErrMissingToken    = errors.New("apiclient: missing auth token")
	ErrUnauthorized    = errors.New("apiclient: not authorized")
)

Errors defined by this package. In addition to these errors, this package may of course return any other stdlib specific error.

Functions

This section is empty.

Types

type CheckInAPI

type CheckInAPI struct {
	BaseURL      string       // optional
	HTTPClient   HTTPClient   // optional
	JSONCodec    JSONCodec    // optional
	RequestMaker RequestMaker // optional
	UserAgent    string       // optional
}

CheckInAPI implements the CheckIn API.

func (*CheckInAPI) Call

Call calls the CheckIn API.

type CheckInCaller

type CheckInCaller interface {
	Call(ctx context.Context, req *apimodel.CheckInRequest) (*apimodel.CheckInResponse, error)
}

CheckInCaller represents any type exposing a method like CheckInAPI.Call.

type CheckReportIDAPI

type CheckReportIDAPI struct {
	BaseURL      string       // optional
	HTTPClient   HTTPClient   // optional
	JSONCodec    JSONCodec    // optional
	RequestMaker RequestMaker // optional
	UserAgent    string       // optional
}

CheckReportIDAPI implements the CheckReportID API.

func (*CheckReportIDAPI) Call

Call calls the CheckReportID API.

type CheckReportIDCaller

type CheckReportIDCaller interface {
	Call(ctx context.Context, req *apimodel.CheckReportIDRequest) (*apimodel.CheckReportIDResponse, error)
}

CheckReportIDCaller represents any type exposing a method like CheckReportIDAPI.Call.

type GobCodec

type GobCodec interface {
	// Encode encodes v as a serialized gob byte slice.
	Encode(v interface{}) ([]byte, error)

	// Decode decodes the serialized gob byte slice into v.
	Decode(b []byte, v interface{}) error
}

GobCodec is a Gob encoder and decoder.

type HTTPClient

type HTTPClient interface {
	// Do should work like http.Client.Do.
	Do(req *http.Request) (*http.Response, error)
}

HTTPClient is the interface of a generic HTTP client.

type JSONCodec

type JSONCodec interface {
	// Encode encodes v as a serialized JSON byte slice.
	Encode(v interface{}) ([]byte, error)

	// Decode decodes the serialized JSON byte slice into v.
	Decode(b []byte, v interface{}) error
}

JSONCodec is a JSON encoder and decoder.

type KVStore

type KVStore interface {
	// Get gets a value from the key-value store.
	Get(key string) ([]byte, error)

	// Set stores a value into the key-value store.
	Set(key string, value []byte) error
}

KVStore is a key-value store.

type LoginAPI

type LoginAPI struct {
	BaseURL      string       // optional
	HTTPClient   HTTPClient   // optional
	JSONCodec    JSONCodec    // optional
	RequestMaker RequestMaker // optional
	UserAgent    string       // optional
}

LoginAPI implements the Login API.

func (*LoginAPI) Call

Call calls the Login API.

type LoginCaller

type LoginCaller interface {
	Call(ctx context.Context, req *apimodel.LoginRequest) (*apimodel.LoginResponse, error)
}

LoginCaller represents any type exposing a method like LoginAPI.Call.

type MeasurementMetaAPI

type MeasurementMetaAPI struct {
	BaseURL      string       // optional
	HTTPClient   HTTPClient   // optional
	JSONCodec    JSONCodec    // optional
	RequestMaker RequestMaker // optional
	UserAgent    string       // optional
}

MeasurementMetaAPI implements the MeasurementMeta API.

func (*MeasurementMetaAPI) Call

Call calls the MeasurementMeta API.

type MeasurementMetaCache

type MeasurementMetaCache struct {
	API      MeasurementMetaCaller // mandatory
	GobCodec GobCodec              // optional
	KVStore  KVStore               // mandatory
}

MeasurementMetaCache implements caching for MeasurementMetaAPI.

func (*MeasurementMetaCache) Call

Call calls the API and implements caching.

type MeasurementMetaCaller

type MeasurementMetaCaller interface {
	Call(ctx context.Context, req *apimodel.MeasurementMetaRequest) (*apimodel.MeasurementMetaResponse, error)
}

MeasurementMetaCaller represents any type exposing a method like MeasurementMetaAPI.Call.

type OpenReportAPI

type OpenReportAPI struct {
	BaseURL      string       // optional
	HTTPClient   HTTPClient   // optional
	JSONCodec    JSONCodec    // optional
	RequestMaker RequestMaker // optional
	UserAgent    string       // optional
}

OpenReportAPI implements the OpenReport API.

func (*OpenReportAPI) Call

Call calls the OpenReport API.

type OpenReportCaller

type OpenReportCaller interface {
	Call(ctx context.Context, req *apimodel.OpenReportRequest) (*apimodel.OpenReportResponse, error)
}

OpenReportCaller represents any type exposing a method like OpenReportAPI.Call.

type PsiphonConfigAPI

type PsiphonConfigAPI struct {
	BaseURL      string       // optional
	HTTPClient   HTTPClient   // optional
	JSONCodec    JSONCodec    // optional
	Token        string       // mandatory
	RequestMaker RequestMaker // optional
	UserAgent    string       // optional
}

PsiphonConfigAPI implements the PsiphonConfig API.

func (*PsiphonConfigAPI) Call

Call calls the PsiphonConfig API.

func (*PsiphonConfigAPI) WithToken

func (api *PsiphonConfigAPI) WithToken(token string) PsiphonConfigCaller

WithToken returns a copy of the API where the value of the Token field is replaced with token.

type PsiphonConfigAPIWithLogin

type PsiphonConfigAPIWithLogin struct {
	API         PsiphonConfigCloner // mandatory
	JSONCodec   JSONCodec           // optional
	KVStore     KVStore             // mandatory
	RegisterAPI RegisterCaller      // mandatory
	LoginAPI    LoginCaller         // mandatory
}

PsiphonConfigAPIWithLogin implements login for PsiphonConfigAPI.

func (*PsiphonConfigAPIWithLogin) Call

Call logins, if needed, then calls the API.

type PsiphonConfigCaller

type PsiphonConfigCaller interface {
	Call(ctx context.Context, req *apimodel.PsiphonConfigRequest) (apimodel.PsiphonConfigResponse, error)
}

PsiphonConfigCaller represents any type exposing a method like PsiphonConfigAPI.Call.

type PsiphonConfigCloner

type PsiphonConfigCloner interface {
	WithToken(token string) PsiphonConfigCaller
}

PsiphonConfigCaller represents any type exposing a method like PsiphonConfigAPI.WithToken.

type RegisterAPI

type RegisterAPI struct {
	BaseURL      string       // optional
	HTTPClient   HTTPClient   // optional
	JSONCodec    JSONCodec    // optional
	RequestMaker RequestMaker // optional
	UserAgent    string       // optional
}

RegisterAPI implements the Register API.

func (*RegisterAPI) Call

Call calls the Register API.

type RegisterCaller

type RegisterCaller interface {
	Call(ctx context.Context, req *apimodel.RegisterRequest) (*apimodel.RegisterResponse, error)
}

RegisterCaller represents any type exposing a method like RegisterAPI.Call.

type RequestMaker

type RequestMaker interface {
	// NewRequest creates a new HTTP request.
	NewRequest(ctx context.Context, method, URL string, body io.Reader) (*http.Request, error)
}

RequestMaker makes an HTTP request.

type SubmitMeasurementAPI

type SubmitMeasurementAPI struct {
	BaseURL          string           // optional
	HTTPClient       HTTPClient       // optional
	JSONCodec        JSONCodec        // optional
	RequestMaker     RequestMaker     // optional
	TemplateExecutor TemplateExecutor // optional
	UserAgent        string           // optional
}

SubmitMeasurementAPI implements the SubmitMeasurement API.

func (*SubmitMeasurementAPI) Call

Call calls the SubmitMeasurement API.

type SubmitMeasurementCaller

type SubmitMeasurementCaller interface {
	Call(ctx context.Context, req *apimodel.SubmitMeasurementRequest) (*apimodel.SubmitMeasurementResponse, error)
}

SubmitMeasurementCaller represents any type exposing a method like SubmitMeasurementAPI.Call.

type TemplateExecutor

type TemplateExecutor interface {
	// Execute takes in input a template string and some piece of data. It
	// returns either a string where template parameters have been replaced,
	// on success, or an error, on failure.
	Execute(tmpl string, v interface{}) (string, error)
}

TemplateExecutor parses and executes a text template.

type TestHelpersAPI

type TestHelpersAPI struct {
	BaseURL      string       // optional
	HTTPClient   HTTPClient   // optional
	JSONCodec    JSONCodec    // optional
	RequestMaker RequestMaker // optional
	UserAgent    string       // optional
}

TestHelpersAPI implements the TestHelpers API.

func (*TestHelpersAPI) Call

Call calls the TestHelpers API.

type TestHelpersCaller

type TestHelpersCaller interface {
	Call(ctx context.Context, req *apimodel.TestHelpersRequest) (apimodel.TestHelpersResponse, error)
}

TestHelpersCaller represents any type exposing a method like TestHelpersAPI.Call.

type TorTargetsAPI

type TorTargetsAPI struct {
	BaseURL      string       // optional
	HTTPClient   HTTPClient   // optional
	JSONCodec    JSONCodec    // optional
	Token        string       // mandatory
	RequestMaker RequestMaker // optional
	UserAgent    string       // optional
}

TorTargetsAPI implements the TorTargets API.

func (*TorTargetsAPI) Call

Call calls the TorTargets API.

func (*TorTargetsAPI) WithToken

func (api *TorTargetsAPI) WithToken(token string) TorTargetsCaller

WithToken returns a copy of the API where the value of the Token field is replaced with token.

type TorTargetsAPIWithLogin

type TorTargetsAPIWithLogin struct {
	API         TorTargetsCloner // mandatory
	JSONCodec   JSONCodec        // optional
	KVStore     KVStore          // mandatory
	RegisterAPI RegisterCaller   // mandatory
	LoginAPI    LoginCaller      // mandatory
}

TorTargetsAPIWithLogin implements login for TorTargetsAPI.

func (*TorTargetsAPIWithLogin) Call

Call logins, if needed, then calls the API.

type TorTargetsCaller

type TorTargetsCaller interface {
	Call(ctx context.Context, req *apimodel.TorTargetsRequest) (apimodel.TorTargetsResponse, error)
}

TorTargetsCaller represents any type exposing a method like TorTargetsAPI.Call.

type TorTargetsCloner

type TorTargetsCloner interface {
	WithToken(token string) TorTargetsCaller
}

TorTargetsCaller represents any type exposing a method like TorTargetsAPI.WithToken.

type URLsAPI

type URLsAPI struct {
	BaseURL      string       // optional
	HTTPClient   HTTPClient   // optional
	JSONCodec    JSONCodec    // optional
	RequestMaker RequestMaker // optional
	UserAgent    string       // optional
}

URLsAPI implements the URLs API.

func (*URLsAPI) Call

Call calls the URLs API.

type URLsCaller

type URLsCaller interface {
	Call(ctx context.Context, req *apimodel.URLsRequest) (*apimodel.URLsResponse, error)
}

URLsCaller represents any type exposing a method like URLsAPI.Call.

Directories

Path Synopsis
Package apimodel describes the data types used by OONI's API.
Package apimodel describes the data types used by OONI's API.
internal
generator
Command generator generates code in the ooapi package.
Command generator generates code in the ooapi package.
openapi
Package openapi contains data structures for Swagger v2.0.
Package openapi contains data structures for Swagger v2.0.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL