CLI
Because curl is so passé
Awesomesauce. We're almost there to a functioning... thing? App? Yes. A functioning app.
The server is all deployed, let's build the cli. Start by making a new src/cli.rs
file with the following contents:
#[tokio::main]
async fn main() {
println!("Hello, world!")
}
Now we need to tell Cargo.toml
about the new binary target, so add the following to Cargo.toml
.
[[bin]]
name = "cli"
path = "src/cli.rs"
Come to think of it, we'll want some command line argument parsing too, so let's throw that dependency in there now:
cargo add clap --features derive
While we're at it, add reqwest
too. reqwest
is a http request library based on hyper
.
cargo add reqwest --features json
Great! So we'll want to basically have two commands:
Store a secret
Fetch a secret
Let's start by adding some clap
library magic. In the cli.rs
file, add this bit at the top:
use std::process::exit;
use clap::Parser;
use uuid::Uuid;
#[derive(Parser, Debug)]
struct Args {
#[arg(short, long)]
store: Option<String>,
#[arg(short, long)]
fetch: Option<Uuid>,
#[arg(short, long)]
code: Option<String>,
}
This parses command line arguments and basically accepts the flags "--store", "--fetch", and "--code".
Now, the rest of this code isn't very interesting, so I'll drop it below. Basically it checks whether you have added the store or fetch arguments, and makes the request to our server accordingly. When you write this code, remember to update the SERVER_URI
variable!
static SERVER_URI: &'static str = "https://carrier-pigeon.shuttleapp.rs";
#[tokio::main]
async fn main() {
let Args { store, fetch, code } = Args::parse();
if store.is_none() && (fetch.is_none() || code.is_none()) {
println!("You must specify either --store or --fetch and --code.");
exit(1);
}
let client = Client::new();
if store.is_some() {
let response = client
.post(format!("{}/secrets", SERVER_URI))
.json(&CreateSecretReq {
secret: store.unwrap(),
expires_at: Utc::now() + Duration::days(1),
})
.send()
.await
.expect("Received a bad response while storing secret")
.json::<CreateSecretRes>()
.await
.expect("Could not parse result from storing secret");
println!(
"Success! Share this id and code with the counterparty:
id: {id}
code: {code}
or, share this URL with the counterparty:
https://carrier-pigeon.shuttle.rs/{id}?code={code}",
id = response.id,
code = response.code
);
} else {
let response = client
.get(format!(
"{}/secrets/{}?code={}",
SERVER_URI,
fetch.unwrap(),
code.unwrap()
))
.send()
.await
.expect("Received a bad response while fetching secret")
.json::<GetSecretRes>()
.await
.expect("Could not parse result from fetching secret");
println!("{}", response.secret);
}
}
Now simply run the command to store,
cargo run --bin=cli -- --store='super secret test message'
and use the resulting id and code to fetch it
cargo run --bin=cli -- --fetch=some-long-id --code=some-medium-string
Your results should be "super secret test message". You did it!! Congratulations!!
Last updated
Was this helpful?