use anyhow::{anyhow, Result}; use regex::Regex; use std::collections::HashMap; use reqwest::header; use serde_json; use urlencoding; #[derive(Debug, Clone)] pub struct CurlAuth { pub url: String, pub headers: header::HeaderMap, pub data: Option, pub url_parameters: Option, } impl CurlAuth { pub fn from_curl(curl_command: &str) -> Result { println!("Parsing curl command..."); // Extract the URL using regex let url_regex = Regex::new(r"curl\s+'([^']+)'")?; let url = match url_regex.captures(curl_command) { Some(captures) => { match captures.get(1) { Some(url_match) => url_match.as_str().to_string(), None => return Err(anyhow!("Could not extract URL from regex match")) } }, None => return Err(anyhow!("Could not find URL in curl command: {}", curl_command)) }; println!("URL: {}", url); // Create a new HeaderMap let mut headers = header::HeaderMap::new(); // Extract headers using regex let header_regex = Regex::new(r"-H\s+'([^']+)'")?; println!("Extracting headers..."); for cap in header_regex.captures_iter(curl_command) { if let Some(header) = cap.get(1) { let header_str = header.as_str(); if let Some((key, value)) = header_str.split_once(':') { let key = key.trim(); let value = value.trim(); println!("Header: {} = {}", key, value); // Parse the header name and value if let Ok(header_name) = key.parse::() { if let Ok(header_value) = value.parse::() { headers.insert(header_name, header_value); } else { println!("Warning: Could not parse header value: {}", value); } } else { println!("Warning: Could not parse header name: {}", key); } } } } // Extract cookies using regex and add them to the headers let cookie_regex = Regex::new(r"-b\s+'([^']+)'")?; if let Some(captures) = cookie_regex.captures(curl_command) { if let Some(cookies_str) = captures.get(1) { println!("Found cookies: {}", cookies_str.as_str()); if let Ok(cookie_value) = cookies_str.as_str().parse::() { headers.insert(header::COOKIE, cookie_value); } else { println!("Warning: Could not parse cookie value"); } } } // Extract data using regex - try different formats let mut data = None; // First try --data-raw let data_raw_regex = Regex::new(r"--data-raw\s+'([^']+)'")?; if let Some(captures) = data_raw_regex.captures(curl_command) { if let Some(data_match) = captures.get(1) { data = Some(data_match.as_str().to_string()); println!("Found data-raw: {}", data.as_ref().unwrap()); } } // If not found, try --data if data.is_none() { let data_regex = Regex::new(r"--data\s+'([^']+)'")?; if let Some(captures) = data_regex.captures(curl_command) { if let Some(data_match) = captures.get(1) { data = Some(data_match.as_str().to_string()); println!("Found data: {}", data.as_ref().unwrap()); } } } // If not found, try -d if data.is_none() { let d_regex = Regex::new(r"-d\s+'([^']+)'")?; if let Some(captures) = d_regex.captures(curl_command) { if let Some(data_match) = captures.get(1) { data = Some(data_match.as_str().to_string()); println!("Found -d: {}", data.as_ref().unwrap()); } } } // Extract URL parameters if present let url_parameters = if url.contains('?') { extract_url_parameters(&url) } else { None }; // If we have URL parameters but no data, create data from parameters if data.is_none() && url_parameters.is_some() { let params = url_parameters.as_ref().unwrap(); println!("Creating data from URL parameters"); data = Some(serde_json::to_string(params).unwrap_or_default()); println!("Created data: {}", data.as_ref().unwrap()); } // Check for essential auth headers/cookies if !headers.contains_key(header::COOKIE) { println!("Warning: Missing cookie header"); } println!("CurlAuth created with URL and {} headers", headers.len()); println!("=== URL ==="); println!("{}", url); println!("=== Headers ==="); for (name, value) in headers.iter() { println!(" {}: {}", name, value.to_str().unwrap_or("[binary value]")); } println!("=== Data ==="); if let Some(data_str) = &data { println!("{}", data_str); } else { println!(" [No data]"); } println!("============"); Ok(Self { url, headers, data, url_parameters, }) } } fn extract_url_parameters(url: &str) -> Option { if let Some(query_part) = url.split('?').nth(1) { let mut result = serde_json::Map::new(); // Process each query parameter for param in query_part.split('&') { let parts: Vec<&str> = param.split('=').collect(); if parts.len() == 2 { let key = parts[0]; let value = parts[1]; if key == "variables" || key == "features" { if let Ok(decoded) = urlencoding::decode(value) { if let Ok(json) = serde_json::from_str::(&decoded) { result.insert(key.to_string(), json); } } } } } if !result.is_empty() { return Some(serde_json::Value::Object(result)); } } None }