| Crates.io | curl-parser |
| lib.rs | curl-parser |
| version | 0.6.0 |
| created_at | 2023-02-09 06:07:07.742215+00 |
| updated_at | 2025-08-25 06:34:50.322265+00 |
| description | Convert curl command to a ParsedRequest (could be further converted to reqwest::RequestBuilder) |
| homepage | https://github.com/tyrchen/curl-parser |
| repository | https://github.com/tyrchen/curl-parser |
| max_upload_size | |
| id | 780539 |
| size | 123,840 |
A Rust library for parsing curl commands into structured HTTP request objects.
Many APIs provide curl examples to help users get started quickly. This crate bridges the gap between curl command examples and Rust code by parsing curl commands into structured ParsedRequest objects that can be easily converted to HTTP requests.
-X, --request - HTTP method-H, --header - HTTP headers-d, --data - Request body-u - Basic authentication-L, --location - Follow redirects-k, --insecure - Skip SSL verificationAdd this to your Cargo.toml:
[dependencies]
curl-parser = "0.6"
reqwest (enabled by default) - Enables conversion to reqwest::RequestBuilderuri (enabled by default) - Parses URLs into http::Uri typeTo use without default features:
[dependencies]
curl-parser = { version = "0.6", default-features = false }
use curl_parser::ParsedRequest;
use std::str::FromStr;
let curl_cmd = "curl https://api.example.com/users";
let request = ParsedRequest::from_str(curl_cmd)?;
println!("Method: {}", request.method);
println!("URL: {}", request.url);
use curl_parser::ParsedRequest;
use serde_json::json;
let curl_cmd = r#"curl -X POST https://api.github.com/repos \
-H "Authorization: Bearer {{ token }}" \
-d '{"name": "{{ repo_name }}"}"#;
let context = json!({
"token": "your_github_token",
"repo_name": "my-new-repo"
});
let request = ParsedRequest::load(curl_cmd, context)?;
use curl_parser::ParsedRequest;
use std::str::FromStr;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let curl_cmd = "curl https://api.github.com/users/rust-lang";
let parsed = ParsedRequest::from_str(curl_cmd)?;
// Convert to reqwest::RequestBuilder
let request: reqwest::RequestBuilder = parsed.try_into()?;
// Send the request
let response = request.send().await?;
println!("Status: {}", response.status());
Ok(())
}
let curl = r#"curl -X POST https://api.example.com/users \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer token123' \
-d '{"name": "John Doe", "email": "john@example.com"}"#;
let request = ParsedRequest::from_str(curl)?;
assert_eq!(request.method, Method::POST);
assert_eq!(request.body, vec![r#"{"name": "John Doe", "email": "john@example.com"}"#]);
let curl = r#"curl https://api.stripe.com/v1/charges \
-u sk_test_1234: \
-H "Stripe-Version: 2022-11-15""#;
let request = ParsedRequest::from_str(curl)?;
// The -u flag is automatically converted to Authorization: Basic header
let curl = r#"curl -X POST https://httpbin.org/post \
-d 'name=John' \
-d 'age=30' \
-d 'city=New York'"#;
let request = ParsedRequest::from_str(curl)?;
// Multiple -d flags are collected and form-urlencoded
The parser correctly handles escaped JSON in headers:
let curl = r#"curl https://api.example.com \
-H "X-Custom-Data: {\"key\":\"value\",\"nested\":{\"data\":true}}"#;
let request = ParsedRequest::from_str(curl)?;
// The escaped JSON is properly unescaped in the header value
If a request body is provided without an explicit method, POST is automatically used:
let curl = r#"curl https://api.example.com -d '{"data": "value"}'"#;
let request = ParsedRequest::from_str(curl)?;
assert_eq!(request.method, Method::POST); // Automatically set to POST
The parser automatically adds common default headers:
Accept: */* if not specifiedContent-Type: application/x-www-form-urlencoded for form dataThis crate is optimized for performance with:
Run benchmarks with:
cargo bench --bench parsing_benchmark
cargo build
cargo test
cargo clippy
cargo fmt
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details.