Skip to content

Instantly share code, notes, and snippets.

@aleics
Created July 18, 2018 11:11
Show Gist options
  • Save aleics/814aa082afd5066eb3cd86adf22e652f to your computer and use it in GitHub Desktop.
Save aleics/814aa082afd5066eb3cd86adf22e652f to your computer and use it in GitHub Desktop.
Diesel connection with the Rocket Framework
use r2d2::{Pool, PooledConnection, Error};
use r2d2_diesel::ConnectionManager;
use diesel::PgConnection;
use rocket::http::Status;
use rocket::{Request, State, Outcome};
use rocket::request::{self, FromRequest};
/// DatabaseHandler handles a single connection to the database
pub struct DatabaseHandler {
conn: PooledConnection<ConnectionManager<PgConnection>>
}
impl DatabaseHandler {
// Get a connection from the pooled connection
pub fn conn(&self) -> &PgConnection {
&*self.conn
}
}
/// Implementation of the `FromRequest` rocket trait for the DatabaseHandler struct.
/// This will allow us to retrieve a connection of the database dynamically for a given request.
impl<'a, 'r> FromRequest<'a, 'r> for DatabaseHandler {
type Error = ();
fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
let pool = request.guard::<State<Database>>()?;
match pool.handler() {
Ok(handler) => Outcome::Success(handler),
Err(_) => Outcome::Failure((Status::ServiceUnavailable, ()))
}
}
}
// Database manages the postgres database pool to retrieve and read connections
pub struct Database {
pool: Pool<ConnectionManager<PgConnection>>,
}
impl Database {
/// Initialization of the database pool
pub fn init(db_url: String) -> Database {
let manager = ConnectionManager::<PgConnection>::new(db_url);
Database {
pool: Pool::builder().build(manager).expect("unable to generate initial database pool")
}
}
/// Get a database handler for a given connection
pub fn handler(&self) -> Result<DatabaseHandler, Error> {
self.pool.get()
.map(|conn| DatabaseHandler { conn })
}
}
#![feature(plugin)]
#![plugin(rocket_codegen)]
extern crate rocket;
extern crate r2d2;
extern crate r2d2_diesel;
#[macro_use] extern crate diesel;
extern crate serde;
extern crate serde_json;
#[macro_use] extern crate serde_derive;
mod db;
mod models;
mod schema;
use rocket::Rocket;
use db::{DatabaseHandler, Database};
use models::User;
use serde::Serialize;
// Serialize any type into a JSON string
fn serialize<T: ?Sized>(val: &T) -> String where T: Serialize {
serde_json::to_string(val)
.unwrap_or(String::new())
}
#[post("/graphql", format = "application/json")]
fn graphql_handler(handler: DatabaseHandler) -> String {
use schema::users::dsl::*;
use diesel::prelude::*;
let result: Vec<User> = users
.select((passport, name, age))
.load::<User>(handler.conn())
.unwrap();
serialize(&result)
}
fn rocket(database: Database) -> Rocket {
rocket::ignite()
.manage(database)
.mount("/api", routes![graphql_handler])
}
fn main() {
rocket(Database::init("postgres://postgres@172.11.0.3".to_string()))
.launch();
}
#[derive(Debug, Queryable, Serialize)]
pub struct User {
passport: String,
name: String,
age: i32
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment