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
- Announce the use of an external crate. In
main.rs
at the top add
# #![allow(unused_variables)] #fn main() { extern crate flashcard_server; #}
- Use the
get_flash_card
function. Also inmain.rs
add an otheruse
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"}⏎