pub struct HttpClient { /* private fields */ }Implementations§
Source§impl HttpClient
impl HttpClient
Sourcepub fn new() -> Self
pub fn new() -> Self
Examples found in repository?
examples/coingecko_oracle.rs (line 22)
13fn main() {
14 // read coin id from stdin
15 let mut buf = [0; 1024];
16 let len = read_stdin(&mut buf).unwrap();
17 let coin_id = std::str::from_utf8(&buf[..len as usize])
18 .unwrap_or_default()
19 .trim();
20
21 // perform http request
22 let client = HttpClient::new();
23 let url = format!(
24 "https://api.coingecko.com/api/v3/simple/price?ids={}&vs_currencies=usd",
25 coin_id
26 );
27 let response = client.get(&url).send().unwrap();
28 let body = response.bytes().to_vec(); // e.g. {"bitcoin":{"usd":67675}}
29
30 // println!("{}", String::from_utf8(body.clone()).unwrap());
31
32 // parse the json response; extrac usd price
33 let json: serde_json::Result<HashMap<String, HashMap<String, f64>>> =
34 serde_json::from_slice(&body);
35 let Ok(data) = json else {
36 eprintln!("Failed to parse JSON");
37 return;
38 };
39 let Some(coin_data) = data.get(coin_id) else {
40 eprintln!("Coin not found in response.");
41 return;
42 };
43 let Some(usd_price) = coin_data.get("usd") else {
44 eprintln!("USD price not found for {}.", coin_id);
45 return;
46 };
47
48 let coin_price = CoinPrice {
49 id: coin_id.to_string(),
50 price: (*usd_price * 1_000_000.0) as u64, // price in 6 decimals
51 currency: "usd".to_string(),
52 };
53 println!("{}", json!(coin_price));
54}Sourcepub fn builder() -> HttpClientBuilder
pub fn builder() -> HttpClientBuilder
Examples found in repository?
examples/http_client.rs (line 40)
4fn main() -> Result<(), Box<dyn std::error::Error>> {
5 println!("====================================");
6 println!("HTTP v2 Client Demo");
7 println!("====================================");
8
9 println!("\n1. GET request:");
10 match get("https://httpbin.org/get").send() {
11 Ok(response) => {
12 println!("GET Status: {}", response.status());
13 println!("GET Success: {}", response.is_success());
14 }
15 Err(e) => println!("GET Error: {}", e),
16 }
17
18 println!("\n2. POST with JSON:");
19 let json_data = serde_json::json!({
20 "name": "Blockless SDK",
21 "version": "2.0",
22 "api_style": "reqwest-like"
23 });
24 match post("https://httpbin.org/post").json(&json_data)?.send() {
25 Ok(response) => {
26 println!("POST JSON Status: {}", response.status());
27 if let Ok(response_json) = response.json::<serde_json::Value>() {
28 if let Some(received_json) = response_json.get("json") {
29 println!("Received JSON: {}", received_json);
30 }
31 }
32 }
33 Err(e) => println!("POST JSON Error: {}", e),
34 }
35
36 println!("\n3. Client instance with default configuration:");
37 let mut default_headers = HashMap::new();
38 default_headers.insert("User-Agent".to_string(), "Blockless-SDK/2.0".to_string());
39 default_headers.insert("Accept".to_string(), "application/json".to_string());
40 let client = HttpClient::builder()
41 .default_headers(default_headers)
42 .timeout(10000)
43 .build();
44 match client
45 .get("https://httpbin.org/get")
46 .query("search", "blockless")
47 .query("limit", "10")
48 .query("format", "json")
49 .send()
50 {
51 Ok(response) => {
52 println!("Client GET Status: {}", response.status());
53 if let Ok(json_data) = response.json::<serde_json::Value>() {
54 if let Some(args) = json_data.get("args") {
55 println!("Query params: {}", args);
56 }
57 }
58 }
59 Err(e) => println!("Client GET Error: {}", e),
60 }
61
62 println!("\n4. Authentication examples:");
63 match client
64 .get("https://httpbin.org/basic-auth/user/pass")
65 .basic_auth("user", "pass")
66 .send()
67 {
68 Ok(response) => {
69 println!("Basic auth status: {}", response.status());
70 if let Ok(json_data) = response.json::<serde_json::Value>() {
71 println!("Authenticated: {:?}", json_data.get("authenticated"));
72 }
73 }
74 Err(e) => println!("Basic auth error: {}", e),
75 }
76
77 match client
78 .get("https://httpbin.org/bearer")
79 .bearer_auth("test-token-12345")
80 .send()
81 {
82 Ok(response) => {
83 println!("Bearer auth status: {}", response.status());
84 if let Ok(json_data) = response.json::<serde_json::Value>() {
85 println!("Token received: {:?}", json_data.get("token"));
86 }
87 }
88 Err(e) => println!("Bearer auth error: {}", e),
89 }
90
91 println!("\n5. Different request body types:");
92 let mut form_data = HashMap::new();
93 form_data.insert("name".to_string(), "Blockless".to_string());
94 form_data.insert("type".to_string(), "distributed computing".to_string());
95 match client
96 .post("https://httpbin.org/post")
97 .form(form_data)
98 .send()
99 {
100 Ok(response) => {
101 println!("Form POST Status: {}", response.status());
102 if let Ok(json_data) = response.json::<serde_json::Value>() {
103 if let Some(form) = json_data.get("form") {
104 println!("Form data received: {}", form);
105 }
106 }
107 }
108 Err(e) => println!("Form POST Error: {}", e),
109 }
110
111 println!("\n6. Multipart form with file upload:");
112 let multipart_fields = vec![
113 MultipartField::text("description", "SDK test file"),
114 MultipartField::file(
115 "upload",
116 b"Hello from Blockless SDK v2!".to_vec(),
117 "hello.txt",
118 Some("text/plain".to_string()),
119 ),
120 ];
121 match client
122 .post("https://httpbin.org/post")
123 .multipart(multipart_fields)
124 .send()
125 {
126 Ok(response) => {
127 println!("Multipart POST Status: {}", response.status());
128 if let Ok(json_data) = response.json::<serde_json::Value>() {
129 if let Some(files) = json_data.get("files") {
130 println!("Files uploaded: {}", files);
131 }
132 }
133 }
134 Err(e) => println!("Multipart POST Error: {}", e),
135 }
136
137 println!("\n7. Binary data:");
138 let binary_data = vec![0x48, 0x65, 0x6c, 0x6c, 0x6f]; // "Hello" in bytes
139 match client
140 .post("https://httpbin.org/post")
141 .header("Content-Type", "application/octet-stream")
142 .body_bytes(binary_data)
143 .send()
144 {
145 Ok(response) => {
146 println!("Binary POST Status: {}", response.status());
147 }
148 Err(e) => println!("Binary POST Error: {}", e),
149 }
150
151 println!("\n8. Advanced request building:");
152 match client
153 .put("https://httpbin.org/put")
154 .header("X-Custom-Header", "custom-value")
155 .header("X-API-Version", "2.0")
156 .query("action", "update")
157 .query("id", "12345")
158 .timeout(5000)
159 .body("Updated data")
160 .send()
161 {
162 Ok(response) => {
163 println!("PUT Status: {}", response.status());
164 if let Ok(json_data) = response.json::<serde_json::Value>() {
165 if let Some(headers) = json_data.get("headers") {
166 println!("Custom headers received: {}", headers);
167 }
168 }
169 }
170 Err(e) => println!("PUT Error: {}", e),
171 }
172
173 println!("\nDemo completed 🚀");
174 Ok(())
175}More examples
examples/ipfs_api.rs (line 14)
3fn main() -> Result<(), Box<dyn std::error::Error>> {
4 println!("IPFS RPC API Demo - HTTP v2 Client");
5 println!("=================================");
6 println!("Make sure your IPFS node is running on localhost:5001");
7 println!("Docker command: docker run --rm -it --name ipfs_host -p 4001:4001 -p 4001:4001/udp -p 8080:8080 -p 5001:5001 ipfs/kubo");
8 println!("Note: If you get CORS errors, configure CORS with:");
9 println!(" docker exec ipfs_host ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '[\"*\"]'");
10 println!(" docker exec ipfs_host ipfs config --json API.HTTPHeaders.Access-Control-Allow-Methods '[\"GET\", \"POST\", \"PUT\", \"DELETE\", \"OPTIONS\"]'");
11 println!(" docker restart ipfs_host\n");
12
13 // Create HTTP client configured for IPFS RPC API
14 let client = HttpClient::builder()
15 .timeout(30000) // 30 seconds for file operations
16 .build();
17
18 let ipfs_api_base = "http://localhost:5001/api/v0";
19
20 // Example 1: Simple POST request - Get node version
21 println!("1. GET node version (POST with no body):");
22 match client.post(format!("{}/version", ipfs_api_base)).send() {
23 Ok(response) => {
24 println!(" Status: {}", response.status());
25 if response.is_success() {
26 if let Ok(version_info) = response.json::<serde_json::Value>() {
27 println!(
28 " IPFS Version: {}",
29 version_info
30 .get("Version")
31 .and_then(|v| v.as_str())
32 .unwrap_or("unknown")
33 );
34 println!(
35 " Commit: {}",
36 version_info
37 .get("Commit")
38 .and_then(|c| c.as_str())
39 .unwrap_or("unknown")
40 );
41 }
42 }
43 }
44 Err(e) => println!(" Error: {} (Is IPFS running?)", e),
45 }
46
47 // Example 2: POST with query parameters - Get node ID
48 println!("\n2. GET node ID (POST with query parameters):");
49 match client
50 .post(format!("{}/id", ipfs_api_base))
51 .query("format", "json")
52 .send()
53 {
54 Ok(response) => {
55 println!(" Status: {}", response.status());
56 if response.is_success() {
57 if let Ok(id_info) = response.json::<serde_json::Value>() {
58 println!(
59 " Node ID: {}",
60 id_info
61 .get("ID")
62 .and_then(|id| id.as_str())
63 .unwrap_or("unknown")
64 );
65 if let Some(addresses) = id_info.get("Addresses") {
66 if let Some(addr_array) = addresses.as_array() {
67 if !addr_array.is_empty() {
68 println!(" First Address: {}", addr_array[0]);
69 }
70 }
71 }
72 }
73 }
74 }
75 Err(e) => println!(" Error: {}", e),
76 }
77
78 // Example 3: POST with multipart file upload - Add file to IPFS
79 println!("\n3. ADD file to IPFS (POST with multipart upload):");
80 let file_content = b"Hello from Blockless SDK HTTP v2 client!\nThis file was uploaded to IPFS using multipart form data.";
81 let multipart_fields = vec![MultipartField::file(
82 "file", // IPFS expects 'file' as the field name
83 file_content.to_vec(),
84 "hello-blockless.txt",
85 Some("text/plain".to_string()),
86 )];
87
88 match client
89 .post(format!("{}/add", ipfs_api_base))
90 .query("pin", "true") // Pin the file after adding
91 .multipart(multipart_fields)
92 .send()
93 {
94 Ok(response) => {
95 println!(" Status: {}", response.status());
96 if response.is_success() {
97 if let Ok(add_result) = response.json::<serde_json::Value>() {
98 let hash = add_result
99 .get("Hash")
100 .and_then(|h| h.as_str())
101 .unwrap_or("unknown");
102 let name = add_result
103 .get("Name")
104 .and_then(|n| n.as_str())
105 .unwrap_or("unknown");
106 let size = add_result
107 .get("Size")
108 .and_then(|s| s.as_str())
109 .unwrap_or("0");
110 println!(" Added file: {}", name);
111 println!(" IPFS Hash: {}", hash);
112 println!(" Size: {} bytes", size);
113
114 // Store hash for later examples
115 if hash != "unknown" {
116 demonstrate_file_operations(&client, ipfs_api_base, hash)?;
117 }
118 }
119 }
120 }
121 Err(e) => println!(" Error: {}", e),
122 }
123
124 // Example 4: Repository stats (POST with query parameters)
125 println!("\n4. GET repository statistics (POST with boolean parameters):");
126 match client
127 .post(format!("{}/repo/stat", ipfs_api_base))
128 .query("human", "true")
129 .send()
130 {
131 Ok(response) => {
132 println!(" Status: {}", response.status());
133 if response.is_success() {
134 if let Ok(repo_stats) = response.json::<serde_json::Value>() {
135 println!(
136 " Repo Size: {}",
137 repo_stats
138 .get("RepoSize")
139 .unwrap_or(&serde_json::Value::Number(0.into()))
140 );
141 println!(
142 " Storage Max: {}",
143 repo_stats
144 .get("StorageMax")
145 .unwrap_or(&serde_json::Value::Number(0.into()))
146 );
147 println!(
148 " Num Objects: {}",
149 repo_stats
150 .get("NumObjects")
151 .unwrap_or(&serde_json::Value::Number(0.into()))
152 );
153 }
154 }
155 }
156 Err(e) => println!(" Error: {}", e),
157 }
158
159 // Example 5: Pin operations - List pinned objects
160 println!("\n5. LIST pinned objects (POST with type filter):");
161 match client
162 .post(format!("{}/pin/ls", ipfs_api_base))
163 .query("type", "recursive")
164 .query("stream", "true")
165 .send()
166 {
167 Ok(response) => {
168 println!(" Status: {}", response.status());
169 if response.is_success() {
170 if let Ok(pin_list) = response.json::<serde_json::Value>() {
171 if let Some(keys) = pin_list.get("Keys").and_then(|k| k.as_object()) {
172 println!(" Pinned objects count: {}", keys.len());
173 // Show first few pinned objects
174 for (hash, info) in keys.iter().take(3) {
175 if let Some(pin_type) = info.get("Type") {
176 println!(" - {} ({})", hash, pin_type);
177 }
178 }
179 if keys.len() > 3 {
180 println!(" ... and {} more", keys.len() - 3);
181 }
182 }
183 }
184 }
185 }
186 Err(e) => println!(" Error: {}", e),
187 }
188
189 // Example 6: Module-level convenience function
190 println!("\n6. GET swarm peers (using module-level function):");
191 match post(format!("{}/swarm/peers", ipfs_api_base))
192 .query("verbose", "false")
193 .send()
194 {
195 Ok(response) => {
196 println!(" Status: {}", response.status());
197 if response.is_success() {
198 if let Ok(peers_info) = response.json::<serde_json::Value>() {
199 if let Some(peers) = peers_info.get("Peers").and_then(|p| p.as_array()) {
200 println!(" Connected peers: {}", peers.len());
201 // Show first few peers
202 for peer in peers.iter().take(2) {
203 if let Some(peer_id) = peer.get("Peer") {
204 if let Some(addr) = peer.get("Addr") {
205 println!(
206 " - Peer: {}...{}",
207 &peer_id.as_str().unwrap_or("")[..8],
208 &peer_id.as_str().unwrap_or("")[peer_id
209 .as_str()
210 .unwrap_or("")
211 .len()
212 .saturating_sub(8)..]
213 );
214 println!(" Address: {}", addr);
215 }
216 }
217 }
218 if peers.len() > 2 {
219 println!(" ... and {} more peers", peers.len() - 2);
220 }
221 }
222 }
223 }
224 }
225 Err(e) => println!(" Error: {}", e),
226 }
227
228 println!("\n✅ IPFS API Demo completed!");
229 println!("This example demonstrated:");
230 println!(" • POST requests with no body (version, id)");
231 println!(" • POST with query parameters (repo/stat, pin/ls)");
232 println!(" • POST with multipart file upload (add)");
233 println!(" • POST with binary responses (cat - in demonstrate_file_operations)");
234 println!(" • Module-level convenience functions (swarm/peers)");
235 println!(" • Different response types (JSON, binary)");
236
237 Ok(())
238}Sourcepub fn get<U: Into<String>>(&self, url: U) -> RequestBuilder
pub fn get<U: Into<String>>(&self, url: U) -> RequestBuilder
Examples found in repository?
examples/coingecko_oracle.rs (line 27)
13fn main() {
14 // read coin id from stdin
15 let mut buf = [0; 1024];
16 let len = read_stdin(&mut buf).unwrap();
17 let coin_id = std::str::from_utf8(&buf[..len as usize])
18 .unwrap_or_default()
19 .trim();
20
21 // perform http request
22 let client = HttpClient::new();
23 let url = format!(
24 "https://api.coingecko.com/api/v3/simple/price?ids={}&vs_currencies=usd",
25 coin_id
26 );
27 let response = client.get(&url).send().unwrap();
28 let body = response.bytes().to_vec(); // e.g. {"bitcoin":{"usd":67675}}
29
30 // println!("{}", String::from_utf8(body.clone()).unwrap());
31
32 // parse the json response; extrac usd price
33 let json: serde_json::Result<HashMap<String, HashMap<String, f64>>> =
34 serde_json::from_slice(&body);
35 let Ok(data) = json else {
36 eprintln!("Failed to parse JSON");
37 return;
38 };
39 let Some(coin_data) = data.get(coin_id) else {
40 eprintln!("Coin not found in response.");
41 return;
42 };
43 let Some(usd_price) = coin_data.get("usd") else {
44 eprintln!("USD price not found for {}.", coin_id);
45 return;
46 };
47
48 let coin_price = CoinPrice {
49 id: coin_id.to_string(),
50 price: (*usd_price * 1_000_000.0) as u64, // price in 6 decimals
51 currency: "usd".to_string(),
52 };
53 println!("{}", json!(coin_price));
54}More examples
examples/http_client.rs (line 45)
4fn main() -> Result<(), Box<dyn std::error::Error>> {
5 println!("====================================");
6 println!("HTTP v2 Client Demo");
7 println!("====================================");
8
9 println!("\n1. GET request:");
10 match get("https://httpbin.org/get").send() {
11 Ok(response) => {
12 println!("GET Status: {}", response.status());
13 println!("GET Success: {}", response.is_success());
14 }
15 Err(e) => println!("GET Error: {}", e),
16 }
17
18 println!("\n2. POST with JSON:");
19 let json_data = serde_json::json!({
20 "name": "Blockless SDK",
21 "version": "2.0",
22 "api_style": "reqwest-like"
23 });
24 match post("https://httpbin.org/post").json(&json_data)?.send() {
25 Ok(response) => {
26 println!("POST JSON Status: {}", response.status());
27 if let Ok(response_json) = response.json::<serde_json::Value>() {
28 if let Some(received_json) = response_json.get("json") {
29 println!("Received JSON: {}", received_json);
30 }
31 }
32 }
33 Err(e) => println!("POST JSON Error: {}", e),
34 }
35
36 println!("\n3. Client instance with default configuration:");
37 let mut default_headers = HashMap::new();
38 default_headers.insert("User-Agent".to_string(), "Blockless-SDK/2.0".to_string());
39 default_headers.insert("Accept".to_string(), "application/json".to_string());
40 let client = HttpClient::builder()
41 .default_headers(default_headers)
42 .timeout(10000)
43 .build();
44 match client
45 .get("https://httpbin.org/get")
46 .query("search", "blockless")
47 .query("limit", "10")
48 .query("format", "json")
49 .send()
50 {
51 Ok(response) => {
52 println!("Client GET Status: {}", response.status());
53 if let Ok(json_data) = response.json::<serde_json::Value>() {
54 if let Some(args) = json_data.get("args") {
55 println!("Query params: {}", args);
56 }
57 }
58 }
59 Err(e) => println!("Client GET Error: {}", e),
60 }
61
62 println!("\n4. Authentication examples:");
63 match client
64 .get("https://httpbin.org/basic-auth/user/pass")
65 .basic_auth("user", "pass")
66 .send()
67 {
68 Ok(response) => {
69 println!("Basic auth status: {}", response.status());
70 if let Ok(json_data) = response.json::<serde_json::Value>() {
71 println!("Authenticated: {:?}", json_data.get("authenticated"));
72 }
73 }
74 Err(e) => println!("Basic auth error: {}", e),
75 }
76
77 match client
78 .get("https://httpbin.org/bearer")
79 .bearer_auth("test-token-12345")
80 .send()
81 {
82 Ok(response) => {
83 println!("Bearer auth status: {}", response.status());
84 if let Ok(json_data) = response.json::<serde_json::Value>() {
85 println!("Token received: {:?}", json_data.get("token"));
86 }
87 }
88 Err(e) => println!("Bearer auth error: {}", e),
89 }
90
91 println!("\n5. Different request body types:");
92 let mut form_data = HashMap::new();
93 form_data.insert("name".to_string(), "Blockless".to_string());
94 form_data.insert("type".to_string(), "distributed computing".to_string());
95 match client
96 .post("https://httpbin.org/post")
97 .form(form_data)
98 .send()
99 {
100 Ok(response) => {
101 println!("Form POST Status: {}", response.status());
102 if let Ok(json_data) = response.json::<serde_json::Value>() {
103 if let Some(form) = json_data.get("form") {
104 println!("Form data received: {}", form);
105 }
106 }
107 }
108 Err(e) => println!("Form POST Error: {}", e),
109 }
110
111 println!("\n6. Multipart form with file upload:");
112 let multipart_fields = vec![
113 MultipartField::text("description", "SDK test file"),
114 MultipartField::file(
115 "upload",
116 b"Hello from Blockless SDK v2!".to_vec(),
117 "hello.txt",
118 Some("text/plain".to_string()),
119 ),
120 ];
121 match client
122 .post("https://httpbin.org/post")
123 .multipart(multipart_fields)
124 .send()
125 {
126 Ok(response) => {
127 println!("Multipart POST Status: {}", response.status());
128 if let Ok(json_data) = response.json::<serde_json::Value>() {
129 if let Some(files) = json_data.get("files") {
130 println!("Files uploaded: {}", files);
131 }
132 }
133 }
134 Err(e) => println!("Multipart POST Error: {}", e),
135 }
136
137 println!("\n7. Binary data:");
138 let binary_data = vec![0x48, 0x65, 0x6c, 0x6c, 0x6f]; // "Hello" in bytes
139 match client
140 .post("https://httpbin.org/post")
141 .header("Content-Type", "application/octet-stream")
142 .body_bytes(binary_data)
143 .send()
144 {
145 Ok(response) => {
146 println!("Binary POST Status: {}", response.status());
147 }
148 Err(e) => println!("Binary POST Error: {}", e),
149 }
150
151 println!("\n8. Advanced request building:");
152 match client
153 .put("https://httpbin.org/put")
154 .header("X-Custom-Header", "custom-value")
155 .header("X-API-Version", "2.0")
156 .query("action", "update")
157 .query("id", "12345")
158 .timeout(5000)
159 .body("Updated data")
160 .send()
161 {
162 Ok(response) => {
163 println!("PUT Status: {}", response.status());
164 if let Ok(json_data) = response.json::<serde_json::Value>() {
165 if let Some(headers) = json_data.get("headers") {
166 println!("Custom headers received: {}", headers);
167 }
168 }
169 }
170 Err(e) => println!("PUT Error: {}", e),
171 }
172
173 println!("\nDemo completed 🚀");
174 Ok(())
175}Sourcepub fn post<U: Into<String>>(&self, url: U) -> RequestBuilder
pub fn post<U: Into<String>>(&self, url: U) -> RequestBuilder
Examples found in repository?
examples/http_client.rs (line 96)
4fn main() -> Result<(), Box<dyn std::error::Error>> {
5 println!("====================================");
6 println!("HTTP v2 Client Demo");
7 println!("====================================");
8
9 println!("\n1. GET request:");
10 match get("https://httpbin.org/get").send() {
11 Ok(response) => {
12 println!("GET Status: {}", response.status());
13 println!("GET Success: {}", response.is_success());
14 }
15 Err(e) => println!("GET Error: {}", e),
16 }
17
18 println!("\n2. POST with JSON:");
19 let json_data = serde_json::json!({
20 "name": "Blockless SDK",
21 "version": "2.0",
22 "api_style": "reqwest-like"
23 });
24 match post("https://httpbin.org/post").json(&json_data)?.send() {
25 Ok(response) => {
26 println!("POST JSON Status: {}", response.status());
27 if let Ok(response_json) = response.json::<serde_json::Value>() {
28 if let Some(received_json) = response_json.get("json") {
29 println!("Received JSON: {}", received_json);
30 }
31 }
32 }
33 Err(e) => println!("POST JSON Error: {}", e),
34 }
35
36 println!("\n3. Client instance with default configuration:");
37 let mut default_headers = HashMap::new();
38 default_headers.insert("User-Agent".to_string(), "Blockless-SDK/2.0".to_string());
39 default_headers.insert("Accept".to_string(), "application/json".to_string());
40 let client = HttpClient::builder()
41 .default_headers(default_headers)
42 .timeout(10000)
43 .build();
44 match client
45 .get("https://httpbin.org/get")
46 .query("search", "blockless")
47 .query("limit", "10")
48 .query("format", "json")
49 .send()
50 {
51 Ok(response) => {
52 println!("Client GET Status: {}", response.status());
53 if let Ok(json_data) = response.json::<serde_json::Value>() {
54 if let Some(args) = json_data.get("args") {
55 println!("Query params: {}", args);
56 }
57 }
58 }
59 Err(e) => println!("Client GET Error: {}", e),
60 }
61
62 println!("\n4. Authentication examples:");
63 match client
64 .get("https://httpbin.org/basic-auth/user/pass")
65 .basic_auth("user", "pass")
66 .send()
67 {
68 Ok(response) => {
69 println!("Basic auth status: {}", response.status());
70 if let Ok(json_data) = response.json::<serde_json::Value>() {
71 println!("Authenticated: {:?}", json_data.get("authenticated"));
72 }
73 }
74 Err(e) => println!("Basic auth error: {}", e),
75 }
76
77 match client
78 .get("https://httpbin.org/bearer")
79 .bearer_auth("test-token-12345")
80 .send()
81 {
82 Ok(response) => {
83 println!("Bearer auth status: {}", response.status());
84 if let Ok(json_data) = response.json::<serde_json::Value>() {
85 println!("Token received: {:?}", json_data.get("token"));
86 }
87 }
88 Err(e) => println!("Bearer auth error: {}", e),
89 }
90
91 println!("\n5. Different request body types:");
92 let mut form_data = HashMap::new();
93 form_data.insert("name".to_string(), "Blockless".to_string());
94 form_data.insert("type".to_string(), "distributed computing".to_string());
95 match client
96 .post("https://httpbin.org/post")
97 .form(form_data)
98 .send()
99 {
100 Ok(response) => {
101 println!("Form POST Status: {}", response.status());
102 if let Ok(json_data) = response.json::<serde_json::Value>() {
103 if let Some(form) = json_data.get("form") {
104 println!("Form data received: {}", form);
105 }
106 }
107 }
108 Err(e) => println!("Form POST Error: {}", e),
109 }
110
111 println!("\n6. Multipart form with file upload:");
112 let multipart_fields = vec![
113 MultipartField::text("description", "SDK test file"),
114 MultipartField::file(
115 "upload",
116 b"Hello from Blockless SDK v2!".to_vec(),
117 "hello.txt",
118 Some("text/plain".to_string()),
119 ),
120 ];
121 match client
122 .post("https://httpbin.org/post")
123 .multipart(multipart_fields)
124 .send()
125 {
126 Ok(response) => {
127 println!("Multipart POST Status: {}", response.status());
128 if let Ok(json_data) = response.json::<serde_json::Value>() {
129 if let Some(files) = json_data.get("files") {
130 println!("Files uploaded: {}", files);
131 }
132 }
133 }
134 Err(e) => println!("Multipart POST Error: {}", e),
135 }
136
137 println!("\n7. Binary data:");
138 let binary_data = vec![0x48, 0x65, 0x6c, 0x6c, 0x6f]; // "Hello" in bytes
139 match client
140 .post("https://httpbin.org/post")
141 .header("Content-Type", "application/octet-stream")
142 .body_bytes(binary_data)
143 .send()
144 {
145 Ok(response) => {
146 println!("Binary POST Status: {}", response.status());
147 }
148 Err(e) => println!("Binary POST Error: {}", e),
149 }
150
151 println!("\n8. Advanced request building:");
152 match client
153 .put("https://httpbin.org/put")
154 .header("X-Custom-Header", "custom-value")
155 .header("X-API-Version", "2.0")
156 .query("action", "update")
157 .query("id", "12345")
158 .timeout(5000)
159 .body("Updated data")
160 .send()
161 {
162 Ok(response) => {
163 println!("PUT Status: {}", response.status());
164 if let Ok(json_data) = response.json::<serde_json::Value>() {
165 if let Some(headers) = json_data.get("headers") {
166 println!("Custom headers received: {}", headers);
167 }
168 }
169 }
170 Err(e) => println!("PUT Error: {}", e),
171 }
172
173 println!("\nDemo completed 🚀");
174 Ok(())
175}More examples
examples/ipfs_api.rs (line 22)
3fn main() -> Result<(), Box<dyn std::error::Error>> {
4 println!("IPFS RPC API Demo - HTTP v2 Client");
5 println!("=================================");
6 println!("Make sure your IPFS node is running on localhost:5001");
7 println!("Docker command: docker run --rm -it --name ipfs_host -p 4001:4001 -p 4001:4001/udp -p 8080:8080 -p 5001:5001 ipfs/kubo");
8 println!("Note: If you get CORS errors, configure CORS with:");
9 println!(" docker exec ipfs_host ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '[\"*\"]'");
10 println!(" docker exec ipfs_host ipfs config --json API.HTTPHeaders.Access-Control-Allow-Methods '[\"GET\", \"POST\", \"PUT\", \"DELETE\", \"OPTIONS\"]'");
11 println!(" docker restart ipfs_host\n");
12
13 // Create HTTP client configured for IPFS RPC API
14 let client = HttpClient::builder()
15 .timeout(30000) // 30 seconds for file operations
16 .build();
17
18 let ipfs_api_base = "http://localhost:5001/api/v0";
19
20 // Example 1: Simple POST request - Get node version
21 println!("1. GET node version (POST with no body):");
22 match client.post(format!("{}/version", ipfs_api_base)).send() {
23 Ok(response) => {
24 println!(" Status: {}", response.status());
25 if response.is_success() {
26 if let Ok(version_info) = response.json::<serde_json::Value>() {
27 println!(
28 " IPFS Version: {}",
29 version_info
30 .get("Version")
31 .and_then(|v| v.as_str())
32 .unwrap_or("unknown")
33 );
34 println!(
35 " Commit: {}",
36 version_info
37 .get("Commit")
38 .and_then(|c| c.as_str())
39 .unwrap_or("unknown")
40 );
41 }
42 }
43 }
44 Err(e) => println!(" Error: {} (Is IPFS running?)", e),
45 }
46
47 // Example 2: POST with query parameters - Get node ID
48 println!("\n2. GET node ID (POST with query parameters):");
49 match client
50 .post(format!("{}/id", ipfs_api_base))
51 .query("format", "json")
52 .send()
53 {
54 Ok(response) => {
55 println!(" Status: {}", response.status());
56 if response.is_success() {
57 if let Ok(id_info) = response.json::<serde_json::Value>() {
58 println!(
59 " Node ID: {}",
60 id_info
61 .get("ID")
62 .and_then(|id| id.as_str())
63 .unwrap_or("unknown")
64 );
65 if let Some(addresses) = id_info.get("Addresses") {
66 if let Some(addr_array) = addresses.as_array() {
67 if !addr_array.is_empty() {
68 println!(" First Address: {}", addr_array[0]);
69 }
70 }
71 }
72 }
73 }
74 }
75 Err(e) => println!(" Error: {}", e),
76 }
77
78 // Example 3: POST with multipart file upload - Add file to IPFS
79 println!("\n3. ADD file to IPFS (POST with multipart upload):");
80 let file_content = b"Hello from Blockless SDK HTTP v2 client!\nThis file was uploaded to IPFS using multipart form data.";
81 let multipart_fields = vec![MultipartField::file(
82 "file", // IPFS expects 'file' as the field name
83 file_content.to_vec(),
84 "hello-blockless.txt",
85 Some("text/plain".to_string()),
86 )];
87
88 match client
89 .post(format!("{}/add", ipfs_api_base))
90 .query("pin", "true") // Pin the file after adding
91 .multipart(multipart_fields)
92 .send()
93 {
94 Ok(response) => {
95 println!(" Status: {}", response.status());
96 if response.is_success() {
97 if let Ok(add_result) = response.json::<serde_json::Value>() {
98 let hash = add_result
99 .get("Hash")
100 .and_then(|h| h.as_str())
101 .unwrap_or("unknown");
102 let name = add_result
103 .get("Name")
104 .and_then(|n| n.as_str())
105 .unwrap_or("unknown");
106 let size = add_result
107 .get("Size")
108 .and_then(|s| s.as_str())
109 .unwrap_or("0");
110 println!(" Added file: {}", name);
111 println!(" IPFS Hash: {}", hash);
112 println!(" Size: {} bytes", size);
113
114 // Store hash for later examples
115 if hash != "unknown" {
116 demonstrate_file_operations(&client, ipfs_api_base, hash)?;
117 }
118 }
119 }
120 }
121 Err(e) => println!(" Error: {}", e),
122 }
123
124 // Example 4: Repository stats (POST with query parameters)
125 println!("\n4. GET repository statistics (POST with boolean parameters):");
126 match client
127 .post(format!("{}/repo/stat", ipfs_api_base))
128 .query("human", "true")
129 .send()
130 {
131 Ok(response) => {
132 println!(" Status: {}", response.status());
133 if response.is_success() {
134 if let Ok(repo_stats) = response.json::<serde_json::Value>() {
135 println!(
136 " Repo Size: {}",
137 repo_stats
138 .get("RepoSize")
139 .unwrap_or(&serde_json::Value::Number(0.into()))
140 );
141 println!(
142 " Storage Max: {}",
143 repo_stats
144 .get("StorageMax")
145 .unwrap_or(&serde_json::Value::Number(0.into()))
146 );
147 println!(
148 " Num Objects: {}",
149 repo_stats
150 .get("NumObjects")
151 .unwrap_or(&serde_json::Value::Number(0.into()))
152 );
153 }
154 }
155 }
156 Err(e) => println!(" Error: {}", e),
157 }
158
159 // Example 5: Pin operations - List pinned objects
160 println!("\n5. LIST pinned objects (POST with type filter):");
161 match client
162 .post(format!("{}/pin/ls", ipfs_api_base))
163 .query("type", "recursive")
164 .query("stream", "true")
165 .send()
166 {
167 Ok(response) => {
168 println!(" Status: {}", response.status());
169 if response.is_success() {
170 if let Ok(pin_list) = response.json::<serde_json::Value>() {
171 if let Some(keys) = pin_list.get("Keys").and_then(|k| k.as_object()) {
172 println!(" Pinned objects count: {}", keys.len());
173 // Show first few pinned objects
174 for (hash, info) in keys.iter().take(3) {
175 if let Some(pin_type) = info.get("Type") {
176 println!(" - {} ({})", hash, pin_type);
177 }
178 }
179 if keys.len() > 3 {
180 println!(" ... and {} more", keys.len() - 3);
181 }
182 }
183 }
184 }
185 }
186 Err(e) => println!(" Error: {}", e),
187 }
188
189 // Example 6: Module-level convenience function
190 println!("\n6. GET swarm peers (using module-level function):");
191 match post(format!("{}/swarm/peers", ipfs_api_base))
192 .query("verbose", "false")
193 .send()
194 {
195 Ok(response) => {
196 println!(" Status: {}", response.status());
197 if response.is_success() {
198 if let Ok(peers_info) = response.json::<serde_json::Value>() {
199 if let Some(peers) = peers_info.get("Peers").and_then(|p| p.as_array()) {
200 println!(" Connected peers: {}", peers.len());
201 // Show first few peers
202 for peer in peers.iter().take(2) {
203 if let Some(peer_id) = peer.get("Peer") {
204 if let Some(addr) = peer.get("Addr") {
205 println!(
206 " - Peer: {}...{}",
207 &peer_id.as_str().unwrap_or("")[..8],
208 &peer_id.as_str().unwrap_or("")[peer_id
209 .as_str()
210 .unwrap_or("")
211 .len()
212 .saturating_sub(8)..]
213 );
214 println!(" Address: {}", addr);
215 }
216 }
217 }
218 if peers.len() > 2 {
219 println!(" ... and {} more peers", peers.len() - 2);
220 }
221 }
222 }
223 }
224 }
225 Err(e) => println!(" Error: {}", e),
226 }
227
228 println!("\n✅ IPFS API Demo completed!");
229 println!("This example demonstrated:");
230 println!(" • POST requests with no body (version, id)");
231 println!(" • POST with query parameters (repo/stat, pin/ls)");
232 println!(" • POST with multipart file upload (add)");
233 println!(" • POST with binary responses (cat - in demonstrate_file_operations)");
234 println!(" • Module-level convenience functions (swarm/peers)");
235 println!(" • Different response types (JSON, binary)");
236
237 Ok(())
238}
239
240/// Demonstrates file operations with the uploaded file
241fn demonstrate_file_operations(
242 client: &HttpClient,
243 api_base: &str,
244 file_hash: &str,
245) -> Result<(), Box<dyn std::error::Error>> {
246 // Example: Get file content (binary response)
247 println!("\n 📄 GET file content (POST returning binary data):");
248 match client
249 .post(format!("{}/cat", api_base))
250 .query("arg", file_hash)
251 .send()
252 {
253 Ok(response) => {
254 println!(" Status: {}", response.status());
255 if response.is_success() {
256 match response.text() {
257 Ok(content) => {
258 println!(
259 " File content: {}",
260 content.lines().next().unwrap_or("empty")
261 );
262 println!(" Content length: {} bytes", content.len());
263 }
264 Err(_) => {
265 println!(" Binary content: {} bytes", response.bytes().len());
266 }
267 }
268 }
269 }
270 Err(e) => println!(" Error: {}", e),
271 }
272
273 // Example: Pin the file explicitly (idempotent operation)
274 println!("\n 📌 PIN file (POST with path parameter):");
275 match client
276 .post(format!("{}/pin/add", api_base))
277 .query("arg", file_hash)
278 .query("recursive", "false")
279 .send()
280 {
281 Ok(response) => {
282 println!(" Status: {}", response.status());
283 if response.is_success() {
284 if let Ok(pin_result) = response.json::<serde_json::Value>() {
285 if let Some(pins) = pin_result.get("Pins").and_then(|p| p.as_array()) {
286 println!(" Pinned {} objects", pins.len());
287 for pin in pins {
288 println!(" - {}", pin.as_str().unwrap_or("unknown"));
289 }
290 }
291 }
292 }
293 }
294 Err(e) => println!(" Error: {}", e),
295 }
296
297 Ok(())
298}Sourcepub fn put<U: Into<String>>(&self, url: U) -> RequestBuilder
pub fn put<U: Into<String>>(&self, url: U) -> RequestBuilder
Examples found in repository?
examples/http_client.rs (line 153)
4fn main() -> Result<(), Box<dyn std::error::Error>> {
5 println!("====================================");
6 println!("HTTP v2 Client Demo");
7 println!("====================================");
8
9 println!("\n1. GET request:");
10 match get("https://httpbin.org/get").send() {
11 Ok(response) => {
12 println!("GET Status: {}", response.status());
13 println!("GET Success: {}", response.is_success());
14 }
15 Err(e) => println!("GET Error: {}", e),
16 }
17
18 println!("\n2. POST with JSON:");
19 let json_data = serde_json::json!({
20 "name": "Blockless SDK",
21 "version": "2.0",
22 "api_style": "reqwest-like"
23 });
24 match post("https://httpbin.org/post").json(&json_data)?.send() {
25 Ok(response) => {
26 println!("POST JSON Status: {}", response.status());
27 if let Ok(response_json) = response.json::<serde_json::Value>() {
28 if let Some(received_json) = response_json.get("json") {
29 println!("Received JSON: {}", received_json);
30 }
31 }
32 }
33 Err(e) => println!("POST JSON Error: {}", e),
34 }
35
36 println!("\n3. Client instance with default configuration:");
37 let mut default_headers = HashMap::new();
38 default_headers.insert("User-Agent".to_string(), "Blockless-SDK/2.0".to_string());
39 default_headers.insert("Accept".to_string(), "application/json".to_string());
40 let client = HttpClient::builder()
41 .default_headers(default_headers)
42 .timeout(10000)
43 .build();
44 match client
45 .get("https://httpbin.org/get")
46 .query("search", "blockless")
47 .query("limit", "10")
48 .query("format", "json")
49 .send()
50 {
51 Ok(response) => {
52 println!("Client GET Status: {}", response.status());
53 if let Ok(json_data) = response.json::<serde_json::Value>() {
54 if let Some(args) = json_data.get("args") {
55 println!("Query params: {}", args);
56 }
57 }
58 }
59 Err(e) => println!("Client GET Error: {}", e),
60 }
61
62 println!("\n4. Authentication examples:");
63 match client
64 .get("https://httpbin.org/basic-auth/user/pass")
65 .basic_auth("user", "pass")
66 .send()
67 {
68 Ok(response) => {
69 println!("Basic auth status: {}", response.status());
70 if let Ok(json_data) = response.json::<serde_json::Value>() {
71 println!("Authenticated: {:?}", json_data.get("authenticated"));
72 }
73 }
74 Err(e) => println!("Basic auth error: {}", e),
75 }
76
77 match client
78 .get("https://httpbin.org/bearer")
79 .bearer_auth("test-token-12345")
80 .send()
81 {
82 Ok(response) => {
83 println!("Bearer auth status: {}", response.status());
84 if let Ok(json_data) = response.json::<serde_json::Value>() {
85 println!("Token received: {:?}", json_data.get("token"));
86 }
87 }
88 Err(e) => println!("Bearer auth error: {}", e),
89 }
90
91 println!("\n5. Different request body types:");
92 let mut form_data = HashMap::new();
93 form_data.insert("name".to_string(), "Blockless".to_string());
94 form_data.insert("type".to_string(), "distributed computing".to_string());
95 match client
96 .post("https://httpbin.org/post")
97 .form(form_data)
98 .send()
99 {
100 Ok(response) => {
101 println!("Form POST Status: {}", response.status());
102 if let Ok(json_data) = response.json::<serde_json::Value>() {
103 if let Some(form) = json_data.get("form") {
104 println!("Form data received: {}", form);
105 }
106 }
107 }
108 Err(e) => println!("Form POST Error: {}", e),
109 }
110
111 println!("\n6. Multipart form with file upload:");
112 let multipart_fields = vec![
113 MultipartField::text("description", "SDK test file"),
114 MultipartField::file(
115 "upload",
116 b"Hello from Blockless SDK v2!".to_vec(),
117 "hello.txt",
118 Some("text/plain".to_string()),
119 ),
120 ];
121 match client
122 .post("https://httpbin.org/post")
123 .multipart(multipart_fields)
124 .send()
125 {
126 Ok(response) => {
127 println!("Multipart POST Status: {}", response.status());
128 if let Ok(json_data) = response.json::<serde_json::Value>() {
129 if let Some(files) = json_data.get("files") {
130 println!("Files uploaded: {}", files);
131 }
132 }
133 }
134 Err(e) => println!("Multipart POST Error: {}", e),
135 }
136
137 println!("\n7. Binary data:");
138 let binary_data = vec![0x48, 0x65, 0x6c, 0x6c, 0x6f]; // "Hello" in bytes
139 match client
140 .post("https://httpbin.org/post")
141 .header("Content-Type", "application/octet-stream")
142 .body_bytes(binary_data)
143 .send()
144 {
145 Ok(response) => {
146 println!("Binary POST Status: {}", response.status());
147 }
148 Err(e) => println!("Binary POST Error: {}", e),
149 }
150
151 println!("\n8. Advanced request building:");
152 match client
153 .put("https://httpbin.org/put")
154 .header("X-Custom-Header", "custom-value")
155 .header("X-API-Version", "2.0")
156 .query("action", "update")
157 .query("id", "12345")
158 .timeout(5000)
159 .body("Updated data")
160 .send()
161 {
162 Ok(response) => {
163 println!("PUT Status: {}", response.status());
164 if let Ok(json_data) = response.json::<serde_json::Value>() {
165 if let Some(headers) = json_data.get("headers") {
166 println!("Custom headers received: {}", headers);
167 }
168 }
169 }
170 Err(e) => println!("PUT Error: {}", e),
171 }
172
173 println!("\nDemo completed 🚀");
174 Ok(())
175}pub fn patch<U: Into<String>>(&self, url: U) -> RequestBuilder
pub fn delete<U: Into<String>>(&self, url: U) -> RequestBuilder
pub fn head<U: Into<String>>(&self, url: U) -> RequestBuilder
pub fn request<U: Into<String>>(&self, method: &str, url: U) -> RequestBuilder
Trait Implementations§
Source§impl Clone for HttpClient
impl Clone for HttpClient
Auto Trait Implementations§
impl Freeze for HttpClient
impl RefUnwindSafe for HttpClient
impl Send for HttpClient
impl Sync for HttpClient
impl Unpin for HttpClient
impl UnwindSafe for HttpClient
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more