diff --git a/Cargo.lock b/Cargo.lock index be4f57c..8fcf9fa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -157,6 +157,7 @@ dependencies = [ "cookie_store", "crokey", "crossterm", + "curl-parser", "image", "indexmap", "jsonxf", @@ -181,6 +182,7 @@ dependencies = [ "tui-big-text", "tui-textarea", "tui-tree-widget", + "walkdir", ] [[package]] @@ -249,6 +251,15 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "boa_ast" version = "0.18.0" @@ -464,9 +475,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.5.0" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80c21025abd42669a92efc996ef13cfb2c5c627858421ea58d5c3b331a6c134f" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" dependencies = [ "clap_builder", "clap_derive", @@ -474,9 +485,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.0" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "458bf1f341769dfcf849846f65dffdf9146daa56bcd2a47cb4e1de9915567c99" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" dependencies = [ "anstream", "anstyle", @@ -486,11 +497,11 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.0" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", "syn 2.0.58", @@ -604,6 +615,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + [[package]] name = "crc32fast" version = "1.4.0" @@ -695,6 +715,32 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "curl-parser" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c9ac8e8203aa44a586de649b10fd57c51df4d8a6c7d2cb83a1c87f162529e9e" +dependencies = [ + "base64 0.21.7", + "form_urlencoded", + "http", + "minijinja", + "pest", + "pest_derive", + "serde", + "snafu", +] + [[package]] name = "darling" version = "0.20.8" @@ -783,6 +829,16 @@ dependencies = [ "syn 2.0.58", ] +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + [[package]] name = "displaydoc" version = "0.2.4" @@ -794,6 +850,12 @@ dependencies = [ "syn 2.0.58", ] +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + [[package]] name = "dyn-clone" version = "1.0.17" @@ -1006,6 +1068,16 @@ dependencies = [ "slab", ] +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "gethostname" version = "0.4.3" @@ -1097,6 +1169,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.3.4" @@ -1521,6 +1599,12 @@ version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +[[package]] +name = "memo-map" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "374c335b2df19e62d4cb323103473cbc6510980253119180de862d89184f6a83" + [[package]] name = "memoffset" version = "0.9.1" @@ -1546,6 +1630,18 @@ dependencies = [ "unicase", ] +[[package]] +name = "minijinja" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55e877d961d4f96ce13615862322df7c0b6d169d40cab71a7ef3f9b9e594451e" +dependencies = [ + "memo-map", + "self_cell", + "serde", + "v_htmlescape", +] + [[package]] name = "miniz_oxide" version = "0.7.2" @@ -1784,6 +1880,51 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "pest" +version = "2.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26293c9193fbca7b1a3bf9b79dc1e388e927e6cacaa78b4a3ab705a1d3d41459" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ec22af7d3fb470a85dd2ca96b7c577a1eb4ef6f1683a9fe9a8c16e136c04687" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.58", +] + +[[package]] +name = "pest_meta" +version = "2.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7a240022f37c361ec1878d646fc5b7d7c4d28d5946e1a80ad5a7a4f4ca0bdcd" +dependencies = [ + "once_cell", + "pest", + "sha2", +] + [[package]] name = "phf" version = "0.11.2" @@ -2336,6 +2477,12 @@ dependencies = [ "libc", ] +[[package]] +name = "self_cell" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" + [[package]] name = "semver" version = "1.0.22" @@ -2407,6 +2554,17 @@ dependencies = [ "unsafe-libyaml", ] +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "signal-hook" version = "0.3.17" @@ -2464,6 +2622,28 @@ version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +[[package]] +name = "snafu" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4de37ad025c587a29e8f3f5605c00f70b98715ef90b9061a815b9e59e9042d6" +dependencies = [ + "doc-comment", + "snafu-derive", +] + +[[package]] +name = "snafu-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990079665f075b699031e9c08fd3ab99be5029b96f3b78dc0709e8f77e4efebf" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "snailquote" version = "0.3.1" @@ -2554,7 +2734,7 @@ version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a3417fc93d76740d974a01654a09777cb500428cc874ca9f45edfe0c4d4cd18" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "rustversion", @@ -2916,6 +3096,18 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + [[package]] name = "unicase" version = "2.7.0" @@ -3026,6 +3218,12 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "v_htmlescape" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e8257fbc510f0a46eb602c10215901938b5c2a7d5e70fc11483b1d3c9b5b18c" + [[package]] name = "version_check" version = "0.9.4" diff --git a/Cargo.toml b/Cargo.toml index 80f4480..75bc3fd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,13 +38,15 @@ jsonxf = "1.1.1" toml = "0.8.11" boa_engine = { version = "0.18.0", default-features = false } parse_postman_collection = "0.2.3" -clap = { version = "4.5.0", features = ["derive", "color"] } +curl-parser = { version = "0.3.1", default-features = false } +clap = { version = "4.5.4", features = ["derive", "color", "suggestions"] } arboard = "3.3.2" tokio = { version = "1.36.0", features = ["rt", "rt-multi-thread", "macros"] } parking_lot = { version = "0.12.2", features = ["serde"] } strum = "0.26.2" lazy_static = "1.4.0" nestify = "0.3.3" +walkdir = "2.5.0" snailquote = "0.3.1" indexmap = { version = "2.2.6", features = ["serde"] } base64 = "0.22.0" diff --git a/README.md b/README.md index 683ec92..eaf2f07 100644 --- a/README.md +++ b/README.md @@ -276,6 +276,7 @@ https://github.com/NachoNievaG/atac.nvim | [toml](https://github.com/toml-rs/toml) | 0.8.11 | Serialize & Deserialize application config files | | [boa_engine](https://github.com/boa-dev/boa) | 0.18.0 | Create Javascript runtimes. Used for pre and post request scripts | | [My fork](https://github.com/Julien-cpsn/postman-collection-rs) of [postman_collection](https://github.com/mandrean/postman-collection-rs) | 0.2.1 | Deserialize Postman collection files | +| [curl-parser](https://github.com/tyrchen/curl-parser) | 0.3.1 | Parse cURL request files | | [clap](https://github.com/clap-rs/clap) | 4.5.0 | Command Line Argument Parser | | [arboard](https://github.com/1Password/arboard) | 3.3.2 | Copy response body to clipboard | | [tokio](https://github.com/tokio-rs/tokio) | 1.0.0 | Handle asynchronous requests | @@ -283,6 +284,7 @@ https://github.com/NachoNievaG/atac.nvim | [strum](https://github.com/Peternator7/strum) | 0.26.2 | Enum facilities | | [lazy_static](https://github.com/rust-lang-nursery/lazy-static.rs) | 1.4.0 | Allows for more flexible constants. Mainly used for accessing CLI arguments everywhere | | [nestify](https://github.com/snowfoxsh/nestify) | 0.3.3 | Used to nest struct definitions | +| [walkdir](https://github.com/BurntSushi/walkdir) | 2.5.0 | Recursively retrieve files | | [snailquote](https://github.com/euank/snailquote) | 0.3.1 | Unescape string | | [indexmap](https://github.com/indexmap-rs/indexmap) | 2.2.6 | Ordered hashmap. Used in environments to preserve files' values order | | [base64](https://github.com/marshallpierce/rust-base64) | 0.22.0 | Encode auth. | diff --git a/import_tests/recursive_curls/depth_2/depth_3/test_curl_3 b/import_tests/recursive_curls/depth_2/depth_3/test_curl_3 new file mode 100644 index 0000000..b1c2835 --- /dev/null +++ b/import_tests/recursive_curls/depth_2/depth_3/test_curl_3 @@ -0,0 +1,18 @@ +curl 'https://github.com/Julien-cpsn/ATAC' \ + -H 'accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7' \ + -H 'accept-language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7' \ + -H 'cache-control: max-age=0' \ + -H 'cookie: _octo=GH1.1.1959269116.1687182163; _device_id=2811f3b85ff75158a08c56ca3ddbe2df; user_session=LLeRFVtOylajDHngA0_zzjNV2-T0N1S22N0YkkOqFMbJ4djZ; __Host-user_session_same_site=LLeRFVtOylajDHngA0_zzjNV2-T0N1S22N0YkkOqFMbJ4djZ; logged_in=yes; dotcom_user=Julien-cpsn; color_mode=%7B%22color_mode%22%3A%22dark%22%2C%22light_theme%22%3A%7B%22name%22%3A%22light%22%2C%22color_mode%22%3A%22light%22%7D%2C%22dark_theme%22%3A%7B%22name%22%3A%22dark_dimmed%22%2C%22color_mode%22%3A%22dark%22%7D%7D; preferred_color_mode=dark; tz=Europe%2FParis; has_recent_activity=1; _gh_sess=Jt6ZOdffY%2FjmplKDbN0QjKwWSAJJ1DmL5yLrH%2BA7Rjr9R%2B8TvXv7Q8so51Cr5ls27Hh3H6A7pDkZaAqaS0Q5HvEA4E6ia4srs8Z9a4bxJciA%2BkpgSZ7%2FIqaiMY40Fdoi7ewczp3qxwQvBmVNpQXexBPnPxpIMsivDlJQvxVX%2F%2Ff5UpK%2BVtEsDXwe1yPxc3j9nqDxnqHspncdM9PzX7zWizSIveAi0sHyFxU3yaogHmCACKZgVMFXmBnrMaIj80jQMFZo9w4LHdu5aOZATGiZKqP61kXXxT0POepF4I%2F4WWrUftneLW4ju4QEGDGOc6dMXMCHaFPVjiT9BMn8QcLJ6Vg%2BOFPB5RVSc0aBe%2B29WCho0iIvt3A64uIxf687A3JZOzmIjiWIJZpSq9nleumJTVZTi%2FJZaq2njqU4Gxjp4uPoIHqzDBg9YpEbWFmFXVoo4WuAYb28ZAD2qNOHM%2FoUUyePjtMmSpi8V7hPRqf3Ci0QDlBvX5bpnfDePbsCPpJhSHqys9oFZBqkxEYJq%2FthAuf3ZXu2euhO46NlOdcVb%2Bl2kzSbCuRHNyrkXTtt1rdlFpcp5x6ZXAvaJKGFAQuHU7jV%2B7FiAotgnz%2BIvEAEfAqLhr6dbCmdNUrKQcG%2BZk9dZhORKA4hG0sLDQ2eZUngq2dbwsLRQp3XWlZiPg%3D%3D--cq4qh6N4eKXeyUzf--fmdJG1EtntyfVOgFbk8NHA%3D%3D' \ + -H 'dnt: 1' \ + -H 'if-none-match: W/"2c8e9a97779f0715b9a44638c8ddabef"' \ + -H 'priority: u=0, i' \ + -H 'referer: https://github.com/' \ + -H 'sec-ch-ua: "Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99"' \ + -H 'sec-ch-ua-mobile: ?0' \ + -H 'sec-ch-ua-platform: "Windows"' \ + -H 'sec-fetch-dest: document' \ + -H 'sec-fetch-mode: navigate' \ + -H 'sec-fetch-site: same-origin' \ + -H 'sec-fetch-user: ?1' \ + -H 'upgrade-insecure-requests: 1' \ + -H 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36' \ No newline at end of file diff --git a/import_tests/recursive_curls/depth_2/depth_3/test_curl_4 b/import_tests/recursive_curls/depth_2/depth_3/test_curl_4 new file mode 100644 index 0000000..3b058f5 --- /dev/null +++ b/import_tests/recursive_curls/depth_2/depth_3/test_curl_4 @@ -0,0 +1,4 @@ +curl 'https://httpbin.org/put' \ + -X PUT \ + -H 'Content-Type: application/json' \ + -d 'test' \ No newline at end of file diff --git a/import_tests/recursive_curls/depth_2/depth_3/test_curl_6 b/import_tests/recursive_curls/depth_2/depth_3/test_curl_6 new file mode 100644 index 0000000..f7d6f66 --- /dev/null +++ b/import_tests/recursive_curls/depth_2/depth_3/test_curl_6 @@ -0,0 +1,2 @@ +curl --location 'https://httpbin.org/bearer' \ +--header 'Authorization: Bearer my_bearer=' \ No newline at end of file diff --git a/import_tests/recursive_curls/depth_2/depth_3/test_curl_7 b/import_tests/recursive_curls/depth_2/depth_3/test_curl_7 new file mode 100644 index 0000000..c8476fe --- /dev/null +++ b/import_tests/recursive_curls/depth_2/depth_3/test_curl_7 @@ -0,0 +1,3 @@ +curl --location 'https://httpbin.org/post' \ +--header 'Content-Type: application/octet-stream' \ +--data '@/C:/Users/u248244/Documents/Rust/ATAC/import_tests/swagger-petstore-v2.1.0.json' \ No newline at end of file diff --git a/import_tests/recursive_curls/depth_2/test_curl_2 b/import_tests/recursive_curls/depth_2/test_curl_2 new file mode 100644 index 0000000..f443ff9 --- /dev/null +++ b/import_tests/recursive_curls/depth_2/test_curl_2 @@ -0,0 +1,16 @@ +curl 'https://docs.rs/clap/latest/clap/' \ + -H 'accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7' \ + -H 'accept-language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7' \ + -H 'cache-control: max-age=0' \ + -H 'dnt: 1' \ + -H 'priority: u=0, i' \ + -H 'referer: https://rust-lang-nursery.github.io/' \ + -H 'sec-ch-ua: "Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99"' \ + -H 'sec-ch-ua-mobile: ?0' \ + -H 'sec-ch-ua-platform: "Windows"' \ + -H 'sec-fetch-dest: document' \ + -H 'sec-fetch-mode: navigate' \ + -H 'sec-fetch-site: cross-site' \ + -H 'sec-fetch-user: ?1' \ + -H 'upgrade-insecure-requests: 1' \ + -H 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36' \ No newline at end of file diff --git a/import_tests/recursive_curls/depth_2/test_curl_5 b/import_tests/recursive_curls/depth_2/test_curl_5 new file mode 100644 index 0000000..898c8ac --- /dev/null +++ b/import_tests/recursive_curls/depth_2/test_curl_5 @@ -0,0 +1,2 @@ +curl https://reqbin.com/echo \ + -u "login:password" \ No newline at end of file diff --git a/import_tests/recursive_curls/test_curl_1 b/import_tests/recursive_curls/test_curl_1 new file mode 100644 index 0000000..3e2052c --- /dev/null +++ b/import_tests/recursive_curls/test_curl_1 @@ -0,0 +1,23 @@ +curl 'https://www.google.com/search?q=some+search&rlz=1C1ONGR_frFR1063FR1063&oq=some+search&gs_lcrp=EgZjaHJvbWUyBggAEEUYOTIGCAEQRRg80gEINzU2OGowajeoAgCwAgA&sourceid=chrome&ie=UTF-8' \ + -H 'accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7' \ + -H 'accept-language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7' \ + -H 'cookie: HSID=Av_zeISP2IoC5ffne; SSID=AKgvP_7KP4Q2hAa7J; APISID=BHGY7ZbmZbJ_sm1O/ACh2Z88aE94LAktBN; SAPISID=8Pljvq5JQ81l6i-W/AE7yudhCMIhSx07aA; __Secure-1PAPISID=8Pljvq5JQ81l6i-W/AE7yudhCMIhSx07aA; __Secure-3PAPISID=8Pljvq5JQ81l6i-W/AE7yudhCMIhSx07aA; SID=g.a000iQi34M-7qEaVOkMFrycXCJM8EqqhOMd2x_eD98hvFBtmDGiYVrLlfIjHEiQDF9UR7JMTcwACgYKAW0SAQASFQHGX2Mi67FwpyVk-XamQ4h1n4-YzhoVAUF8yKpmHMVXUV6LSLVgLdR39TtR0076; __Secure-1PSID=g.a000iQi34M-7qEaVOkMFrycXCJM8EqqhOMd2x_eD98hvFBtmDGiYeQ0eDf3PWlHwVAxIQCQZSQACgYKAQ4SAQASFQHGX2Mi8cOFgeIIFTgntS5oW6LNRhoVAUF8yKqTtznLmD3NAcbAgrp4pPgX0076; __Secure-3PSID=g.a000iQi34M-7qEaVOkMFrycXCJM8EqqhOMd2x_eD98hvFBtmDGiYymEt7XyxPJc9XnYV2-s3kwACgYKAagSAQASFQHGX2Mi0MZRs5Ln80PaVraKG-YuwxoVAUF8yKrm83-kkzD22gxazewDzerG0076; OTZ=7515057_48_52_123900_48_436380; NID=513=UWSHg2m07oid_oICg5QPNg42NEXDwmQ-1Re8H5-JeTIKQN1fIIyJmwfPw38LxWLmaGKJLV8e6qrxX_8LEOaL6TRw6LwYyIsdCj-UjQ7yhHF3yApwcWTm9hjTE4cjq4bvD4PO2--Ghy8TYtl_dU3W2HG4TILc6HLhEsyScvpc_P0pWNgKGI2rIOqJyuj9ZhRaYDl1yMeX5jvHTTh5V3cGDaGw9P3iebXTaL23iauLhPI0oTM6zjdyLDpGJrxX2b3qRvosGS2MgOOF1V3cKx_Wn-7MJWj8bKvlvvw2EEJ6w_MkQMNJ7npEhLNjw8Jwp-PZPaVEJ7Pv1tqyWBU0aw1M5aP2KDdFSXrbNNM6o2Yn3fWIzboPmrxufXlIh6a2CVh4uR6CTgXKjrQaUjpbWKZtRg-rqtDuKW14B83lzZjvQR79fUrkGQYjmlmQ1FkU21QXk_ln780-gVTYULlYAUsHlyNFnMq4ynqdaT5LO7ZJW_T36Wv-URtZamHha-9sX1MmRbqqusYMxh3Nr8Uo7y9IA241D2WIKGi-OJj8z65np9nvOCAlzJkIS9WGpV27NDQqokwxJD87aPw4dibeVp2nQLwm1qRTAnwdp4t6ZB3AaAGiVzHuAIvYIfpgHYWUMTSMSIabQhSYGTmvhf5jHA; SEARCH_SAMESITE=CgQIhJsB; AEC=AQTF6HyWxVlqhwtKFurLp8MJDzz-RmIqYYq9Yp2YChWpu2seU7RYeOBnMm0; __Secure-ENID=19.SE=M390Zgw8_lsFMHxTOQYX4mBtx9KVzOdYUw7PL5JfrPlkgJ7YK1NQdieYWRmFd5g7E_PFfugqNnx6oAo7zQ5AxPT0CXQmoI-vnJAQTLR0RNxMP63vrZz7cFqkAEviEJpvhRGf4vUbrgUB_26PLDSAxejYEt6kZGc3ryi9sXgYPXFdJCK06gecG_JC2HF7o5tm0J79_C6rxle9ahzi9UXDN9QhbZ9POmaWKHefIIA3TjcYseTo-mWGLorvQZsVQUHi3hyf0zMq1QoK-2bGY9G1nC8NaFb2fNR3mxF7bu7aAhun1Hl4gHZDtX3CHghXfBGwz6Gx7JPWkSptAdu7z-9Qm1ykttSIQg66r8gysaDwEAfAvwSzSW_-fLlvE-cmjeKk_px3anvx1XiNRGxhNHXQriaQsQjqxES43FFiYGp7wLwCJsenMEB-nTI79JZ9Vh05_qknchOP7QMEXtARm6S7rPnosjBbv0e84VvzarbLpMegmkzWaId32X83ON_2h0y_yzV78urk6qzCf_5CTyD98B6opbWfExK9UGDGql7VMimj8KtqeMCXB9yNe9yKRVhx5uPnfOEIKoBY1e1SKS6UQvtzXv2n-tNqd1iy1OSejS86-J8Lnke8yJKjrfor; DV=Q2LJvyNVsmxWACJ-bZgLX549pDGc9NiJV5getGLf6QAAABAYEUSZHNXSUQAAAAgH7s-UDNE6IAAAANfCf_a5KYAFDgAAAA; __Secure-1PSIDTS=sidts-CjEBLwcBXPYch52QnGCI_H7mp8ew3-QWF1TdVapd-Ot8DKeRG0SCr6TvhFo5NyKRdO8NEAA; __Secure-3PSIDTS=sidts-CjEBLwcBXPYch52QnGCI_H7mp8ew3-QWF1TdVapd-Ot8DKeRG0SCr6TvhFo5NyKRdO8NEAA; SIDCC=AKEyXzVA8OiZZvrJ2RzBTteJTcwb4UfdUZY9dHNEz0DWkEXOI3wWe1fXDKDB8gtDkhxKeWqnYXM; __Secure-1PSIDCC=AKEyXzVfXxqD0IqDytZWO1FbpXVvv0mG_MXUbaQCBjNaX7Tf835kifjhpjNv3fIxS2RqjRiSMMur; __Secure-3PSIDCC=AKEyXzWy7jyQPWXTZICPbhtJllfzaZdxEp9bTurivJihHm0-8k59CDLsTX2_gWp8SOBAgVYiS3lM' \ + -H 'dnt: 1' \ + -H 'priority: u=0, i' \ + -H 'sec-ch-ua: "Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99"' \ + -H 'sec-ch-ua-arch: "x86"' \ + -H 'sec-ch-ua-bitness: "64"' \ + -H 'sec-ch-ua-full-version: "124.0.6367.119"' \ + -H 'sec-ch-ua-full-version-list: "Chromium";v="124.0.6367.119", "Google Chrome";v="124.0.6367.119", "Not-A.Brand";v="99.0.0.0"' \ + -H 'sec-ch-ua-mobile: ?0' \ + -H 'sec-ch-ua-model: ""' \ + -H 'sec-ch-ua-platform: "Windows"' \ + -H 'sec-ch-ua-platform-version: "15.0.0"' \ + -H 'sec-ch-ua-wow64: ?0' \ + -H 'sec-fetch-dest: document' \ + -H 'sec-fetch-mode: navigate' \ + -H 'sec-fetch-site: none' \ + -H 'sec-fetch-user: ?1' \ + -H 'upgrade-insecure-requests: 1' \ + -H 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36' \ + -H 'x-client-data: CIe2yQEIo7bJAQipncoBCJmDywEIkqHLAQia/swBCIWgzQEIk+DNAQiRh84BCPSJzgEY9MnNAQ==' \ No newline at end of file diff --git a/import_tests/test_curl b/import_tests/test_curl new file mode 100644 index 0000000..3e2052c --- /dev/null +++ b/import_tests/test_curl @@ -0,0 +1,23 @@ +curl 'https://www.google.com/search?q=some+search&rlz=1C1ONGR_frFR1063FR1063&oq=some+search&gs_lcrp=EgZjaHJvbWUyBggAEEUYOTIGCAEQRRg80gEINzU2OGowajeoAgCwAgA&sourceid=chrome&ie=UTF-8' \ + -H 'accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7' \ + -H 'accept-language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7' \ + -H 'cookie: HSID=Av_zeISP2IoC5ffne; SSID=AKgvP_7KP4Q2hAa7J; APISID=BHGY7ZbmZbJ_sm1O/ACh2Z88aE94LAktBN; SAPISID=8Pljvq5JQ81l6i-W/AE7yudhCMIhSx07aA; __Secure-1PAPISID=8Pljvq5JQ81l6i-W/AE7yudhCMIhSx07aA; __Secure-3PAPISID=8Pljvq5JQ81l6i-W/AE7yudhCMIhSx07aA; SID=g.a000iQi34M-7qEaVOkMFrycXCJM8EqqhOMd2x_eD98hvFBtmDGiYVrLlfIjHEiQDF9UR7JMTcwACgYKAW0SAQASFQHGX2Mi67FwpyVk-XamQ4h1n4-YzhoVAUF8yKpmHMVXUV6LSLVgLdR39TtR0076; __Secure-1PSID=g.a000iQi34M-7qEaVOkMFrycXCJM8EqqhOMd2x_eD98hvFBtmDGiYeQ0eDf3PWlHwVAxIQCQZSQACgYKAQ4SAQASFQHGX2Mi8cOFgeIIFTgntS5oW6LNRhoVAUF8yKqTtznLmD3NAcbAgrp4pPgX0076; __Secure-3PSID=g.a000iQi34M-7qEaVOkMFrycXCJM8EqqhOMd2x_eD98hvFBtmDGiYymEt7XyxPJc9XnYV2-s3kwACgYKAagSAQASFQHGX2Mi0MZRs5Ln80PaVraKG-YuwxoVAUF8yKrm83-kkzD22gxazewDzerG0076; OTZ=7515057_48_52_123900_48_436380; NID=513=UWSHg2m07oid_oICg5QPNg42NEXDwmQ-1Re8H5-JeTIKQN1fIIyJmwfPw38LxWLmaGKJLV8e6qrxX_8LEOaL6TRw6LwYyIsdCj-UjQ7yhHF3yApwcWTm9hjTE4cjq4bvD4PO2--Ghy8TYtl_dU3W2HG4TILc6HLhEsyScvpc_P0pWNgKGI2rIOqJyuj9ZhRaYDl1yMeX5jvHTTh5V3cGDaGw9P3iebXTaL23iauLhPI0oTM6zjdyLDpGJrxX2b3qRvosGS2MgOOF1V3cKx_Wn-7MJWj8bKvlvvw2EEJ6w_MkQMNJ7npEhLNjw8Jwp-PZPaVEJ7Pv1tqyWBU0aw1M5aP2KDdFSXrbNNM6o2Yn3fWIzboPmrxufXlIh6a2CVh4uR6CTgXKjrQaUjpbWKZtRg-rqtDuKW14B83lzZjvQR79fUrkGQYjmlmQ1FkU21QXk_ln780-gVTYULlYAUsHlyNFnMq4ynqdaT5LO7ZJW_T36Wv-URtZamHha-9sX1MmRbqqusYMxh3Nr8Uo7y9IA241D2WIKGi-OJj8z65np9nvOCAlzJkIS9WGpV27NDQqokwxJD87aPw4dibeVp2nQLwm1qRTAnwdp4t6ZB3AaAGiVzHuAIvYIfpgHYWUMTSMSIabQhSYGTmvhf5jHA; SEARCH_SAMESITE=CgQIhJsB; AEC=AQTF6HyWxVlqhwtKFurLp8MJDzz-RmIqYYq9Yp2YChWpu2seU7RYeOBnMm0; __Secure-ENID=19.SE=M390Zgw8_lsFMHxTOQYX4mBtx9KVzOdYUw7PL5JfrPlkgJ7YK1NQdieYWRmFd5g7E_PFfugqNnx6oAo7zQ5AxPT0CXQmoI-vnJAQTLR0RNxMP63vrZz7cFqkAEviEJpvhRGf4vUbrgUB_26PLDSAxejYEt6kZGc3ryi9sXgYPXFdJCK06gecG_JC2HF7o5tm0J79_C6rxle9ahzi9UXDN9QhbZ9POmaWKHefIIA3TjcYseTo-mWGLorvQZsVQUHi3hyf0zMq1QoK-2bGY9G1nC8NaFb2fNR3mxF7bu7aAhun1Hl4gHZDtX3CHghXfBGwz6Gx7JPWkSptAdu7z-9Qm1ykttSIQg66r8gysaDwEAfAvwSzSW_-fLlvE-cmjeKk_px3anvx1XiNRGxhNHXQriaQsQjqxES43FFiYGp7wLwCJsenMEB-nTI79JZ9Vh05_qknchOP7QMEXtARm6S7rPnosjBbv0e84VvzarbLpMegmkzWaId32X83ON_2h0y_yzV78urk6qzCf_5CTyD98B6opbWfExK9UGDGql7VMimj8KtqeMCXB9yNe9yKRVhx5uPnfOEIKoBY1e1SKS6UQvtzXv2n-tNqd1iy1OSejS86-J8Lnke8yJKjrfor; DV=Q2LJvyNVsmxWACJ-bZgLX549pDGc9NiJV5getGLf6QAAABAYEUSZHNXSUQAAAAgH7s-UDNE6IAAAANfCf_a5KYAFDgAAAA; __Secure-1PSIDTS=sidts-CjEBLwcBXPYch52QnGCI_H7mp8ew3-QWF1TdVapd-Ot8DKeRG0SCr6TvhFo5NyKRdO8NEAA; __Secure-3PSIDTS=sidts-CjEBLwcBXPYch52QnGCI_H7mp8ew3-QWF1TdVapd-Ot8DKeRG0SCr6TvhFo5NyKRdO8NEAA; SIDCC=AKEyXzVA8OiZZvrJ2RzBTteJTcwb4UfdUZY9dHNEz0DWkEXOI3wWe1fXDKDB8gtDkhxKeWqnYXM; __Secure-1PSIDCC=AKEyXzVfXxqD0IqDytZWO1FbpXVvv0mG_MXUbaQCBjNaX7Tf835kifjhpjNv3fIxS2RqjRiSMMur; __Secure-3PSIDCC=AKEyXzWy7jyQPWXTZICPbhtJllfzaZdxEp9bTurivJihHm0-8k59CDLsTX2_gWp8SOBAgVYiS3lM' \ + -H 'dnt: 1' \ + -H 'priority: u=0, i' \ + -H 'sec-ch-ua: "Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99"' \ + -H 'sec-ch-ua-arch: "x86"' \ + -H 'sec-ch-ua-bitness: "64"' \ + -H 'sec-ch-ua-full-version: "124.0.6367.119"' \ + -H 'sec-ch-ua-full-version-list: "Chromium";v="124.0.6367.119", "Google Chrome";v="124.0.6367.119", "Not-A.Brand";v="99.0.0.0"' \ + -H 'sec-ch-ua-mobile: ?0' \ + -H 'sec-ch-ua-model: ""' \ + -H 'sec-ch-ua-platform: "Windows"' \ + -H 'sec-ch-ua-platform-version: "15.0.0"' \ + -H 'sec-ch-ua-wow64: ?0' \ + -H 'sec-fetch-dest: document' \ + -H 'sec-fetch-mode: navigate' \ + -H 'sec-fetch-site: none' \ + -H 'sec-fetch-user: ?1' \ + -H 'upgrade-insecure-requests: 1' \ + -H 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36' \ + -H 'x-client-data: CIe2yQEIo7bJAQipncoBCJmDywEIkqHLAQia/swBCIWgzQEIk+DNAQiRh84BCPSJzgEY9MnNAQ==' \ No newline at end of file diff --git a/src/app/files/import/curl.rs b/src/app/files/import/curl.rs new file mode 100644 index 0000000..b044686 --- /dev/null +++ b/src/app/files/import/curl.rs @@ -0,0 +1,202 @@ +use std::fs; +use std::path::PathBuf; +use std::str::FromStr; +use std::sync::Arc; + +use parking_lot::RwLock; +use regex::Regex; +use reqwest::header::CONTENT_TYPE; +use reqwest::Url; +use walkdir::WalkDir; + +use crate::app::app::App; +use crate::app::startup::args::ARGS; +use crate::panic_error; +use crate::request::auth::Auth; +use crate::request::body::ContentType; +use crate::request::body::ContentType::NoBody; +use crate::request::collection::Collection; +use crate::request::method::Method; +use crate::request::request::{KeyValue, Request}; + +impl App<'_> { + pub fn import_curl_file(&mut self, path_buf: &PathBuf, collection_name: &String, request_name: &Option, recursive: &bool, max_depth: u16) { + println!("Parsing cURL request"); + + println!("Collection name: {}", collection_name); + + let (collection_index, collection) = match self.collections.iter_mut().enumerate().find(|(_, collection)| collection.name == collection_name.as_str()) { + Some((index, collection)) => (index, collection), + None => { + println!("Collection does not exist. Creating it..."); + + let file_format = self.config.get_preferred_collection_file_format(); + + let collection = Collection { + name: collection_name.clone(), + requests: vec![], + path: ARGS.directory.join(format!("{}.{}", collection_name.clone(), file_format.to_string())), + file_format, + }; + + self.collections.push(collection); + + (self.collections.len()-1, self.collections.last_mut().unwrap()) + } + }; + + let request_name = match request_name { + None => path_buf.file_stem().unwrap().to_str().unwrap().to_string(), + Some(request_name) => request_name.clone() + }; + + let requests = match path_buf.is_file() { + true => vec![ + parse_request(path_buf, request_name) + ], + false => parse_requests_recursively(path_buf, *recursive, max_depth), + }; + + // Add the parsed request to the collection + collection.requests.extend(requests); + + self.save_collection_to_file(collection_index); + } +} + +fn parse_requests_recursively(path: &PathBuf, recursive: bool, max_depth: u16) -> Vec>> { + let max_depth: usize = match recursive { + true => max_depth as usize, + false => 1 + }; + + let mut requests: Vec>> = vec![]; + let walker = WalkDir::new(path) + .max_depth(max_depth) + .into_iter() + .filter_map(|e| e.ok()); + + for entry in walker { + if !entry.file_type().is_file() { + continue; + } + + // Will use the file name as the request name + let file_name = entry.file_name().to_str().unwrap().to_string(); + let request = parse_request(&entry.path().to_path_buf(), file_name); + + requests.push(request); + } + + return requests; +} + +/// TODO: parse everything with regexes in order to handle everything +fn parse_request(path: &PathBuf, request_name: String) -> Arc> { + let curl_stringed = match fs::read_to_string(path) { + Ok(original_curl) => original_curl, + Err(e) => panic_error(format!("Could not read cURL file\n\t{e}")), + }; + + println!("\tRequest name: {}", request_name); + + let parsed_curl = match curl_parser::ParsedRequest::load(&curl_stringed, None::) { + Ok(parsed_curl) => parsed_curl, + Err(e) => panic_error(format!("Could not parse cURL\n\t{e}")), + }; + + /* URL */ + + // Parse the URL so we can transform it + let mut curl_url = match Url::parse(&parsed_curl.url.to_string()) { + Ok(url) => url, + Err(e) => panic_error(format!("Could not parse URL\n\t{e}")), + }; + + curl_url.set_query(None); + let url = curl_url.to_string(); + + /* QUERY PARAMS */ + + let params = curl_url + .query_pairs() + .map(|(k, v)| KeyValue { + enabled: true, + data: (k.to_string(), v.to_string()), + }) + .collect(); + + /* METHOD */ + + let method = match Method::from_str(parsed_curl.method.as_str()) { + Ok(method) => method, + Err(e) => panic_error(format!("Unknown method\n\t{e}")), + }; + + /* HEADERS */ + + let headers: Vec = parsed_curl.headers + .iter() + .filter(|(header_name, _)| header_name.as_str() != "authorization") // Exclude Authorization header, as that will be handled by the auth field + .map(|(k, v)| KeyValue { + enabled: true, + data: (k.to_string(), v.to_str().unwrap().to_string()), + }) + .collect(); + + /* AUTH */ + + let basic_auth_regex = Regex::new(r#"(-u|--user) ["'](?.*):(?.*)["']"#).unwrap(); + + let auth = match basic_auth_regex.captures(&curl_stringed) { + None => { + let bearer_token_header = parsed_curl.headers + .iter() + .find(|(header_name, value)| header_name.as_str() == "authorization" && value.to_str().unwrap().starts_with("Bearer ")); + + if let Some((_, bearer_token)) = bearer_token_header { + let bearer_token = &bearer_token.to_str().unwrap()[7..]; + + Auth::BearerToken(bearer_token.to_string()) + } + else { + Auth::NoAuth + } + } + Some(capture) => Auth::BasicAuth(capture["username"].to_string(), capture["password"].to_string()) + }; + + /* BODY */ + + let body; + + // TODO: does not support forms yet + if !parsed_curl.body.is_empty() { + let content_type_header = headers.iter().find(|header| header.data.0 == CONTENT_TYPE.as_str()); + let body_stringed = parsed_curl.body.join("\n"); + + + if let Some(content_type) = content_type_header { + body = ContentType::from_content_type(&content_type.data.1, body_stringed); + } + else { + body = NoBody; + } + } + else { + body = NoBody; + } + + let request = Request { + name: request_name, + url, + method, + params, + headers, + body, + auth, + ..Default::default() + }; + + return Arc::new(RwLock::new(request)); +} \ No newline at end of file diff --git a/src/app/files/import/mod.rs b/src/app/files/import/mod.rs new file mode 100644 index 0000000..d3306ee --- /dev/null +++ b/src/app/files/import/mod.rs @@ -0,0 +1,2 @@ +pub(super) mod postman; +pub(super) mod curl; \ No newline at end of file diff --git a/src/app/files/postman.rs b/src/app/files/import/postman.rs similarity index 100% rename from src/app/files/postman.rs rename to src/app/files/import/postman.rs diff --git a/src/app/files/mod.rs b/src/app/files/mod.rs index 6e2e60e..3d22bb0 100644 --- a/src/app/files/mod.rs +++ b/src/app/files/mod.rs @@ -3,4 +3,4 @@ pub mod environment; pub mod log; pub mod config; pub mod key_bindings; -mod postman; \ No newline at end of file +pub mod import; \ No newline at end of file diff --git a/src/app/startup/args.rs b/src/app/startup/args.rs index 2c48e62..a00359d 100644 --- a/src/app/startup/args.rs +++ b/src/app/startup/args.rs @@ -1,11 +1,12 @@ use std::env; use std::path::PathBuf; use clap::{Parser, Subcommand}; +use clap::builder::Styles; use lazy_static::lazy_static; -use crate::{panic_error}; +use crate::panic_error; #[derive(Parser, Debug)] -#[command(version, about, long_about = None)] +#[command(version, about, long_about = None, styles = Styles::styled())] pub struct Args { /// Main application directory, containing JSON collections files, the atac.toml config file and the atac.log file #[arg(short, long)] @@ -15,26 +16,54 @@ pub struct Args { pub command: Option, /// Avoid saving data to the collection file - #[arg(long, default_value_t = false)] + #[arg(global = true, long, default_value_t = false)] pub dry_run: bool, } -#[derive(Debug, Subcommand, PartialEq)] +#[derive(Subcommand, Debug, PartialEq)] pub enum Command { - /// Used to import a collection file such as Postman - Import(ImportArgs), + /// Import a collection or request from other file formats (Postman v2.1.0, cURL) + Import { + /// The type of file to import + #[command(subcommand)] + import_type: ImportType, + }, } -#[derive(Debug, clap::Args, PartialEq)] -pub struct ImportArgs { - /// A file to import, only Postman v2.1 JSON collection for now - pub path: PathBuf, +#[derive(Subcommand, Debug, PartialEq)] +pub enum ImportType { + /// Import a Postman v2.1.0 file + Postman { + /// Path to the file to import + import_path: PathBuf, - /// Max depth at which import should stop creating nested collections and only get the deeper requests - #[arg(long)] - pub max_depth: Option, + /// Max depth at which import should stop creating nested collections and only get the deeper requests + #[arg(long)] + max_depth: Option, + }, + + /// Import a curl file + Curl { + /// Path to the file to import + import_path: PathBuf, + + /// Collection name to save the request to + collection_name: String, + + /// Request name (will use the file name if none is provided) + request_name: Option, + + /// Search for deeper files + #[arg(short, long, conflicts_with = "request_name")] + recursive: bool, + + /// Max depth at which import should stop creating nested collections and only get the deeper requests + #[arg(long, requires = "recursive", conflicts_with = "request_name")] + max_depth: Option, + }, } + pub struct ParsedArgs { pub directory: PathBuf, pub is_directory_from_env: bool, diff --git a/src/app/startup/startup.rs b/src/app/startup/startup.rs index 04f9174..fa80643 100644 --- a/src/app/startup/startup.rs +++ b/src/app/startup/startup.rs @@ -1,7 +1,7 @@ use std::fs::OpenOptions; use crate::app::app::App; -use crate::app::startup::args::{ARGS, Command}; +use crate::app::startup::args::{ARGS, Command, ImportType}; use crate::panic_error; use crate::request::collection::CollectionFileFormat; @@ -18,12 +18,23 @@ impl App<'_> { if let Some(command) = &ARGS.command { match command { - Command::Import(import_args) => { - self.import_postman_collection(&import_args.path, import_args.max_depth.unwrap_or(99)); + Command::Import { import_type} => match import_type { + ImportType::Postman { + import_path, + max_depth + } => self.import_postman_collection(&import_path, max_depth.unwrap_or(99)), + + ImportType::Curl { + import_path, + collection_name, + request_name, + recursive, + max_depth + } => self.import_curl_file(&import_path, collection_name, request_name, recursive, max_depth.unwrap_or(99)) } } } - + self } diff --git a/src/request/body.rs b/src/request/body.rs index fc059ee..6fe0965 100644 --- a/src/request/body.rs +++ b/src/request/body.rs @@ -41,6 +41,20 @@ impl ContentType { } } + pub fn from_content_type(content_type: &str, body: String) -> ContentType { + match content_type { + //"multipart/form-data" => Multipart(body), + //"application/x-www-form-urlencoded" => Form(body), + "application/octet-stream" => File(body), + "text/plain" => Raw(body), + "application/json" => Json(body), + "application/xml" => Json(body), + "application/html" => Json(body), + "application/javascript" => Json(body), + _ => NoBody + } + } + pub fn get_form(&self) -> Option<&Vec> { match self { Multipart(form) | Form(form) => Some(form),