Merge pull request #2 from ChristopherBiscardi/brp-client-example-ureq

simplify client for more likely use case
This commit is contained in:
Matty 2024-09-15 11:49:42 -04:00 committed by GitHub
commit 14161a44e4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 12 additions and 79 deletions

View file

@ -385,6 +385,7 @@ smol-macros = "0.1"
smol-hyper = "0.1"
anyhow = "1"
macro_rules_attribute = "0.2"
ureq = {version = "2.10.1", features=["json"]}
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
wasm-bindgen = { version = "0.2" }

View file

@ -1,20 +1,9 @@
//! A simple command line client that allows issuing queries to a remote Bevy
//! app via the BRP.
use std::process;
use anyhow::Result as AnyhowResult;
use argh::FromArgs;
use bevy::remote::{DEFAULT_ADDR, DEFAULT_PORT};
use http_body_util::BodyExt as _;
use hyper::client::conn::http1;
use hyper::header::HOST;
use hyper::Request;
use macro_rules_attribute::apply;
use serde_json::Value;
use smol::{net::TcpStream, Executor};
use smol_hyper::rt::FuturesIo;
use smol_macros::main;
/// Struct containing the command-line arguments that can be passed to this example.
/// The components are passed by their full type names positionally, while `host`
@ -43,85 +32,28 @@ struct Args {
}
/// The application entry point.
#[apply(main!)]
async fn main(executor: &Executor<'_>) -> AnyhowResult<()> {
fn main() -> AnyhowResult<()> {
// Parse the arguments.
let args: Args = argh::from_env();
// Create the URL. We're going to need it to issue the HTTP request.
let host_part = format!("{}:{}", args.host, args.port);
let url = format!("https://{}/", host_part)
.parse::<hyper::Uri>()
.unwrap();
let url = format!("http://{}/", host_part);
// Create our `smol` TCP stream.
let stream = TcpStream::connect(host_part).await.unwrap();
// Create a HTTP 1.x connection.
let (mut sender, connection) = http1::handshake::<_, String>(FuturesIo::new(stream))
.await
.unwrap();
let brp_request = format!(
r#"
{{
let res = ureq::post(&url)
.send_json(ureq::json!({
"jsonrpc": "2.0",
"id": 1,
"method": "bevy/query",
"params": {{
"data": {{
"components": [{}]
}}
}}
}}
"#,
args.components
.into_iter()
.map(|comp| format!("\"{comp}\""))
.reduce(|a, b| format!("{a}, {b}"))
.unwrap_or_else(String::new)
);
// Connect.
executor
.spawn(async move {
if let Err(error) = connection.await {
die(&format!("Failed to connect: {}", error));
"params": {
"data": {
"components": args.components
}
})
.detach();
}
}))?
.into_json::<serde_json::Value>()?;
// We're connected, so build the HTTP request.
let authority = url.authority().unwrap();
let http_request = Request::builder()
.uri(&url)
.header(HOST, authority.as_str())
.body(brp_request)
.unwrap();
let response = match sender.send_request(http_request).await {
Ok(response) => response,
Err(error) => die(&format!("Failed to send request: {}", error)),
};
let body = match response.collect().await {
Ok(body) => body.to_bytes(),
Err(error) => die(&format!("Failed to receive data: {}", error)),
};
let response: Value = match serde_json::from_slice(&body) {
Ok(response) => response,
Err(error) => die(&format!("Failed to parse response as JSON: {}", error)),
};
// Just print the JSON to stdout.
println!("{}", serde_json::to_string_pretty(&response).unwrap());
println!("{:#}", res);
Ok(())
}
/// Exits with an error message.
fn die(message: &str) -> ! {
eprintln!("{}", message);
process::exit(1);
}