diff --git a/Cargo.toml b/Cargo.toml index 07cc962..8b596dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rust-api-test" -description = "CLI for testing REST APIs" +description = "CLI tool for testing REST APIs" version = "0.1.0" edition = "2021" license = "MIT" @@ -8,10 +8,7 @@ authors = ["Prasad Jivane "] repository = "https://github.com/prasadjivane/rust-api-test" [dependencies] -reqwest = "0.11" +reqwest = { version = "0.11", features = ["blocking", "json"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" - -[dependencies.tokio] -version = "1.0" -features = ["full"] +tokio = { version = "1.0", features = ["full"] } diff --git a/README.md b/README.md index 8872f0b..fa07740 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,33 @@ - -rust-api-test +rust-api-test [github](https://github.com/prasadjivane/rust-api-test) [crates.io](https://crates.io/crates/rust-api-test) [docs.rs](https://docs.rs/crate/rust-api-test) [releases](https://github.com/prasadjivane/rust-api-test/releases) + + # rust-api-test `rust-api-test` is a Rust package that provides a command-line interface (CLI) for testing REST APIs in real-time. It allows Rust developers to easily perform HTTP GET, POST, PUT, and DELETE requests from the command line. ## Features -- Supports GET, POST, PUT, and DELETE HTTP methods. -- Allows sending JSON data in the request body. -- Provides real-time feedback on the response including status code and response body. +- Simple and easy-to-use CLI interface +- Supports GET, POST, PUT, and DELETE HTTP methods +- Real-time testing of REST APIs +- JSON request and response handling ## Installation +To use rust-api-test, you need to have Rust and Cargo installed on your system. You can install them from [rustup.rs](https://rustup.rs/). + +Once you have Rust and Cargo installed, you can install rust-api-test using Cargo: + +```bash +cargo install rust-api-test +``` + To use `rust-api-test` in your Rust project, simply add it as a dependency in your `Cargo.toml` file: ```ssh @@ -27,32 +37,32 @@ rust-api-test = "0.1.0" ## Usage -Once installed, you can use `rust-api-test` from the command line: +`rust-api-test [body]` -``` -rust-api-test -``` -Follow the on-screen instructions to select the HTTP method, enter the URL, and provide optional JSON data for POST and PUT requests. +## Examples -## Example +Get data from an API endpoint +```bash +rust-api-test GET https://jsonplaceholder.typicode.com/posts/1 +``` -```Enter your choice: -1. GET -2. POST -3. PUT -4. DELETE -5. Exit +Post data to an API endpoint +```bash +rust-api-test POST https://jsonplaceholder.typicode.com/posts userId=1 title="Test Title" body="Test Body" ``` + ## Dependencies -- reqwest - HTTP client for Rust. -- serde_json - JSON serialization and deserialization library for Rust. +- reqwest - HTTP client for Rust. + +- serde_json - JSON serialization and deserialization library for Rust. ## Contributing Contributions are welcome! If you encounter any issues or have suggestions for improvements, feel free to open an [issue](https://github.com/prasadjivane/rust-api-test/issues) or submit a [pull](https://github.com/prasadjivane/rust-api-test/pulls) request on [GitHub](https://github.com/prasadjivane). + ## License -This project is licensed under the [MIT License](https://github.com/prasadjivane/rust-api-test?tab=MIT-1-ov-file) - see the LICENSE file for details. +This project is licensed under the [MIT License](https://github.com/prasadjivane/rust-api-test?tab=MIT-1-ov-file) - see the LICENSE file for details. \ No newline at end of file diff --git a/src/api.rs b/src/api.rs new file mode 100644 index 0000000..c0dedc4 --- /dev/null +++ b/src/api.rs @@ -0,0 +1,27 @@ +use reqwest::{Client, Result}; +use serde_json::Value; +use std::collections::HashMap; + +pub async fn get(url: &str) -> Result { + let response = Client::new().get(url).send().await?; + let json = response.json().await?; + Ok(json) +} + +pub async fn post(url: &str, body: HashMap<&str, &str>) -> Result { + let response = Client::new().post(url).json(&body).send().await?; + let json = response.json().await?; + Ok(json) +} + +pub async fn put(url: &str, body: HashMap<&str, &str>) -> Result { + let response = Client::new().put(url).json(&body).send().await?; + let json = response.json().await?; + Ok(json) +} + +pub async fn delete(url: &str) -> Result { + let response = Client::new().delete(url).send().await?; + let json = response.json().await?; + Ok(json) +} diff --git a/src/main.rs b/src/main.rs index 7f959df..a948701 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,124 +1,41 @@ -use std::io; -use reqwest::{Client, Response}; -use serde::{Deserialize, Serialize}; +mod api; use std::collections::HashMap; -use serde_json::json; +use std::env; +fn main() { + let args: Vec = env::args().collect(); + if args.len() < 3 { + println!("Usage: {} [body]", args[0]); + return; + } -#[derive(Debug, Serialize, Deserialize)] -struct ApiResponse { - // Define the structure of the API response data - // This can vary depending on your API's response format - // For simplicity, let's assume it's JSON -} - -async fn get(url: &str) -> Result { - // Implement GET method - Client::new().get(url).send().await -} - -async fn post(url: &str, body: HashMap<&str, &str>) -> Result { - // Serialize the body to JSON - let body_json = json!(body); - - // Send POST request with JSON body - Client::new() - .post(url) - .header("Content-Type", "application/json") - .body(body_json.to_string()) - .send() - .await -} - -async fn put(url: &str, body: HashMap<&str, &str>) -> Result { - // Serialize the body to JSON - let body_json = json!(body); - - // Send PUT request with JSON body - Client::new() - .put(url) - .header("Content-Type", "application/json") - .body(body_json.to_string()) - .send() - .await -} - -async fn delete(url: &str) -> Result { - // Implement DELETE method - Client::new().delete(url).send().await -} - -async fn handle_response(response: Response) -> Result<(), reqwest::Error> { - // Process and display the response - let status = response.status(); - let body = response.text().await?; - - println!("Status: {}", status); - println!("Body: {}", body); - - Ok(()) -} - -#[tokio::main] -async fn main() -> Result<(), Box> { - println!("REST CLI Tester"); - - loop { - println!("Enter your choice:"); - println!("1. GET"); - println!("2. POST"); - println!("3. PUT"); - println!("4. DELETE"); - println!("5. Exit"); - - let mut choice = String::new(); - io::stdin().read_line(&mut choice)?; - - match choice.trim().parse() { - Ok(1) => { - println!("Enter URL:"); - let mut url = String::new(); - io::stdin().read_line(&mut url)?; - let response = get(&url.trim()).await?; - handle_response(response).await?; - } - Ok(2) => { - println!("Enter URL:"); - let mut url = String::new(); - io::stdin().read_line(&mut url)?; - - println!("Enter JSON Body:"); - let mut body_str = String::new(); - io::stdin().read_line(&mut body_str)?; - - let body: HashMap<&str, &str> = serde_json::from_str(&body_str)?; - let response = post(&url.trim(), body).await?; - handle_response(response).await?; - } - Ok(3) => { - println!("Enter URL:"); - let mut url = String::new(); - io::stdin().read_line(&mut url)?; - - println!("Enter JSON Body:"); - let mut body_str = String::new(); - io::stdin().read_line(&mut body_str)?; - - let body: HashMap<&str, &str> = serde_json::from_str(&body_str)?; - let response = put(&url.trim(), body).await?; - handle_response(response).await?; - } - Ok(4) => { - println!("Enter URL:"); - let mut url = String::new(); - io::stdin().read_line(&mut url)?; - let response = delete(&url.trim()).await?; - handle_response(response).await?; - } - Ok(5) => break, - _ => println!("Invalid choice!"), + let method = &args[1]; + let url = &args[2]; + + let body: HashMap<&str, &str> = if args.len() > 3 { + args[3..].iter() + .map(|s| { + let mut parts = s.split('='); + (parts.next().unwrap(), parts.next().unwrap_or("")) + }) + .collect() + } else { + HashMap::new() + }; + + let result = match method.as_str() { + "GET" => tokio::runtime::Runtime::new().unwrap().block_on(api::get(url)), + "POST" => tokio::runtime::Runtime::new().unwrap().block_on(api::post(url, body)), + "PUT" => tokio::runtime::Runtime::new().unwrap().block_on(api::put(url, body)), + "DELETE" => tokio::runtime::Runtime::new().unwrap().block_on(api::delete(url)), + _ => { + println!("Invalid method!"); + return; } - } + }; - Ok(()) -} \ No newline at end of file + match result { + Ok(response) => println!("{:#?}", response), + Err(e) => println!("Error: {}", e), + } +}