{"id":11738,"date":"2025-09-06T15:17:24","date_gmt":"2025-09-06T15:17:24","guid":{"rendered":"https:\/\/putridparrot.com\/blog\/?p=11738"},"modified":"2025-09-06T15:18:26","modified_gmt":"2025-09-06T15:18:26","slug":"rust-rocket-and-openapi-swagger","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/rust-rocket-and-openapi-swagger\/","title":{"rendered":"Rust Rocket (and openapi\/swagger)"},"content":{"rendered":"<p>Rocket provides code that allows us to build web servers and web based applications such as web APIs. <\/p>\n<p>We&#8217;ll start by just creating a simple endpoint, and then we&#8217;ll look at adding Open API and swagger support.<\/p>\n<p><strong>Starting simple<\/strong><\/p>\n<p>Create yourself a Rust package, for example with cargo<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\ncargo new myapi --bin\r\n<\/pre>\n<p>add the following dependency to your Cargo.toml<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nrocket = &quot;0.5.1&quot;\r\n<\/pre>\n<p>Now create a Rocket.toml so we can configure rocket&#8217;s server and mine looks like this<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n&#x5B;default]\r\nport = 8080\r\naddress = &quot;127.0.0.1&quot;\r\n<\/pre>\n<p>We need a main.rs (so you can delete the lib.rs if you wish for now) and here&#8217;s a very basic starting point<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n#&#x5B;macro_use] extern crate rocket;\r\n\r\n#&#x5B;get(&quot;\/&quot;)]\r\nfn index() -&gt; &amp;&#039;static str {\r\n    &quot;Hello, world!&quot;\r\n}\r\n\r\n#&#x5B;launch]\r\nfn rocket() -&gt; _ {\r\n    rocket::build().mount(&quot;\/&quot;, routes!&#x5B;index])\r\n}\r\n<\/pre>\n<p>Now, run the application using<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\ncargo run\r\n<\/pre>\n<p>As you can see this is a minimal API style, i.e. we create a function supplying it with an HTTP method and we add it to the routes list.<\/p>\n<p><strong>Adding the usual echo endpoint<\/strong><\/p>\n<p>Now let&#8217;s add my version of &#8220;Hello World&#8221; for API&#8217;s, a simple echo endpoint.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n#&#x5B;get(&quot;\/echo?&lt;text&gt;&quot;)]\r\nfn echo(text: &amp;str) -&gt; String {\r\n    format!(&quot;Echo: {}&quot;, text)\r\n}\r\n<\/pre>\n<p>Now add this to the routes i.e.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n#&#x5B;launch]\r\nfn rocket() -&gt; _ {\r\n    rocket::build().mount(&quot;\/&quot;, routes!&#x5B;index, echo])\r\n}\r\n<\/pre>\n<p><strong>Add Open API and Swagger<\/strong><\/p>\n<p>Now we have a couple of simple endpoints, let&#8217;s add Open API and Swagger and change the echo endpoint to use Json. I&#8217;m purposefully going to keep the index as non-Open API just to demonstrate running both Open API and non-Open API endpoints.<\/p>\n<p>We&#8217;re going to need a few addition to our Cargo.toml &#8211; now, unfortunately it&#8217;s easy to get multiple version dependencies for these, so the one&#8217;s shown here will work together without warning\/errors<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n&#x5B;dependencies]\r\nrocket = { version = &quot;0.5.1&quot;, features = &#x5B;&quot;json&quot;] }\r\nopenapi = &quot;0.1.5&quot;\r\nserde = &quot;1.0.219&quot;\r\nrocket_okapi = { version = &quot;0.9.0&quot;, features = &#x5B;&quot;swagger&quot;] }\r\nschemars = &quot;0.8.22&quot;\r\n<\/pre>\n<p>Notice we&#8217;re adding features to the rocket crate and we&#8217;ve got some creates for swagger and open api. The <em>schamars<\/em> crate 0.8.22 was being used by other crates, hence I locked this down to the same version.<\/p>\n<p>We&#8217;ll extend our echo endpoint to return Json, but before we do I&#8217;ll list the use clauses that are listed after <em>#[macro_use] extern crate rocket;<\/em><\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nuse rocket::serde::{Serialize, json::Json};\r\nuse rocket_okapi::{openapi, openapi_get_routes};\r\nuse rocket_okapi::swagger_ui::{make_swagger_ui, SwaggerUIConfig};\r\nuse schemars::JsonSchema;\r\n<\/pre>\n<p>We&#8217;ll create a response object for the echo endpoint and update the echo endpoint to both return this and add the openapi attribute to allow this endpoint to have an open api spec generated for it<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n#&#x5B;derive(Serialize, JsonSchema)]\r\nstruct EchoResponse {\r\n    message: String,\r\n}\r\n\r\n#&#x5B;openapi]\r\n#&#x5B;get(&quot;\/echo?&lt;text&gt;&quot;)]\r\nfn echo(text: &amp;str) -&gt; Json&lt;EchoResponse&gt; {\r\n    Json(EchoResponse {\r\n        message: format!(&quot;Echo: {}&quot;, text),\r\n    })\r\n}\r\n<\/pre>\n<p>Next up we need to change the <em>rocket<\/em> function, so let&#8217;s just see the latest version<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n#&#x5B;launch]\r\nfn rocket() -&gt; _ {\r\n    rocket::build()\r\n        .mount(&quot;\/&quot;, routes!&#x5B;index])\r\n        .mount(&quot;\/&quot;, openapi_get_routes!&#x5B;echo])\r\n        .mount(\r\n            &quot;\/swagger&quot;,\r\n            make_swagger_ui(&amp;SwaggerUIConfig {\r\n                url: &quot;\/openapi.json&quot;.to_owned(),\r\n                ..Default::default()\r\n            })\r\n        )\r\n}\r\n<\/pre>\n<p>Now I purposefully left the index route without an open api attribute just to demonstrate, if you have such endpoints, you need to still use the <em>routes!<\/em> macro, if you add index to <em>openapi_get_routes!<\/em> without the open api attribute you&#8217;ll get some slight ambiguous error&#8217;s such as <em>a function with a similar name exists<\/em>. <\/p>\n<p>Now run your application and go to http:\/\/localhost:8080\/swagger\/index.html and you can interact with your endpoints via the Swagger UI you can also access the openapi.json file using http:\/\/localhost:8080\/openapi.json.<\/p>\n<p><strong>Code<\/strong><\/p>\n<p>Available on <a href=\"https:\/\/github.com\/putridparrot\/blog-projects\/tree\/master\/rocket_sample\" target=\"_blank\">GitHub<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Rocket provides code that allows us to build web servers and web based applications such as web APIs. We&#8217;ll start by just creating a simple endpoint, and then we&#8217;ll look at adding Open API and swagger support. Starting simple Create yourself a Rust package, for example with cargo cargo new myapi &#8211;bin add the following [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[754,191,356],"tags":[],"class_list":["post-11738","post","type-post","status-publish","format-standard","hentry","category-rocket","category-rust","category-web-api"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/11738","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=11738"}],"version-history":[{"count":3,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/11738\/revisions"}],"predecessor-version":[{"id":11807,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/11738\/revisions\/11807"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=11738"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=11738"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=11738"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}