Simone Basso 55bdebe8b2
engine/ooapi: autogenerated API with login and caching (#234)
* internal/engine/ooapi: auto-generated API client

* feat: introduce the callers abstraction

* feat: implement API caching on disk

* feat: implement cloneWithToken when we require login

* feat: implement login

* fix: do not cache all APIs

* feat: start making space for more tests

* feat: implement caching policy

* feat: write tests for caching layer

* feat: add integration tests and fix some minor issues

* feat: write much more unit tests

* feat: add some more easy unit tests

* feat: add tests that use a local server

While there, make sure many fields we care about are OK.

* doc: write basic documentation

* fix: tweak sentence

* doc: improve ooapi documentation

* doc(ooapi): other documentation improvements

* fix(ooapi): remove caching for most APIs

We discussed this topic yesterday with @FedericoCeratto. The only
place where we want LRU caching is MeasurementMeta.

* feat(ooapi): improve handling of errors during login

This was also discussed yesterday with @FedericoCeratto

* fix(swaggerdiff_test.go): temporarily disable

Before I work on this, I need to tend onto other tasks.

* fix(ootest): add one more test case

We're going towards 100% coverage of this package, as it ought to be.

* feat(ooapi): test cases for when the probe clock is off

* fix(ooapi): change test to have 100% unittest coverage

* feat: sync server and client APIs definition

Companion PR: https://github.com/ooni/api/pull/218

* fix(ooapi): start testing again against API

* fix(ooapi): only generate each file once

* chore: set version to 3.7.0-alpha

While there, make sure we don't always skip a currently failing
riseupvpn test, and slightly clarify the readme.

* fix(kvstore): less scoped error message
2021-03-04 11:51:07 +01:00

137 lines
3.7 KiB
Go

package main
import "github.com/ooni/probe-cli/v3/internal/engine/ooapi/apimodel"
// URLPath describes a URLPath.
type URLPath struct {
// IsTemplate indicates whether Value contains a template. A future
// version of this implementation will automatically deduce that.
IsTemplate bool
// Value is the value of the URL path.
Value string
// InSwagger indicates the corresponding name to be used in
// the Swagger specification.
InSwagger string
}
// Descriptor is an API descriptor. It tells the generator
// what code it should emit for a given API.
type Descriptor struct {
// Name is the name of the API.
Name string
// CachePolicy indicates the caching policy to use.
CachePolicy int
// RequiresLogin indicates whether the API requires login.
RequiresLogin bool
// Method is the method to use ("GET" or "POST").
Method string
// URLPath is the URL path.
URLPath URLPath
// Request is an instance of the request type.
Request interface{}
// Response is an instance of the response type.
Response interface{}
}
// These are the caching policies.
const (
// CacheNone indicates we don't use a cache.
CacheNone = iota
// CacheFallback indicates we fallback to the cache
// when there is a failure.
CacheFallback
// CacheAlways indicates that we always check the
// cache before sending a request.
CacheAlways
)
// Descriptors describes all the APIs.
//
// Note that it matters whether the requests and responses
// are pointers. Generally speaking, if the message is a
// struct, use a pointer. If it's a map, don't.
var Descriptors = []Descriptor{{
Name: "CheckReportID",
Method: "GET",
URLPath: URLPath{Value: "/api/_/check_report_id"},
Request: &apimodel.CheckReportIDRequest{},
Response: &apimodel.CheckReportIDResponse{},
}, {
Name: "CheckIn",
Method: "POST",
URLPath: URLPath{Value: "/api/v1/check-in"},
Request: &apimodel.CheckInRequest{},
Response: &apimodel.CheckInResponse{},
}, {
Name: "Login",
Method: "POST",
URLPath: URLPath{Value: "/api/v1/login"},
Request: &apimodel.LoginRequest{},
Response: &apimodel.LoginResponse{},
}, {
Name: "MeasurementMeta",
Method: "GET",
URLPath: URLPath{Value: "/api/v1/measurement_meta"},
Request: &apimodel.MeasurementMetaRequest{},
Response: &apimodel.MeasurementMetaResponse{},
CachePolicy: CacheAlways,
}, {
Name: "Register",
Method: "POST",
URLPath: URLPath{Value: "/api/v1/register"},
Request: &apimodel.RegisterRequest{},
Response: &apimodel.RegisterResponse{},
}, {
Name: "TestHelpers",
Method: "GET",
URLPath: URLPath{Value: "/api/v1/test-helpers"},
Request: &apimodel.TestHelpersRequest{},
Response: apimodel.TestHelpersResponse{},
}, {
Name: "PsiphonConfig",
RequiresLogin: true,
Method: "GET",
URLPath: URLPath{Value: "/api/v1/test-list/psiphon-config"},
Request: &apimodel.PsiphonConfigRequest{},
Response: apimodel.PsiphonConfigResponse{},
}, {
Name: "TorTargets",
RequiresLogin: true,
Method: "GET",
URLPath: URLPath{Value: "/api/v1/test-list/tor-targets"},
Request: &apimodel.TorTargetsRequest{},
Response: apimodel.TorTargetsResponse{},
}, {
Name: "URLs",
Method: "GET",
URLPath: URLPath{Value: "/api/v1/test-list/urls"},
Request: &apimodel.URLsRequest{},
Response: &apimodel.URLsResponse{},
}, {
Name: "OpenReport",
Method: "POST",
URLPath: URLPath{Value: "/report"},
Request: &apimodel.OpenReportRequest{},
Response: &apimodel.OpenReportResponse{},
}, {
Name: "SubmitMeasurement",
Method: "POST",
URLPath: URLPath{
InSwagger: "/report/{report_id}",
IsTemplate: true,
Value: "/report/{{ .ReportID }}",
},
Request: &apimodel.SubmitMeasurementRequest{},
Response: &apimodel.SubmitMeasurementResponse{},
}}