7 releases

0.1.6 Mar 19, 2024
0.1.5 Sep 24, 2023
0.1.4 Jul 20, 2023
0.1.3 Jun 12, 2023
0.1.0 Dec 31, 2022

#1130 in Network programming


Used in 2 crates

MIT license

175KB
4.5K SLoC

Crud Api

This crate provides a framework to generate an executable to manipulate your HTTP API from CLI.

The apps using this lib can replace your curl queries when you need to access to your favorite API.

Features

API:

  • data are encoded in JSON. It don't support XML, grpc, ...
  • output can be formated on json, yaml, toml, csv or tsv
  • output stream on stdout or in a file

Tutorial

Let's create an CLI for jsonplaceholder API. For the impatients, the whole code of this example can be found in examples/jsonplaceholder_api.rs

First add these dependencies to Cargo.toml:

[dependencies]
log = "0.4"
pretty_env_logger = "0.5"
clap = "4.3"
crud-api = {version = "0.1", path="../crud/crud-api", default-features=false, features=["toml","json","yaml"]}
crud-auth = {version = "0.1", path="../crud/crud-auth"}
crud-auth-bearer = {version = "0.1", path="../crud/crud-auth-bearer"}
hyper = { version = "0.14", features = ["client","http1"] }
hyper-tls = "0.5"
miette = { version = "5.9", features = ["fancy"] }
tokio = { version = "1", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
# To force static openssl
openssl = { version = "0.10", features = ["vendored"] }

Now, create a minimal runner stucture and a main function. ApiRun on JSONPlaceHolder derives all the CLI.

use crud_api::ApiRun;
use crud_auth::CrudAuth;
use crud_auth_no_auth::Auth;
use miette::{IntoDiagnostic, Result};

#[derive(ApiRun)]
struct JSONPlaceHolder;

#[tokio::main]
async fn main() -> Result<()> {
  JSONPlaceHolder::run().await
}

crud_api_endpoint::ApiRun accepts some parameters. They are documented in crud_api_endoint crate. Let's customize our CLI with a base_url for our API, a name used in the documentation and the settings. qualifier and organisation is used to compute the settings location and env_prefix is the prefix of the environment variables

#[derive(ApiRun)]
#[api(infos(
  base_url = "http://jsonplaceholder.typicode.com",
  name = "jsonplaceholder",
  qualifier = "com",
  organisation = "typicode",
  env_prefix = "JSONPLACEHOLDER"
))]
struct JSONPlaceHolder;

Before creating the first endpoint we need to describe its output structure.

use serde::{Deserialize, Serialize};
#[derive(Debug, Default, Deserialize, Serialize)]
struct Post {
  id: u32,
  #[serde(rename = "userId")]
  user_id: u32,
  title: String,
  body: String,
}

Now, we can declare the endpoint. The minimal parameters are:

use crud_api::Api;
#[derive(Api, Debug, Default, Deserialize, Serialize)]
#[api(
  endpoint(
    route = "/posts",
    cli_route = "/post",
    multiple_results,
  ))]
struct Post {
  id: u32,
  #[serde(rename = "userId")]
  user_id: u32,
  title: String,
  body: String,
}

We can create more complex enpoint. Let's create an edit route.

  • The route parameter takes a post's id argument. This argument should be present in the cli_route.
  • the HTTP method is set with the method parameter.
  • Some help can be provided via the parameters cli_help and cli_long_help.
  • the payload is described by the struct declared with the payload_struct. The query parameter can be add with the query_struct parameter.

In this step, the payload structure is PostCreate (the same structure is used for both creation and update). PostCreate derives ApiInput. All PostCreate fields parameters are describe in the crud_api_endpoint::ApiInputConfig structs.

use crud_api::{Api, ApiInput};
#[derive(Api, Debug, Default, Deserialize, Serialize)]
#[api(
  endpoint(
    route = "/posts",
    cli_route = "/post",
    multiple_results,
  ),
  endpoint(
    route = "/posts/{id}",
    method = "PUT",
    payload_struct = "PostCreate",
    cli_route = "/post/{id}/replace",
    cli_help = "Update a Posts (replace the whole post)"
  )
)]
struct Post {
  id: u32,
  #[serde(rename = "userId")]
  user_id: u32,
  title: String,
  body: String,
}

#[derive(Debug, ApiInput, Default, Serialize, Deserialize)]
#[allow(dead_code, non_snake_case)]
struct PostCreate {
  #[api(long = "user-id")]
  userId: u32,
  #[api(no_short, help = "Title of the post")]
  title: String,
  #[api(no_short)]
  body: String,
}

Output Customization

Tables

Results arrays are formatted using the crate crud-tidy-viewer. The available table column options are:

  • table_skip: don't display this field in the table.
  • table_format: format this field in table.
    • date formatter: date(format = "%Y-%m-%d %H:%M:%S")

Pretty Structures

The crate crud-pretty-struct can format a single (json) struct.

Dependencies

~23–36MB
~580K SLoC