Skip to main content

opentele2_browser/
lib.rs

1//! Browser HTTP header and fingerprint generation from the Apify fingerprint
2//! datapoints, based on [browserforge].
3//!
4//! The crate embeds the three Bayesian networks of
5//! `apify_fingerprint_datapoints` 0.15.0 (see `data/SOURCE.md`) and samples
6//! them exactly as browserforge's `bayesian_network.py` does, with two
7//! deliberate differences: every random draw comes from the seedable
8//! [`Rng`], and every set operation keeps first-seen order instead of
9//! Python's hash order, so a seed reproduces its output on any platform.
10//!
11//! [browserforge]: https://github.com/daijro/browserforge
12
13pub mod fingerprint;
14pub mod headers;
15mod map;
16pub mod network;
17pub mod rng;
18mod zip;
19
20pub use fingerprint::{
21    Fingerprint, FingerprintGenerator, FingerprintOptions, FingerprintOverrides,
22    NavigatorFingerprint, Screen, ScreenFingerprint, VideoCard, generate_fingerprint,
23    generate_headers,
24};
25pub use headers::{
26    Browser, HeaderGenerator, HeaderOptions, HeaderOverrides, Headers, HttpVersion, browser_of,
27    get_user_agent, pascalize,
28};
29pub use map::{OrderedMap, Restrictions, Values};
30pub use network::{BayesianNetwork, Node, fingerprint_network, header_network, input_network};
31pub use rng::Rng;
32
33/// The message browserforge raises for an unsatisfiable constraint closure.
34const TOO_RESTRICTIVE: &str = "The current constraints are too restrictive. No possible values can be found for the given constraints.";
35
36/// The message browserforge raises when no headers fit the options.
37const NO_HEADERS: &str = "No headers based on this input can be generated. Please relax or change some of the requirements you specified.";
38
39/// The message browserforge raises when no fingerprint fits the headers.
40const NO_FINGERPRINT: &str = "Cannot generate headers. User-Agent may be invalid, or screen constraints are too restrictive.";
41
42/// Errors of the crate.
43#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
44#[non_exhaustive]
45pub enum Error {
46    /// The constraints leave some node without any possible value.
47    #[error("{TOO_RESTRICTIVE}")]
48    TooRestrictive,
49    /// A constraint names a node the network does not have.
50    #[error("unknown network node {0:?}")]
51    UnknownNode(String),
52    /// A network archive is not a readable zip file.
53    #[error("malformed zip archive: {0}")]
54    Zip(String),
55    /// A network definition is not valid network JSON.
56    #[error("malformed network definition: {0}")]
57    Network(String),
58    /// Header generator options that browserforge rejects, such as a browser
59    /// whose minimum version exceeds its maximum or more than ten locales.
60    #[error("invalid header options: {0}")]
61    InvalidOptions(String),
62    /// No input sample satisfies the options, even after the permitted
63    /// relaxations.
64    #[error("{NO_HEADERS}")]
65    NoHeaders,
66    /// The generated headers carry no `User-Agent`.
67    #[error("Failed to find User-Agent in generated response")]
68    MissingUserAgent,
69    /// The fingerprint network has no sample for the generated `User-Agent`
70    /// (and, when strict, the screen constraint).
71    #[error("{NO_FINGERPRINT}")]
72    NoFingerprint,
73    /// The generated `User-Agent` names no known browser.
74    #[error("Failed to find browser in User-Agent {0:?}")]
75    UnknownBrowser(String),
76    /// An embedded JSON data file is malformed.
77    #[error("malformed embedded data: {0}")]
78    Data(String),
79    /// The operating system could not provide entropy.
80    #[error("operating system entropy unavailable: {0}")]
81    Entropy(#[source] getrandom::Error),
82}
83
84/// The crate's result type.
85pub type Result<T> = std::result::Result<T, Error>;