Expand description
Call your game’s own HTTPS JSON API from Bevy.
A system fires a request through HttpClient and gets a RequestId; a few frames
later exactly one answer arrives as a Bevy message: JsonResponse<T> for typed JSON
(feature json) or HttpResponse for raw bytes. The answer is the decoded value or a
BackendError: network, TLS, timeout, an HTTP status with the server’s body, a decode
error, cancelled, or shutdown on AppExit. Nothing is ever dropped silently.
Features: http (the real transport: ureq on a few worker threads, rustls with ring, and
multipart/form-data uploads with Multipart), json
(typed requests), gzip, ws (named WebSocket connections: WsClient and friends), ssh
(named SSH connections that run commands, ADMIN / DEV builds only: SshClient), sftp (file
operations on them), ssh-rsa (RSA keys for SSH). Default: http, json. No tokio unless you
enable ssh. Without http the crate still builds, and the FakeHttpTransport drives
everything in tests. The README is the full manual.
A quick start:
use bevy::prelude::*;
use bevy_net_backend::prelude::*;
use serde::Deserialize;
#[derive(Deserialize, Clone, Debug)]
struct Profile {
name: String,
level: u32,
}
fn main() {
App::new()
.add_plugins((MinimalPlugins, BackendPlugin::new(HttpConfig::new("https://api.example.com"))))
.add_json_response::<Profile>()
.add_systems(Startup, |backend: Res<HttpClient>| {
backend.get_json::<Profile>("/me");
})
.add_systems(Update, |mut answers: MessageReader<JsonResponse<Profile>>| {
for answer in answers.read() {
match &answer.result {
Ok(profile) => info!("{} is level {}", profile.name, profile.level),
Err(error) => warn!("could not load the profile: {error}"),
}
}
})
.run();
}Re-exports§
pub use http;
Modules§
- prelude
- Everything a game usually needs:
use bevy_net_backend::prelude::*;.
Structs§
- ApiKey
Header - A key in a header of your choice, e.g.
X-Api-Key: <key>. - ApiKey
Query - A key in a query parameter, e.g.
?api_key=<key>. Prefer a header where the API allows it: URLs end up in server access logs, and ureq logs the full path and query attracelevel. - Backend
Credentials - The game’s current credentials, applied to every request (except those made
without_credentials). Empty by default; the game sets it after its own login call and clears it on logout. - Backend
Plugin - The plugin. Add it once; it adds no other plugin and works under
MinimalPlugins(and even without Bevy’sTimePlugin). - Bearer
Token Authorization: Bearer <token>: Laravel Sanctum / Passport, most Node and Go APIs, JWTs.- Fake
Http Transport - An in-memory
HttpTransportfor tests: it records every request and answers from scripted routes or by hand. Clones share one state, so keep a clone to script and inspect it after inserting it: - Fake
SshTransport ssh - An in-memory
SshTransportfor tests: records every connect, command, SFTP operation, cancel and close, and answers from a script. Clones share one state. Events are delivered on the next poll (the next frame’sFirst). Never touches the network or any file. - Fake
WsTransport ws - An in-memory
WsTransportfor tests: records every link, frame and close, and answers from a script. Clones share one state. Events are delivered on the next poll (the next frame’sFirst). - Http
Client - Makes requests. A resource with shared access only (
Res<HttpClient>), so any number of systems in any schedule can use it without ordering against each other; it also works from&World. - Http
Config - The backend’s settings: a resource the plugin inserts, which the game may change at any time
(for example
set_base_urlafter reading its own settings file). - Http
Response - The answer to a raw request (
HttpClient::send,request,get): the response (status 200–299) or why not. - Http
Transport Res - The installed transport. The plugin inserts the HTTP transport (feature
http) when the app has none; insert your own (for example aFakeHttpTransport) to replace it. - InFlight
- Every request waiting for its answer, HTTP, WebSocket and SSH alike (optional read-only
tracking, e.g. for a “saving…” spinner). An HTTP request appears here in
PostUpdate(BackendSystems::Send) of the frame it was made in, a WebSocket request or SSH command in the same place (also while it waits for its connection). A request leaves it when it is answered; the answer message follows inFirst(of that frame, or of the next one for answers decided inPostUpdate, such as a cancel). - Json
Body Field json - A field in the JSON body, e.g.
{"token": "<token>", ...}, for APIs that want it there. - Json
Envelope jsonandws - The default protocol (feature
json): JSON objects in text frames. - Json
Response json - The answer to a typed JSON request (
get_json::<T>,post_json::<T>,send_json::<T>): the decodedTor why not. Register eachTonce withBackendAppExt::add_json_response. - Multipart
http - A
multipart/form-dataform: text fields and files, in order. Build it, then send it withHttpClient::post_multipart(orpost_multipart_json,send_multipart,OutgoingRequest::with_multipart). - Outgoing
Request - A request the game builds: method, path (appended to the base URL), query parameters, headers, an optional body and an optional timeout.
- Prepared
Request - A request ready for an
HttpTransport: the full URL, every header (defaults and credentials applied), the body, the timeout and the response body limit. - RawResponse
- What a server sent back: status, headers and the raw body.
- Rejection
- The error payload of a
BackendError::Rejectedanswer (with the default JSON envelope: the JSON oferrorin{"id":…,"ok":false,"error":…}). - Request
Id - Identifies one request made through
bevy_net_backend. Every answer carries the id of the request it answers, so a game can match them. - Request
Info - What a pending request is, for display (a “saving…” list, a debug overlay). Never holds a query string, header value or body.
- Russh
Transport ssh - The real
SshTransport(featuressh): russh 0.63.3 with ring for the AEAD ciphers, on one private thread with a tokio current-thread runtime, started on the first connect. The plugin inserts one unless anSshTransportResexists. - Secret
- A secret string (token, key, password) that never shows up in
Debug,Displayor this crate’s logs: both print<redacted>. Read it withexposewhere it is really needed. - Sftp
Entry sftpandssh - One entry of a directory listing.
#[non_exhaustive]: build one withnew. - Sftp
Finished sftpandssh - The one answer to an SFTP operation. Written in
First. - Sftp
Progress sftpandssh - Progress of an SFTP transfer: bytes moved so far (at most about 10 per second per transfer).
Written in
First. - SshAuth
ssh - How to log in. Several can be given (
SshTarget::with_auth); they are tried in order. Keys are the recommendation (a key file or the agent); a password and keyboard-interactive (e.g. password + a 2FA code) are opt-in for servers that need them, with values typed by the admin at runtime. There is deliberately no way to pass key bytes: keys are loaded at runtime from the admin’s machine, never baked into a binary.Debugshows the key file’s name, never its path, contents, passphrase or password. - SshClient
ssh - Opens, closes and uses named SSH connections (feature
ssh). LikeHttpClienta resource with shared access only (Res<SshClient>), so any number of systems can use it without ordering. Everything is applied inPostUpdate(BackendSystems::Send). - SshCommand
ssh - A command to run (
SshClient::run). The command line goes to the server’s shell as it is: quote arguments yourself. It may hold secrets (a token in an argument): itsDebugshows only its length, and the crate never logs it. Prefer passing secrets throughwith_stdin; a command line is visible to other users of the server in its process list. - SshConn
Id ssh - Identifies one connection attempt: each
connectof a named connection is a new one. Opaque;Displayshows it for logs. - SshConnection
Info ssh - What one connection is doing, in
SshConnections. - SshConnections
ssh - The state of every named SSH connection (read-only for the game). Every name passed to
connectgets an entry, a refused one too (Disconnectedwith the error). Only connections that are notDisconnectedcount againstSshSettings::with_max_connections; beyond 256 remembered names the oldestDisconnectedones are forgotten. - SshExit
ssh - How a command ended. A non-zero status is still
Ok: the command ran (checksuccess).#[non_exhaustive]: build one with the constructors. - SshFinished
ssh - The one answer to
SshClient::run: how the command ended, or why it did not run to its end. Written inFirst. - SshName
ssh - The name of an SSH connection (
"main","build-box", …). Cheap to clone. - SshOutput
ssh - A chunk of a command’s output, as it arrived (a chunk may end in the middle of a line or of a
UTF-8 character: join chunks before splitting lines). 0..n per command, all written before or
in the same frame as its
SshFinished.Debugshows the length only (output may hold secrets); the crate never logs output. - SshPrompt
ssh - One prompt of a keyboard-interactive round. The texts come from the server (untrusted; control
characters removed).
#[non_exhaustive]. - SshPrompt
Answers ssh - A ready-made
SshPromptResponder: answers each prompt whose text contains a given word (case-insensitive), e.g.passwordandcode. A round with a prompt nothing matches gives up.Debugshows the words, never the answers. - SshPrompt
Request ssh - One keyboard-interactive round: the server’s name and instructions and its prompts (all
server-supplied, untrusted).
#[non_exhaustive]. - SshReconnect
ssh - Automatic reconnect of an SSH connection (
SshTarget::with_reconnect; OFF unless set): exponential backoff with full jitter, as for WebSocket. A reconnect never re-runs a command: commands that were running when the connection was lost are answeredDisconnected(with their honeststarted); commands that had not been sent yet wait for the new connection. Not retried: host key, authentication, protocol (Ssh) and invalid-settings errors. The delay before attemptnis a random value in0..=min(cap, base · 2^(n-1)); the counter resets after the connection stayed up forstable_after. - SshSettings
ssh - App-wide SSH settings, given to the plugin with
BackendPlugin::with_ssh. Private fields + builder. - SshState
Changed ssh - A connection’s state changed. Written in
First. - SshTarget
ssh - One SSH server and how to reach it, given to
SshClient::connect. Private fields + builder. - SshTransport
Res ssh - The installed SSH transport. The plugin inserts a
RusshTransportwhen there is none; insert aFakeSshTransportfor tests. Connections of a transport that is removed or replaced count as lost. - Tungstenite
Transport ws - The real WebSocket transport (feature
ws): tungstenite 0.30 (no permessage-deflate) on one std thread per link, namednet-backend-ws-link#N. TLS is rustls with ring, passed explicitly, and Mozilla’s roots, exactly like the HTTP transport. No async runtime. - Ureq
Transport http - The real HTTP transport: ureq 3.4 (HTTP/1.1, blocking) with rustls (ring crypto) and the
Mozilla root certificates, on
HttpConfig::workersthreads. The plugin creates it from the config when the app has noHttpTransportRes; create one yourself to install it later. - WsClient
ws - Opens, closes and uses named WebSocket connections. Like
HttpClienta resource with shared access only (Res<WsClient>), so any number of systems can use it without ordering. Everything is applied inPostUpdate(BackendSystems::Send). - WsConnection
Info ws - What one connection is doing, in
WsConnections. - WsConnections
ws - The state of every named connection (read-only for the game).
- WsHandshake
ws - Everything a transport needs to open one link: the URL, the handshake headers (credentials
applied) and the connection’s limits. Built by the plugin;
Debugnever shows header values or the query. - WsLink
Id ws - Identifies one connection attempt (a “link”): each (re)connect of a named connection is a new
link. Opaque;
Displayshows it for logs. - WsMessage
ws - A data frame the server sent (every one, whether or not the protocol also turned it into an
answer or a push). Written in
Firstof the frame it arrived. - WsName
ws - The name of a WebSocket connection (
"main","chat", …). Cheap to clone. - WsOutgoing
ws - A request with a raw payload, for
WsClient::request_raw; the protocol wraps it (withJsonEnvelope,kindis"type"and the payload must be JSON). - WsPush
jsonandws - A typed server push (features
ws+json). - WsRaw
Response ws - The answer to
WsClient::request_raw: the response payload or why not. Exactly one per request.Debugshows the payload length only. - WsReconnect
ws - Reconnect policy: exponential backoff with full jitter, a cap and optional maximum attempts.
- WsResponse
jsonandws - The answer to a typed request: the decoded response or why not. Exactly one per request.
- WsSettings
ws - The settings of one connection, given to
WsClient::connect. Private fields + builder. - WsState
Changed ws - A connection’s state changed (or an attempt failed). Written in
First. - WsTransport
Res ws - The installed WebSocket transport. The plugin inserts a
TungsteniteTransportwhen there is none; insert aFakeWsTransportfor tests. Links of a transport that is removed or replaced count as lost (and reconnect on the new one).
Enums§
- Backend
Error - Why a request did not succeed. Every request gets exactly one answer; this is the error half.
- Backend
Systems - The plugin’s system sets, named after phases: HTTP, WebSocket (feature
ws) and SSH (featuressh) systems all run in them (in that order within a set).#[non_exhaustive]: a later version may add a set. - Config
Error - What is wrong with an
HttpConfig(fromHttpConfig::validate). - Host
KeyProblem - Why an SSH host key was refused (
BackendError::HostKey).#[non_exhaustive]. - Request
Kind - The kind of connection a pending request belongs to.
#[non_exhaustive]: later versions may add kinds. - Request
Purpose - What a request is for, so
Credentialscan treat kinds differently. 0.1.0 only makesHttprequests. - Sftp
Entry Kind sftpandssh - The kind of a directory entry.
- SftpOp
sftpandssh - One SFTP operation (what a transport receives; games use the
SshClientmethods). Remote paths are the server’s (relative paths start in the login directory).Debugshows local paths by file name only and uploads by length only. - Sftp
Outcome sftpandssh - What a finished SFTP operation produced.
#[non_exhaustive];Debugshows downloaded data by length only. - SshEvent
ssh - What a transport reports. After
Closeda connection reports nothing more; a request reports at most oneFinished/SftpFinished.Debugnever shows output bytes. - SshState
ssh - The state of one named SSH connection.
#[non_exhaustive]. - SshStream
ssh - Which output stream a chunk came from.
- WsFrame
ws - One WebSocket data frame.
Debugshows the kind and length only (a frame may hold a token). - WsIncoming
ws - What the protocol made of an incoming frame.
- WsLink
Event ws - What happened on a link. After
ClosedorFaileda link reports nothing more. - WsState
ws - The state of one named connection. A resource (
WsConnections) plus messages (WsStateChanged), not BevyStates.#[non_exhaustive].
Constants§
- DEADLINE_
GRACE - How long after its own timeout a request is answered with a timeout by the plugin, in case the transport never reports it (a stuck worker, a custom transport that forgets it).
- DEFAULT_
MAX_ BODY_ BYTES - The default limit of a response body: 10 MiB. A bigger body is answered with
BackendError::BodyTooLarge. - DEFAULT_
MULTIPART_ MAX_ BYTES http - Default limit of one encoded form (the whole request body): 32 MiB.
- DEFAULT_
MULTIPART_ MAX_ PARTS http - Default limit of parts in one form.
- DEFAULT_
SFTP_ MAX_ BYTES ssh - Default limit of one SFTP transfer (upload or download): 256 MiB.
- DEFAULT_
SFTP_ TIMEOUT ssh - Default time an SFTP operation (a whole transfer) may take.
- DEFAULT_
SSH_ COMMAND_ TIMEOUT ssh - Default time a command may run.
- DEFAULT_
SSH_ CONNECT_ TIMEOUT ssh - Default limit for connect + key exchange + host key check + authentication together.
- DEFAULT_
SSH_ MAX_ OUTPUT_ BYTES ssh - Default limit of a command’s output (stdout + stderr): 8 MiB.
- DEFAULT_
TIMEOUT - The default request timeout: 15 s for the whole call (connect, send, receive).
- DEFAULT_
WORKERS - The default number of worker threads of the HTTP transport.
- DEFAULT_
WS_ MAX_ MESSAGE_ BYTES ws - Default largest message (and frame) accepted: 1 MiB.
- DEFAULT_
WS_ READ_ TIMEOUT ws - Default read timeout of a connection thread.
- MAX_
SSH_ COMMAND_ BYTES ssh - The longest command line accepted: 64 KiB.
- MAX_
TIMEOUT - The longest timeout accepted: one hour.
- MAX_
WORKERS - The most worker threads the HTTP transport starts.
Traits§
- Backend
AppExt Appextension of this crate (implemented forApponly; sealed, so methods behind features never break an outside implementation).- Credentials
- Adds the game’s authentication to a request, right before it is sent (after the config’s default headers and the request’s own headers, so it wins over both).
- Http
Transport - Moves prepared requests to a server and results back. The plugin owns the bookkeeping (pending requests, deadlines, cancel, exit); a transport only has to deliver.
- SshPrompt
Responder ssh - Answers keyboard-interactive prompts (
SshAuth::keyboard_interactive). Called on the SSH thread: never block. Return one answer per prompt, orNoneto give up (the method then fails). Methods added later always come with a default implementation. - SshTransport
ssh - Opens SSH connections and runs requests on them. The plugin owns the bookkeeping (pending requests, deadlines, cancel, exit) and every answer; a transport only reports. All methods run on the main thread and must never block or panic.
- WsProtocol
ws - How requests and pushes are laid out in frames. Every frame also arrives raw as a
WsMessage, whatever the protocol does with it. - WsPush
Message jsonandws - A typed server push (features
ws+json): pushes of kindKINDarrive asWsPush<Self>. Register withadd_ws_push. - WsRequest
jsonandws - A typed WebSocket request (features
ws+json), sent withWsClient::requestand answered withWsResponse<Self::Response>. Register withadd_ws_request. - WsTransport
ws - Opens links and moves frames. The plugin owns reconnects, requests and every answer; a
transport only delivers.
send,closeandpollrun on the main thread and must never block. Methods added later always come with a default implementation.
Type Aliases§
- Http
Transport Result - What a transport reports for one request: the server’s answer (any status; the plugin turns
a non-2xx status into
BackendError::Status) or the error that stopped it.