Sending FlashCard

We are capable to serialize a flash card to JSON. The next step is to send it to the frontend. We will do this by making an end point where the frontend can request a flash card.

This probably will be a somewhat longer chapter because there are a lot of moving pieces. So make sure to fetch yourself a nice drink and strap in for the ride.

Dependencies

We will be using some dependencies that need to be declared in the Cargo.toml. Specifically the following dependencies

hyper = "0.12.35"
mime = "0.3.14"

Create a new route

The next step is to dream up a new route. Where should the frontend get a flash card from. We are offering an API and it is reasonable to adhere to the REST model. One suggestion is to choose /api/flashcard.

In main.rs we have configured a router. We can extend it with a route for a flash card


# #![allow(unused_variables)]
#fn main() {
route.get("/api/flashcard").to(get_flash_card);
#}

the get_flash_card handler is something that does not yet exist. But it is something we like. In order to use it we should do

  1. Announce the use of an external crate. In main.rs at the top add

# #![allow(unused_variables)]
#fn main() {
extern crate flashcard_server;
#}
  1. Use the get_flash_card function. Also in main.rs add an other use expression

# #![allow(unused_variables)]
#fn main() {
use flashcard_server::handler::flashcard::*;
#}

Create a new module

From the usage we learn that there should be a handler. So we need to announce that in out lib.rs


# #![allow(unused_variables)]
#fn main() {
pub mod handler;
#}

We will create this module by using a sub-directory handler that contains a mod.rs file. We probably are going to create a lot of handlers for this applications so the contains of the handler/mod.rs could look like this.


# #![allow(unused_variables)]
#fn main() {
pub mod flashcard;
#}

This just announces an other module. This time do, we are not creating a sub-directory. Instead we are creating a file named flashcard.rs in the handler directory. This is the other way of creating a module.

flashcard.rs should have our definition of get_flash_card.

get_flash_card

A handler has a particular signature for the gotham web framework to work with it. In goes a State, a provided by gotham. At goes a tuple of a state, and whatever you want to return. All in all this amounts to the following code.


# #![allow(unused_variables)]
#fn main() {
use gotham::state::State;
use crate::domain::FlashCard;


pub fn get_flash_card(state: State) -> (State, FlashCard) {
    let flash_card = FlashCard::new("Kodieren", "Encode");

    (state, flash_card)
}
#}

Here we create a new flash card and remove it with the state unaltered.

Response

The web is build about requests and responses. Each response can be of a certain MIME type, but it can't know everything that could be send back. So we will need to tell gotham how to create a real response from a flash card.

There is a trait that you can implement that does precisely that. It is called IntoResponse and it will allow us to specifiy how to turn a flash card into a response.

In order to use it we need to declare it, and related type.


# #![allow(unused_variables)]
#fn main() {
use gotham::handler::IntoResponse;
use gotham::helpers::http::response::create_response;
use gotham::state::State;
use hyper::{Body, Response, StatusCode};
#}

Next we should implement the IntoResponse trait.


# #![allow(unused_variables)]
#fn main() {
impl IntoResponse for FlashCard {
    fn into_response(self, state: &State) -> Response<Body> {
        create_response(
            state,
            StatusCode::OK,
            mime::APPLICATION_JSON,
            serde_json::to_string(&self).expect("serialized flash card"),
        )
    }
}
#}

Here we use the create_response function to create a valid response, which contains JSON with a body of a string representation of the flash card.

Verification

When you restart the application and open a terminal you should be able to execute the following curl command

curl -X GET http://localhost:8886/api/flashcard

and the server should respond with

{"front":"Kodieren","back":"Encode","face":"Front"}⏎