c2ea0b4704
We introduce a fork of internal/httpx, named internal/httpapi, where there is a clear split between the concept of an API endpoint (such as https://0.th.ooni.org/) and of an API descriptor (such as using `GET` to access /api/v1/test-list/url). Additionally, httpapi allows to create a SequenceCaller that tries to call a given API descriptor using multiple API endpoints. The SequenceCaller will stop once an endpoint works or when all the available endpoints have been tried unsuccessfully. The definition of "success" is the following: we consider "failure" any error that occurs during the HTTP round trip or when reading the response body. We DO NOT consider "failure" errors (1) when parsing the input URL; (2) when the server returns >= 400; (3) when the server returns a string that does not parse as valid JSON. The idea of this classification of failures is that we ONLY want to retry when we see what looks like a network error that may be caused by (collateral or targeted) censorship. We take advantage of the availability of this new package and we refactor web_connectivity@v0.4 and web_connectivity@v0.5 to use a SequenceCaller for calling the web connectivity TH API. This means that we will now try all the available THs advertised by the backend rather than just selecting and using the first one provided by the backend. Because this diff is designed to be backported to the `release/3.16` branch, we have omitted additional changes to always use httpapi where we are currently using httpx. Yet, to remind ourselves about the need to do that, we have deprecated the httpx package. We will rewrite all the code currently using httpx to use httpapi as part of future work. It is also worth noting that httpapi will allow us to refactor the backend code such that (1) we remove code to select a backend URL endpoint at the beginning and (2) we try several endpoints. The design of the code is such that we can add to the mix some endpoints using as `http.Client` a special client using a tunnel. This will allow us to automatically fallback backend queries. Closes https://github.com/ooni/probe/issues/2353. Related to https://github.com/ooni/probe/issues/1519. |
||
---|---|---|
.. | ||
atomicx | ||
bytecounter | ||
cmd | ||
database | ||
engine | ||
experiment/webconnectivity | ||
fsx | ||
geoipx | ||
httpapi | ||
httpx | ||
humanize | ||
kvstore | ||
legacy/assetsdir | ||
logx | ||
measurex | ||
measurexlite | ||
mlablocate | ||
mlablocatev2 | ||
model | ||
multierror | ||
netxlite | ||
oonirun | ||
platform | ||
ptx | ||
randx | ||
registry | ||
runtimex | ||
scrubber | ||
shellx | ||
stuninput | ||
testingx | ||
torlogs | ||
tracex | ||
tunnel | ||
tutorial | ||
version | ||
README.md |
Directory github.com/ooni/probe-cli/internal
This directory contains private Go packages.
Useful commands
You can read the Go documentation of a package by using go doc -all
.
For example:
go doc -all ./internal/netxlite
You can get a graph of the dependencies using kisielk/godepgraph.
For example:
godepgraph -s -novendor -p golang.org,gitlab.com ./internal/engine | dot -Tpng -o deps.png
You can further tweak which packages to exclude by appending
prefixes to the list passed to the -p
flag.
Tutorials
The tutorial package contains tutorials on writing new experiments, using measurements libraries, and networking code.
Network extensions
This section briefly describes the overall design of the network
extensions (aka netx
) inside ooni/probe-cli
. In OONI, we have
two distinct but complementary needs:
-
speaking with our backends or accessing other services useful to bootstrap OONI probe and perform measurements;
-
implementing network experiments.
We originally implemented these functionality into a separate
repository: ooni/netx. The
original design document
still provides a good overview of the problems we wanted to solve.
The newer dd-002-step-by-step.md
design document describes the current architecture (as of 2022-06-17)
and the future trajectory for netx
.
The general idea of netx
has always been to provide interfaces replacing
standard library objects that we could further wrap to perform network
measurements without deviating from the normal APIs expected by Go programmers.
For example,
type Dialer interface {
DialContext(ctx context.Context, network, address string) (net.Conn, error)
}
is a generic dialer that could be a &net.Dialer{}
but could also be a
saving dialer that saves the results of dial events. So, you could write
something like:
saver := &Saver{}
var dialer Dialer = NewDialer()
dialer = saver.WrapDialer(dialer)
conn, err := dialer.DialContext(ctx, network, address)
events := saver.ExtractEvents()
In short, with the original netx
you could write measurement code
resembling ordinary Go code but you could also save network events
from which to derive whether there was censorship.
Since then, the architecture itself has evolved and netx
has been
merged into ooni/probe-engine
and later ooni/probe-cli
. As of
2022-06-06, these are the fundamental netx
packages:
-
model/netx.go: contains the interfaces and structs patterned after the Go standard library used by
netx
; -
netxlite: implements error wrapping (i.e., mapping Go errors to OONI errors), enforces timeouts, and generally ensures that we're using a stdlib-like network API that meet all our constraints and requirements (e.g., logging);
-
bytecounter: provides support for counting the number of bytes consumed by network interactions;
-
multierror: defines an
error
type that contains a list of errors for representing the results of operations where multiple sub-operations may fail (e.g., TCP connect fails for all the IP addresses associated with a domain name); -
tracex: support for collecting events during operations such as TCP connect, QUIC handshake, HTTP round trip. Collecting events allows us to analyze such events and determine whether there was blocking. This measurement strategy is called tracing because we wrap fundamental types (e.g., a dialer or an HTTP transport) to save the result of each operation into a "list of events" type called `Saver;
-
engine/netx: code surviving from the original
netx
implementation that we're still using for measuring. Issue ooni/probe#2121 describes a slow refactoring process where we'll move code outside ofnetx
and insidenetxlite
or other packages. We are currently experimenting with step-by-step measurements, an alternative measurement approach where we break down operations in simpler building blocks. This alternative approach may eventually makenetx
obsolete.