2

I'm trying to implement a simple Actix API, and the first method I'm testing, is one for creating a "book" object in a SQLite database. I've got the up.sql, schema, model and DAO (just for encapsulating the DB code) all writen, but I'm lacking a very important part: input.

So now I have to deal with the handler, which should read the HttpRequest (which will come as a JSON format), and then save the object in the SQLite instance. The problem is β€”and this is as funny as annoying-, I have no idea how to read, at least in a proper way, the body of the request.

I've seen a solution in which you take the raw bytes and parse them, but I guess there are much better and more simple solutions for just reading a request's body. But I couldn't find anything useful.

pub async fn create_book_handler(req: HttpRequest) -> HttpResponse {
    let book: Book = req.  <--- what comes here?
    books_dao::create_book(&book);
    let response = Json(book);
    HttpResponse::Ok()
        .content_type(ContentType::json())
        .json(response)
}
Tobias S.
  • 21,159
  • 4
  • 27
  • 45
Zerok
  • 1,323
  • 1
  • 24
  • 56
  • Do the docs provide any help? Usually they're quite specific. – tadman Nov 20 '22 at 02:21
  • 1
    I didn't get any help from them in this matter. For me, both Actix and Diesel docs were extremely unhelpful (for being overly simplistic or overly complicated), and I actually took a long time to reach to that point in the test app. I don't want to offend anyone, but I think docs quality and standarization is not yet present in this echosystem. How can it be that hard to find such a common functionality that in most langs isn't more than a simple method call? – Zerok Nov 20 '22 at 02:34
  • 1
    Sorry to hear that. Most Rust projects seem to be organized much better than that, so hopefully this is a temporary condition. – tadman Nov 20 '22 at 05:21

1 Answers1

2

Actix Web uses "extractors" as a type-safe way to extract information from the request. One of those extractors is web::Json which allows deserializing of the body into a given type.

Your struct needs to implement the Deserialize trait provided by serde.

#[derive(serde::Deserialize)]
struct Book {
    title: String,
}

The only thing left to do is to specify the extractor of type web::Json<Book> as the parameter of your route function.

async fn some_route(book: web::Json<Book>) -> Result<String> {
    Ok(format!("This book is called {}!", book.title))
}

Actix Web will automatically call the from_request method of web::Json to deserialize the JSON body into the struct when the route is called.

Tobias S.
  • 21,159
  • 4
  • 27
  • 45