Bootstrapping a server

To start a server instance, we have to prepare a database interaction. But it doesn't work directly as it did with the diesel crate. To connect a database, we have to add the crates we need and activate the necessary features of the rocket_contrib crate:

rocket = "0.4.0-rc.1"
rocket_contrib = { version = "0.4.0-rc.1", features = ["diesel_sqlite_pool"] }
serde = "1.0"
serde_json = "1.0"
serde_derive = "1.0"
diesel = { version = "1.3", features = ["sqlite", "r2d2"] }
diesel_migrations = "1.3"
log = "0.4"

We used the diesel_sqlite_pool feature of the rocket_contrib crate and sqlite with r2d2 from the diesel crate. The following lines of code import macros from all of the crates we need, add the comment module that we will create later, and import all necessary types:

#![feature(proc_macro_hygiene, decl_macro)]

#[macro_use]
extern crate rocket;
#[macro_use]
extern crate diesel;
#[macro_use]
extern crate diesel_migrations;
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate rocket_contrib;

mod comment;

use rocket::fairing::AdHoc;
use rocket::request::Form;
use rocket_contrib::json::Json;
use diesel::SqliteConnection;
use comment::{Comment, NewComment};

You will also see that we used two features from the nightly release: proc_macro_hygiene and decl_macro. Without these features, you can't declare handlers.

The nightly Rust compiler contains a lot of cool but unstable features. Unstable doesn't mean you can't use them in production applications; it means the features may be changed or even removed. Their being unstable means that it's risky to use these, because you may need to rewrite your code later. The Rocket framework requires you to use some unstable features. You can find the complete list of unstable features in the Unstable Book: https://doc.rust-lang.org/stable/unstable-book/.

Now we can connect to SQLite Database in the code. To do so, we create a wrapper for SqliteConnection and the user database attribute to assign a database connection is set in the global.database.sqlite_database parameters:

#[database("sqlite_database")]
pub struct Db(SqliteConnection);

Another feature we used is migration embedding, which includes all of the SQL scripts from the migrations folder in a program:

embed_migrations!();

Now we can create and launch a server instance. We create a Rocket instance with the ignite method call, but before we launch it, we add two middleware called fairings in the Rocket framework. The first is created for the Db database wrapper and provides a database pool in requests. The second is the AdHoc fairing, which tries to run migrations for a database. Look at the following code:

fn main() {
rocket::ignite()
.attach(Db::fairing())
.attach(AdHoc::on_attach("Database Migrations", |rocket| {
let conn = Db::get_one(&rocket).expect("no database connection");
match embedded_migrations::run(&*conn) {
Ok(_) => Ok(rocket),
Err(err) => {
error!("Failed to run database migrations: {:?}", err);
Err(rocket)
},
}
}))
.mount("/", routes![list, add_new])
.launch();
}

After that, we call the mount method to add routes to the root path. Routes are created by the routes! macro, where we include all of the routes defined later in this section. When the Rocket instance is built, we run it with the launch method call.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.60.249