avatarJerry Wang

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

1266

Abstract

keyword">use</span> serde::Deserialize;</pre></div><div id="fd82"><pre><span class="hljs-meta">#[derive(Deserialize)]</span> <span class="hljs-keyword">struct</span> <span class="hljs-type">CreateUser</span> { email: <span class="hljs-keyword">String</span>, password: <span class="hljs-keyword">String</span>, }</pre></div><div id="5a59"><pre><span class="hljs-keyword">async</span> fn <span class="hljs-title function_">create_user</span>(<span class="hljs-params">Json(payload): Json<CreateUser></span>) { <span class="hljs-comment">// ...</span> }</pre></div><div id="99a8"><pre><span class="hljs-title">let app = Router::</span><span class="hljs-keyword">new</span>().route(<span class="hljs-string">"/users"</span>, post(create_user))<span class="hljs-comment">;</span></pre></div><p id="1c1d">We can spot a few things in the above example:</p><ol><li>the async function <code>create_user()</code> is the handler, which is set up to handle POST requests against the <code>/users</code> endpoint</li><li>the function argument <code>Json(payload)</code> is a Json extractor that consumes the JSON body and deserializes it as JSON into the target type <code>CreateUser</code></li></ol><h1 id="285e">How to make an API endpoint accept POST reques

Options

ts with an optional JSON body?</h1><p id="0c11">All extractors defined in axum will reject the request if it doesn’t match. If you wish to make an extractor optional, you can wrap it in <code>Option</code>:</p><div id="8c07"><pre><span class="hljs-keyword">use</span> axum::{ Json, routing::post, Router, }; <span class="hljs-keyword">use</span> serde_json::Value;

<span class="hljs-keyword">async</span> <span class="hljs-keyword">fn</span> <span class="hljs-title function_">create_user</span>(payload: <span class="hljs-type">Option</span><Json<Value>>) { <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> <span class="hljs-variable">Some</span>(payload) = payload { <span class="hljs-comment">// We got a valid JSON payload</span> } <span class="hljs-keyword">else</span> { <span class="hljs-comment">// Payload wasn't valid JSON</span> } } <span class="hljs-keyword">let</span> <span class="hljs-variable">app</span> = Router::<span class="hljs-title function_ invoke__">new</span>().<span class="hljs-title function_ invoke__">route</span>(<span class="hljs-string">"/users"</span>, <span class="hljs-title function_ invoke__">post</span>(create_user));</pre></div></article></body>

How to Make an API Endpoint Accept POST Requests with an Optional JSON body in axum?

What is axum?

axum is a very popular web application framework in the Rust world.

How does axum handle incoming requests?

Like many other web application frameworks, axum routes the incoming requests to handlers.

What is a handler?

In axum, a handler is an async function that accepts zero or more “extractors” as arguments and returns something that can be converted into a response.

What is an extractor?

In axum, an extractor is a type for extracting data from requests, which implements FromRequest or FromRequestParts.

For example, Json is an extractor that consumes the request body and deserializes it as JSON into some target type:

use axum::{
    Json,
    routing::post,
    Router,
};
use serde::Deserialize;
#[derive(Deserialize)]
struct CreateUser {
    email: String,
    password: String,
}
async fn create_user(Json(payload): Json<CreateUser>) {
    // ...
}
let app = Router::new().route("/users", post(create_user));

We can spot a few things in the above example:

  1. the async function create_user() is the handler, which is set up to handle POST requests against the /users endpoint
  2. the function argument Json(payload) is a Json extractor that consumes the JSON body and deserializes it as JSON into the target type CreateUser

How to make an API endpoint accept POST requests with an optional JSON body?

All extractors defined in axum will reject the request if it doesn’t match. If you wish to make an extractor optional, you can wrap it in Option:

use axum::{
    Json,
    routing::post,
    Router,
};
use serde_json::Value;

async fn create_user(payload: Option<Json<Value>>) {
    if let Some(payload) = payload {
        // We got a valid JSON payload
    } else {
        // Payload wasn't valid JSON
    }
}
let app = Router::new().route("/users", post(create_user));
Rust
Rust Programming Language
Web App Development
Web Development
Recommended from ReadMedium