{"id":2850,"date":"2022-07-15T07:33:01","date_gmt":"2022-07-15T12:33:01","guid":{"rendered":"https:\/\/www.becomebetterprogrammer.com\/?p=2850"},"modified":"2022-07-15T07:39:16","modified_gmt":"2022-07-15T12:39:16","slug":"rust-how-to-make-an-http-request","status":"publish","type":"post","link":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-how-to-make-an-http-request\/","title":{"rendered":"Rust | How To Make an HTTP Request in Rust? (Step-by-step)"},"content":{"rendered":"\n<p>If you are relatively new to Rust, you probably have gone through a decent learning curve to understand the programming language concepts. Working with hardcoded data in your projects is not common when working on real-world application, but rather making HTTP requests to fetch data from other APIs. After all, do you know how to make an HTTP request in Rust?<\/p>\n\n\n\n<p><b>Here are the steps to make an HTTP request in Request in Rust using Reqwest:<\/b><\/p>\n\n\n\n<ol class=\"wp-block-list\"><li><strong>Create a project<\/strong> <strong>(optional)<\/strong><\/li><li><strong>Add Reqwest and Tokio dependencies<\/strong><\/li><li><strong>Define the function to make an HTTP request using reqwest<\/strong><\/li><li><strong>Configure request accordingly such as passing additional headers (optional)<\/strong><\/li><li><strong>Deserialize HTTP response as JSON<\/strong><\/li><\/ol>\n\n\n\n<p>In this article, you will learn how to make an HTTP request in Rust using <a href=\"https:\/\/docs.rs\/reqwest\/latest\/reqwest\/\" target=\"_blank\" rel=\"noreferrer noopener\">Reqwest<\/a>. Don&#8217;t worry if you haven&#8217;t used Reqwest before. This article will explain how to use it as we go through this tutorial. Fortunately,  Reqwest makes it simple to make HTTP requests. <\/p>\n\n\n\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_82_2 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\"><p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<\/div><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-how-to-make-an-http-request\/#Steps_to_Make_an_HTTP_request_in_Rust\" >Steps to Make an HTTP request in Rust<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-how-to-make-an-http-request\/#1_Create_a_project_optional\" >1. Create a project (optional)<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-how-to-make-an-http-request\/#2_Add_Reqwest_and_Tokio_Dependencies\" >2. Add Reqwest and Tokio Dependencies<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-how-to-make-an-http-request\/#3_Define_the_function_to_make_an_HTTP_request_using_Reqwest\" >3. Define the function to make an HTTP request using Reqwest<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-how-to-make-an-http-request\/#Code_explanation\" >Code explanation<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-how-to-make-an-http-request\/#Run_the_code_to_test_it_works\" >Run the code to test it works<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-how-to-make-an-http-request\/#4_Configure_request_accordingly_such_as_passing_additional_headers_optional\" >4. Configure request accordingly such as passing additional headers (optional)<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-how-to-make-an-http-request\/#5_Deserialize_HTTP_response_as_JSON\" >5. Deserialize HTTP response as JSON<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-how-to-make-an-http-request\/#Add_Serde_dependency\" >Add Serde dependency<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-how-to-make-an-http-request\/#Define_response_struct\" >Define response struct<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-how-to-make-an-http-request\/#Apply_Deserialize_derive_macro\" >Apply Deserialize derive macro<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-how-to-make-an-http-request\/#Use_the_json_method_to_deserialize_the_response_body_as_JSON\" >Use the json() method to deserialize the response body as JSON<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-how-to-make-an-http-request\/#Update_the_functions_result_type\" >Update the function&#8217;s result type<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-how-to-make-an-http-request\/#Run_the_code_to_test_it_works-2\" >Run the code to test it works<\/a><\/li><\/ul><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-15\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-how-to-make-an-http-request\/#Understanding_Deserialization_JSON_errors\" >Understanding Deserialization JSON errors<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-16\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-how-to-make-an-http-request\/#Conclusion\" >Conclusion<\/a><\/li><\/ul><\/nav><\/div>\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Steps_to_Make_an_HTTP_request_in_Rust\"><\/span>Steps to Make an HTTP request in Rust <span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"1_Create_a_project_optional\"><\/span>1. Create a project (optional)<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>This step is optional if you are working off of an existing project. However, if you are rather starting from scratch, you will need to create a new project prior you add the code to make an HTTP request in Rust.<\/p>\n\n\n\n<p class=\"has-luminous-vivid-amber-background-color has-background\"><strong>Note<\/strong>: This project uses cargo CLI which is installed when installing Rust. If you haven&#8217;t installed Rust in your local machine, <a href=\"https:\/\/www.rust-lang.org\/tools\/install\" target=\"_blank\" rel=\"noopener\">follow the instructions to install Rust mentioned here<\/a> before you continue following this tutorial.<\/p>\n\n\n\n<p>Rust makes it easy to create a new project using the <code>cargo new<\/code> command. To use it, open your terminal in the directory where you want to create your Rust project and execute the <code>cargo new &lt;name_of_the_project><\/code> command. For this article, you can call the project <em>rust-make-http-request<\/em>. Hence, the command will look like this.<\/p>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>cargo new rust-make-http-request<\/code><\/pre>\n\n\n\n<p>This will generate a new folder called <em>rust-make-http-request<\/em> with a basic folder structure containing files such as cargo.toml and the main.rs.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"460\" height=\"255\" src=\"https:\/\/www.becomebetterprogrammer.com\/wp-content\/uploads\/2022\/06\/image-1.png\" alt=\"\" class=\"wp-image-2854\" srcset=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/06\/image-1.png 460w, https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/06\/image-1-300x166.png 300w\" sizes=\"auto, (max-width: 460px) 100vw, 460px\" \/><figcaption>Files generated after running <code>cargo new rust-make-http-request<\/code> command<\/figcaption><\/figure>\n<\/div>\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"2_Add_Reqwest_and_Tokio_Dependencies\"><\/span>2. Add Reqwest and Tokio Dependencies<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Rust projects use the cargo.toml file to define the project&#8217;s metadata such as the name and version. Also, it serves as the package manager. In other words, the cargo.toml file contains the lists of dependencies, called &#8220;crates&#8221;, that a Rust project uses. If you started a Rust project from scratch, most likely you won&#8217;t have any listed dependencies. <\/p>\n\n\n\n<p>Since you are going to make an HTTP request using the Reqwest crate, or dependency, we need to add it as part of the <code>[dependencies]<\/code> listed in the cargo.toml file as well as the <a href=\"https:\/\/crates.io\/crates\/tokio\" target=\"_blank\" rel=\"noopener\">Tokio<\/a>, a crate that allows running asynchronous  applications with Rust. Hence, add the following dependencies  under <code>[dependencies]<\/code> section.<\/p>\n\n\n\n<pre class=\"wp-block-code language-cargo\"><code>&#91;dependencies]\nreqwest = { version = \"0.11\", features = &#91;\"json\"] }\ntokio = { version = \"1\", features = &#91;\"full\"] }<\/code><\/pre>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow\">\n<p class=\"has-luminous-vivid-amber-background-color has-background\"><strong>Note:<\/strong> Once you save the changes to the cargo.toml file, cargo will automatically download the dependencies and update the cargo.lock file.<\/p>\n<\/div><\/div>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"3_Define_the_function_to_make_an_HTTP_request_using_Reqwest\"><\/span>3. Define the function to make an HTTP request using Reqwest<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>For this tutorial, you will use the <a href=\"https:\/\/catfact.ninja\/\" target=\"_blank\" rel=\"noopener\">Cat Fact Ninja API <\/a>to make a GET request to fetch a random fact about cats. The API endpoint you are going to use is <a href=\"https:\/\/catfact.ninjafact\/fact\" target=\"_blank\" rel=\"noopener\">https:\/\/catfact.ninjafact\/fact<\/a>.<\/p>\n\n\n\n<p>Open the main.rs file. By default, it should have generated a <code>main()<\/code> function using a <code>println!<\/code> macro to log &#8220;<em>Hello, world!<\/em>&#8220;. Replace that with the following code.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>#&#91;tokio::main]\nasync fn main() {\n    let fact = get_cat_fact().await;\n\n    println!(\"fact = {:#?}\", fact);\n}\n\nasync fn get_cat_fact() -&gt; Result&lt;String, Box&lt;dyn std::error::Error&gt;&gt; {\n    let client = reqwest::Client::new();\n    let body = client.get(\"https:\/\/catfact.ninja\/fact\").send()\n        .await?\n        .text()\n        .await?;\n\n    Ok(body)\n}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Code_explanation\"><\/span>Code explanation<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>If you have experience working with other programming languages and making HTTP requests, you might have a general idea of what is going on. However, I&#8217;ll walk you through the code explaining step-by-step.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Using <code>tokio:main<\/code> attribute<\/h5>\n\n\n\n<p>The first part to take a look at is the <code>main()<\/code> function.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>#&#91;tokio::main]\nasync fn main() {\n    let fact = get_cat_fact().await;\n\n    println!(\"fact = {:#?}\", fact);\n}<\/code><\/pre>\n\n\n\n<p>The main function calls the <code>get_cat_fact()<\/code> function to make a request to the Cat Fact Ninja API. Then, it logs the result in the terminal. Notice the usage of the <code>await<\/code> after-calling the <code>get_cat_fact()<\/code> function. This allows to wait until the asynchronous function finishes its process prior to moving on to the next line of code.<\/p>\n\n\n\n<p>To use <code>await<\/code> inside a function, the function must be an <code>async<\/code> function.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>#&#91;tokio::main]\nasync fn main() {}<\/code><\/pre>\n\n\n\n<p>Otherwise, you will get the following error:<code>error[E0728]: await is only allowed inside async functions and blocks<\/code> .<\/p>\n\n\n\n<p>Why does the <code>main<\/code> function use the <a href=\"https:\/\/docs.rs\/tokio\/0.2.2\/tokio\/attr.main.html?search=\" target=\"_blank\" rel=\"noopener\"><code>tokio::main<\/code><\/a> attribute?<\/p>\n\n\n\n<p>If you attempt to make the <code>main()<\/code> function <code>async<\/code> without using the <code>tokio::main<\/code> attribute, you will get the following error: <code>error[E0752]: main function is not allowed to be async<\/code> .<\/p>\n\n\n\n<p>As shared in the <a href=\"https:\/\/docs.rs\/tokio\/0.2.2\/tokio\/attr.main.html\" target=\"_blank\" rel=\"noopener\">documentation<\/a>, <code>tokio::main<\/code> &#8220;marks async function to be executed by the selected runtime.&#8221; Hence, using the <code>tokio::main<\/code> attribute allows the <code>main<\/code> function to use the <code>async<\/code> keyword.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Making the request to an API<\/h5>\n\n\n\n<p>In the<code>get_cat_fact<\/code> function, you make a request to the Cat Fact Ninja API. More specifically, to the <code>GET<\/code> facts endpoint, or <a href=\"https:\/\/catfact.ninja\/fact\" target=\"_blank\" rel=\"noopener\">https:\/\/catfact.ninja\/fact<\/a>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>async fn get_cat_fact() -&gt; Result&lt;String, Box&lt;dyn std::error::Error&gt;&gt; {\n    let client = reqwest::Client::new();\n    let body = client.get(\"https:\/\/catfact.ninja\/fact\").send()\n        .await?\n        .text()\n        .await?;\n\n    Ok(body)\n}<\/code><\/pre>\n\n\n\n<p>First, create the <code>client<\/code> variable that holds the <a href=\"https:\/\/docs.rs\/reqwest\/latest\/reqwest\/struct.Client.html\" target=\"_blank\" rel=\"noopener\">Client<\/a> to make requests.<\/p>\n\n\n\n<p>Then, you use the <a href=\"https:\/\/docs.rs\/reqwest\/latest\/reqwest\/struct.Client.html#method.get\" target=\"_blank\" rel=\"noopener\"><code>client.get<\/code> method<\/a> to make a <code>GET<\/code> request. In case you need to make a different type of request, such as a <code>POST<\/code> request, the <code>client<\/code> has available other convenient methods to make the requests:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>To make a <code>GET<\/code> request, use <code>client.get()<\/code><\/li><li>To make a <code>POST<\/code> request, use <code>client.post()<\/code><\/li><li>To make a <code>PUT<\/code> request, use <code>client.put()<\/code><\/li><li>To make a <code>PATCH<\/code> request, use <code>client.patch()<\/code><\/li><li>To make a <code>DELETE<\/code>request, use <code>client.delete()<\/code><\/li><li>To make a <code>HEAD<\/code> request, use <code>client.head()<\/code><\/li><\/ul>\n\n\n\n<p>These convenience methods are a wrapper of using the <code>client.request<\/code> method with a specific request type, for instance,  if you inspect the definition of the <a href=\"https:\/\/github.com\/seanmonstar\/reqwest\/blob\/5397d2cf8eaecc9f964ab4d2b40b8f2ad24ce26d\/src\/async_impl\/client.rs#L1365-L1367\" target=\"_blank\" rel=\"noopener\"><code>client.get<\/code>method<\/a>,<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>    \/\/\/ Convenience method to make a `GET` request to a URL.\n    \/\/\/\n    \/\/\/ # Errors\n    \/\/\/\n    \/\/\/ This method fails whenever the supplied `Url` cannot be parsed.\n    pub fn get&lt;U: IntoUrl&gt;(&amp;self, url: U) -&gt; RequestBuilder {\n        self.request(Method::GET, url)\n    }<\/code><\/pre>\n\n\n\n<p>you will find it automatically passes <code>Method::GET<\/code> as a parameter of the <code>client.request<\/code> method.<\/p>\n\n\n\n<p>The request is sent once you trigger the<code>send()<\/code> method, returning a <a href=\"https:\/\/rust-lang.github.io\/async-book\/02_execution\/02_future.html\" target=\"_blank\" rel=\"noopener\">future Response<\/a>. That&#8217;s why, it is inmmediately followed by an <code>await<\/code> ,<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>client.get(\"https:\/\/catfact.ninja\/fact\").send()\n        .await?<\/code><\/pre>\n\n\n\n<p>which waits until there is a response from the external API.<\/p>\n\n\n\n<p>Finally, the <code>text()<\/code> method gets the response as a text. The <code>text()<\/code> method is an asynchronous operation. Hence, use <code>await<\/code> right after to extract the response data before moving on to the next line of code:<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>let body = client.get(\"https:\/\/catfact.ninja\/fact\").send()\n        .await?\n        .text()\n        .await?;<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Run_the_code_to_test_it_works\"><\/span>Run the code to test it works<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>Execute the <code>cargo run<\/code> command to test the code works.<\/p>\n\n\n\n<p>If everything works as intended, you should see a cat fact logged in the terminal, similar to the screenshot below:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"808\" height=\"144\" src=\"https:\/\/www.becomebetterprogrammer.com\/wp-content\/uploads\/2022\/07\/image.png\" alt=\"\" class=\"wp-image-2954\" srcset=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/07\/image.png 808w, https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/07\/image-300x53.png 300w\" sizes=\"auto, (max-width: 808px) 100vw, 808px\" \/><figcaption>Cat fact logged in the terminal after running <code>cargo run<\/code> command<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"4_Configure_request_accordingly_such_as_passing_additional_headers_optional\"><\/span>4. Configure request accordingly such as passing additional headers (optional)<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Depending on the API endpoint to trigger, you will need to configure you request accordingly. In this case, triggering the <code>GET<\/code> request to fetch a cat fact from the Cat Fact Ninja API didn&#8217;t require special configuration such as passing a <a href=\"https:\/\/auth0.com\/docs\/secure\/tokens\/json-web-tokens\" target=\"_blank\" rel=\"noopener\">JWT <\/a>in the header, defining the request content type, or passing cookies in the header.<\/p>\n\n\n\n<p>To pass headers in the request, use the <code>header()<\/code> method right after defining the request type (<code>get()<\/code> , <code>post()<\/code> , <code>put()<\/code>, etc).<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>use reqwest::header::{AUTHORIZATION, CONTENT_TYPE};\n\nlet body = client\n        .get(\"https:\/\/catfact.ninja\/fact\")\n        .header(CONTENT_TYPE, \"application\/json\")\n        .header(AUTHORIZATION, \"Bearer {MY_JWT}\")\n        .send()\n        .await?\n        .text()\n        .await?;<\/code><\/pre>\n\n\n\n<p>Notice the previous example chains a set of <code>header()<\/code> methods in case of changing multiple header configurations needs. Also, the Reqwest library has a key of the different header keys you can import such as <code>AUTHORIZATION<\/code> or <code>CONTENT_TYPE<\/code>.<\/p>\n\n\n\n<p class=\"has-luminous-vivid-amber-background-color has-background\"><strong>Note:<\/strong> The previous snippet of code is an example of how to pass headers additional headers to the request. It is not necessary to make these changes to the code used in this tutorial.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"5_Deserialize_HTTP_response_as_JSON\"><\/span>5. Deserialize HTTP response as JSON<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>By now you know how to make a request and get the response as a text. However, it is uncommon to get a text response to consume or use the data to perform additional processes. <\/p>\n\n\n\n<p>Typically, the response data comes as <a href=\"https:\/\/www.w3schools.com\/js\/js_json_intro.asp\" target=\"_blank\" rel=\"noopener\">JSON<\/a>. Then, it is converted to an object structure that a programming language can store the data, which makes easier to manipulate the data in a given programming language, and Rust isn&#8217;t the exception.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Add_Serde_dependency\"><\/span>Add Serde dependency<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>To deserialize the HTTP response as JSON,  you will need <a href=\"https:\/\/crates.io\/crates\/serde\" target=\"_blank\" rel=\"noopener\">serde<\/a> dependency in your project. <\/p>\n\n\n\n<p>Open the cargo.toml file. Then, add serde in the <em>dependencies<\/em> section:<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>&#91;dependencies]\nreqwest = { version = \"0.11\", features = &#91;\"json\"] }\ntokio = { version = \"1\", features = &#91;\"full\"] }\nserde = { version = \"1.0\", features = &#91;\"derive\"] }<\/code><\/pre>\n\n\n\n<p>Save the cargo.toml file once you add the serde dependency.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Define_response_struct\"><\/span>Define response struct<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>Open the main.rs file and generate the <code>struct<\/code> containing the data structure of the API response. This article uses the Cat Fact Ninja API <code>GET<\/code> endpoint, which returns a response data with the following object structure:<\/p>\n\n\n\n<pre class=\"wp-block-code language-json\"><code>{\n   \"fact\": \"Smuggling a cat out of ancient Egypt was punishable by death. Phoenician traders eventually succeeded in smuggling felines, which they sold to rich people in Athens and other important cities.\",\n   \"length\": 192\n}<\/code><\/pre>\n\n\n\n<p>Since the response contains the keys <code>fact<\/code> and <code>length<\/code> , you will need to create a <code>struct<\/code> with the fields <code>fact<\/code> and <code>length<\/code> and types <code>String<\/code> and <code>i32<\/code> respectively.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>struct CatFact {\n    fact: String,\n    length: i32,\n}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Apply_Deserialize_derive_macro\"><\/span>Apply <code>Deserialize<\/code> derive macro<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>Import the derive macro <code>use serde::{Deserialize};<\/code> , and write <code>#[derive(Deserialize)]<\/code> on <code>CatFact<\/code> struct. This will look like this:<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>use  serde::{Deserialize};\n\n#&#91;derive(Deserialize, Debug)]\nstruct CatFact {\n    fact: String,\n    length: i32,\n}<\/code><\/pre>\n\n\n\n<p class=\"has-luminous-vivid-amber-background-color has-background\"><strong>Note:<\/strong> The <code>Debug<\/code> macro, which you see in the previous snippet of code, allows to log the <code>struct<\/code> value using the <code>println!<\/code> macro rule. In this tutorial, you use the <code>println!<\/code> macro to log the request&#8217;s response.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>println!(\"fact = {:#?}\", fact);<\/code><\/pre>\n\n\n\n<p class=\"has-luminous-vivid-amber-background-color has-background\">Failing to use the <code>Debug<\/code> macro results in errors during compilation. If you opt to not use the <code>Debug<\/code> macro, remove the <code>println!<\/code> statement to prevent errors.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Use_the_json_method_to_deserialize_the_response_body_as_JSON\"><\/span>Use the <code>json()<\/code> method to deserialize the response body as JSON<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>Go to the <code>get_cat_fact<\/code> function. Then, update the code that implements the <code>text()<\/code> method and use <code>.json::&lt;CatFact>()<\/code>  instead.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>let body = client\n        .get(\"https:\/\/catfact.ninja\/fact\")\n        .send()\n        .await?\n        .json::&lt;CatFact&gt;()\n        .await?;<\/code><\/pre>\n\n\n\n<p>The <code>json::&lt;T&gt;()<\/code> method attempts to deserialize the response as JSON, where <code>T<\/code> is <code>CatFact<\/code>.<\/p>\n\n\n\n<p class=\"has-luminous-vivid-amber-background-color has-background\"><strong>Note<\/strong>: <strong>the <code>json::&lt;T>()<\/code> will fail if the <code>T<\/code> passed doesn&#8217;t match the JSON response<\/strong>. That means, if the response has the keys <code>fact<\/code>,<code>length<\/code>, and, for instance, <code>id<\/code> , the deserialization process will fail as the <code>CatFact<\/code>  struct doesn&#8217;t have the <code>id<\/code> field.<strong> The json::()could also fail if the field type doesn&#8217;t match a key value of the JSON object<\/strong> like the following example:<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>#&#91;derive(Deserialize, Debug)]\nstruct CatFact {\n    fact: String,\n    length: String,  \/\/ this will cause an error as the \"length\" key in the JSON response is not a String\n}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Update_the_functions_result_type\"><\/span>Update the function&#8217;s result type<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>Initially, the <code>get_cat_fact()<\/code> function returned the result type:<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>Result&lt;String, Box&lt;dyn std::error::Error&gt;&gt;<\/code><\/pre>\n\n\n\n<p>Since you no longer use the <code>text()<\/code> to get the response body as a text, the <code>get_cat_fact()<\/code> function doesn&#8217;t return a <code>String<\/code>. <\/p>\n\n\n\n<p>Instead, it returns the <code>Catfact<\/code> struct. Therefore, update the <code>get_cat_fact()<\/code> to contain the correct result type.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>async fn get_cat_fact() -&gt; Result&lt;CatFact, Box&lt;dyn std::error::Error&gt;&gt; {\n  \/\/ the rest of the code\n}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Run_the_code_to_test_it_works-2\"><\/span>Run the code to test it works<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>Once you have made all the changes, check your code looks similar to the following:<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>use  serde::{Deserialize, Debug};\n\n#&#91;derive(Deserialize, Debug)]\nstruct CatFact {\n    fact: String,\n    length: i32,\n}\n\n#&#91;tokio::main]\nasync fn main() {\n    let fact = get_cat_fact().await;\n\n    println!(\"fact = {:#?}\", fact);\n}\n\nasync fn get_cat_fact() -&gt; Result&lt;CatFact, Box&lt;dyn std::error::Error&gt;&gt; {\n    let client = reqwest::Client::new();\n\n    let body = client\n        .get(\"https:\/\/catfact.ninja\/fact\")\n        .send()\n        .await?\n        .json::&lt;CatFact&gt;()\n        .await?;\n\n    Ok(body)\n}<\/code><\/pre>\n\n\n\n<p>If your code is correct, run the <code>cargo run<\/code> command. You should see additional a <code>CatFact<\/code> struct shape-like log in the terminal.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"114\" src=\"https:\/\/www.becomebetterprogrammer.com\/wp-content\/uploads\/2022\/07\/image-1-1024x114.png\" alt=\"\" class=\"wp-image-2959\" srcset=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/07\/image-1-1024x114.png 1024w, https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/07\/image-1-300x33.png 300w, https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/07\/image-1.png 1103w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>Terminal ouput of the fact variable <\/figcaption><\/figure>\n<\/div>\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Understanding_Deserialization_JSON_errors\"><\/span>Understanding Deserialization JSON errors<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>As mentioned in the previous step, the <code>request::json&lt;T>()<\/code> method could fail if the struct <code>T<\/code> doesn&#8217;t match the response&#8217;s body JSON structure. However, the code doesn&#8217;t have a friendly way to let you know the shape of <code>T<\/code> doesn&#8217;t match (I know this from experience and it can be a real-time waster).<\/p>\n\n\n\n<p>To demonstrate that an error happens when <code>T<\/code> is not an exact match, you will create a new <code>DifferentCatFact<\/code> struct containing all the fields from <code>CatFact<\/code> and an <code>id<\/code> field.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>#&#91;derive(Deserialize, Debug)]\r\nstruct DifferentCatFact {\r\n    fact: String,\r\n    length: i32,\n    id: String,\r\n}<\/code><\/pre>\n\n\n\n<p>Copy the <code>get_cat_fact()<\/code> function and paste it below. Update the name of the copied function to <code>get_different_cat_fact()<\/code> function and update the <code>T<\/code> instances from <code>CatFact<\/code> to <code>DifferentCatFact<\/code> . Your code should look like this:<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>async fn get_different_cat_fact() -> Result&lt;DifferentCatFact, Box&lt;dyn std::error::Error>> {\r\n    let client = reqwest::Client::new();\r\n\r\n    let body = client\r\n        .get(\"https:\/\/catfact.ninja\/fact\")\r\n        .send()\r\n        .await?\r\n        .json::&lt;DifferentCatFact>()\r\n        .await?;\r\n\r\n    Ok(body)\r\n}<\/code><\/pre>\n\n\n\n<p>In the <code>main()<\/code> function, add a new variable called <code>different_cat_fact<\/code> that stores the response from  calling the <code>get_different_cat_fact()<\/code> function. Then, log the value returned using the <code>println!<\/code> macro. <\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>#&#91;tokio::main]\nasync fn main() {\n    let fact = get_cat_fact().await;\n\n    println!(\"fact = {:#?}\", fact);\n\n    \/\/ The code below will panic when not using the Debug macro as the code\r\n    \/\/ fails to deserialize the response as JSON from the GET Cat Fact Ninja \r\n    \/\/ API endpoint using struct DifferentCatFact as this struct doesn't match\r\n    \/\/ the JSON structure of the response.\n    let different_cat_fact = get_different_cat_fact().await;\n\n    println!(\"different cat fact = {:#?}\", different_cat_fact);\n}<\/code><\/pre>\n\n\n\n<p>If you attempt to run the code using <code>cargo run<\/code>  , you will see a <code>reqwest::Error<\/code> in the output of your terminal.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"670\" height=\"127\" src=\"https:\/\/www.becomebetterprogrammer.com\/wp-content\/uploads\/2022\/07\/image-2.png\" alt=\"\" class=\"wp-image-2978\" srcset=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/07\/image-2.png 670w, https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-content\/uploads\/2022\/07\/image-2-300x57.png 300w\" sizes=\"auto, (max-width: 670px) 100vw, 670px\" \/><figcaption>The output of error when struct doesn&#8217;t match JSON structure<\/figcaption><\/figure>\n<\/div>\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Conclusion\"><\/span>Conclusion<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>In this tutorial, you learned how to make a HTTP request to another API using the Reqwest crate in Rust. Also, you learned how to extract the body response in two ways:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Get the response as text<\/li><li>Attempt to deserialize the response as JSON<\/li><\/ul>\n\n\n\n<p>If you run into any issues, feel free to compare your code with the code of this article https:\/\/github.com\/arealesramirez\/rust-how-to-make-an-http-request<\/p>\n\n\n\n<p><strong>Was this article helpful?<\/strong><\/p>\n\n\n\n<p>Let us know your comments by replying on <a href=\"https:\/\/twitter.com\/bbprogrammer\" target=\"_blank\" rel=\"noopener\">Twitter of Become A Better Programmer<\/a>.<\/p>\n\n\n\n<figure class=\"wp-block-embed aligncenter is-type-rich is-provider-twitter wp-block-embed-twitter\"><div class=\"wp-block-embed__wrapper\">\n<blockquote class=\"twitter-tweet\" data-width=\"550\" data-dnt=\"true\"><p lang=\"en\" dir=\"ltr\">It is common to make an HTTP request when working on real-world projects, and this is not the exception when working with <a href=\"https:\/\/twitter.com\/rustlang?ref_src=twsrc%5Etfw\" target=\"_blank\" rel=\"noopener\">@rustlang<\/a>.<br><br>To make things easier, we created a tutorial showing you step-by-step how to make an HTTP request in Rust.<br><br>Check it out!<a href=\"https:\/\/t.co\/QzqbWIIplU\">https:\/\/t.co\/QzqbWIIplU<\/a><\/p>&mdash; Become A Better Programmer (@bbprogrammer) <a href=\"https:\/\/twitter.com\/bbprogrammer\/status\/1547923657711763456?ref_src=twsrc%5Etfw\" target=\"_blank\" rel=\"noopener\">July 15, 2022<\/a><\/blockquote><script async src=\"https:\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script>\n<\/div><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>If you are relatively new to Rust, you probably have gone through a decent learning curve to understand the programming language concepts. Working with hardcoded data in your projects is not common when working on real-world application, but rather making HTTP requests to fetch data from other APIs. After all, do you know how to &#8230; <a title=\"Rust | How To Make an HTTP Request in Rust? (Step-by-step)\" class=\"read-more\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-how-to-make-an-http-request\/\" aria-label=\"More on Rust | How To Make an HTTP Request in Rust? (Step-by-step)\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":2983,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"nf_dc_page":"","_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[31],"tags":[],"class_list":["post-2850","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-rust","generate-columns","tablet-grid-50","mobile-grid-100","grid-parent","grid-50"],"_links":{"self":[{"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/posts\/2850","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/comments?post=2850"}],"version-history":[{"count":5,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/posts\/2850\/revisions"}],"predecessor-version":[{"id":3002,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/posts\/2850\/revisions\/3002"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/media\/2983"}],"wp:attachment":[{"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/media?parent=2850"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/categories?post=2850"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/tags?post=2850"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}