├── LICENSE ├── README.md ├── default.env └── template ├── .env ├── Cargo.toml ├── Rocket.toml ├── migrations └── 20170104003515_count │ ├── down.sql │ └── up.sql └── src ├── bin └── main.rs ├── lib.rs ├── models.rs └── schema.rs /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Orhan Balci 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rocket-Template 2 | 3 | This is a REST API project template that uses [Rocket](https://github.com/SergioBenitez/Rocket) framework with [Diesel](https://github.com/diesel-rs/diesel) ORM backed up with Postgresql database. You can generate project skeleton using porteurbars. 4 | 5 | - In order to create project you need to install [porteurbars](https://github.com/softprops/porteurbars) first. 6 | - Run 7 | ```porteurbars orhanbalci/rocket-template your_project_directory``` 8 | - You need nightly version of Rust for [Rocket](https://github.com/SergioBenitez/Rocket). 9 | ```rustup default nightly``` 10 | - Install diesel_cli. 11 | ``` 12 | apt get install libsqlite3-dev 13 | apt get install libmysqlclient-dev 14 | apt get install libpq-dev 15 | cargo install diesel_cli 16 | ``` 17 | - Run database migration from your project directory. First make sure you have a working database url in your .env file. 18 | ```disel migration run``` 19 | - Ignite your diesel powered rocket api 20 | ```cargo run``` 21 | - Skeleton code is taken from [mgattozi](https://github.com/mgattozzi/mgattozzi) 22 | 23 | -------------------------------------------------------------------------------- /default.env: -------------------------------------------------------------------------------- 1 | DatabaseUrl=postgres://user@localhost/sample_db 2 | PackageName=RocketSample 3 | BinaryName=RocketSample 4 | DevelopmentPort=4000 5 | StagingPort=3000 6 | ProductionPort=2000 7 | Author=Orhan Balci 8 | -------------------------------------------------------------------------------- /template/.env: -------------------------------------------------------------------------------- 1 | DATABASE_URL={{DatabaseUrl}} 2 | -------------------------------------------------------------------------------- /template/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "{{PackageName}}" 3 | version = "1.0.0" 4 | authors = ["{{Author}}"] 5 | 6 | [[bin]] 7 | name = "{{BinaryName}}" 8 | path = "src/bin/main.rs" 9 | 10 | [lib] 11 | name = "mlib" 12 | path = "src/lib.rs" 13 | 14 | [dependencies] 15 | # Rocket Server Deps 16 | rocket = "0.2" 17 | rocket_codegen = "0.2" 18 | rocket_contrib = "0.2" 19 | 20 | # JSON Deps 21 | serde = "0.9" 22 | serde_json = "0.9" 23 | serde_derive = "0.9" 24 | 25 | # DB Deps 26 | diesel = { version = "~0.9.0", features = ["postgres"] } 27 | diesel_codegen = { version = "~0.9.0", features = ["postgres"] } 28 | dotenv = "~0.8.0" 29 | r2d2 = "~0.7.1" 30 | r2d2-diesel = "~0.9.0" 31 | lazy_static = "~0.1.0" 32 | -------------------------------------------------------------------------------- /template/Rocket.toml: -------------------------------------------------------------------------------- 1 | [dev] 2 | port = {{DevelopmentPort}} 3 | [staging] 4 | port = {{StagingPort}} 5 | [prod] 6 | port = {{ProductionPort}} 7 | -------------------------------------------------------------------------------- /template/migrations/20170104003515_count/down.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE counts; 2 | -------------------------------------------------------------------------------- /template/migrations/20170104003515_count/up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE counts ( 2 | id SERIAL PRIMARY KEY, 3 | clicks SERIAL NOT NULL 4 | ); 5 | 6 | INSERT INTO counts (clicks) VALUES (0); 7 | -------------------------------------------------------------------------------- /template/src/bin/main.rs: -------------------------------------------------------------------------------- 1 | #![feature(plugin, custom_derive, custom_attribute)] 2 | #![plugin(rocket_codegen)] 3 | 4 | #[macro_use] 5 | extern crate lazy_static; 6 | extern crate rocket; 7 | extern crate rocket_contrib; 8 | extern crate diesel; 9 | extern crate mlib; 10 | #[macro_use] 11 | extern crate serde_derive; 12 | extern crate serde_json; 13 | extern crate r2d2; 14 | extern crate r2d2_diesel; 15 | 16 | // Server Imports 17 | // Used to Setup DB Pool 18 | use rocket::request::{Outcome, FromRequest}; 19 | use rocket::Outcome::{Success, Failure}; 20 | use rocket::http::Status; 21 | 22 | // Used for Routes 23 | use rocket::Request; 24 | use rocket::response::NamedFile; 25 | use rocket_contrib::JSON; 26 | 27 | // Std Imports 28 | use std::path::{Path, PathBuf}; 29 | 30 | // DB Imports 31 | use diesel::prelude::*; 32 | use diesel::update; 33 | use diesel::pg::PgConnection; 34 | use r2d2::{Pool, PooledConnection, GetTimeout}; 35 | use r2d2_diesel::ConnectionManager; 36 | use mlib::models::*; 37 | use mlib::*; 38 | 39 | fn main() { 40 | // Put site last so that path collision tries others 41 | // first 42 | rocket::ignite() 43 | .mount("/", routes![ 44 | count, 45 | count_update 46 | ]) 47 | .launch(); 48 | } 49 | 50 | // DB Items 51 | lazy_static! { 52 | pub static ref DB_POOL: Pool> = create_db_pool(); 53 | } 54 | 55 | pub struct DB(PooledConnection>); 56 | 57 | impl DB { 58 | pub fn conn(&self) -> &PgConnection { 59 | &*self.0 60 | } 61 | } 62 | 63 | impl<'a, 'r> FromRequest<'a, 'r> for DB { 64 | type Error = GetTimeout; 65 | fn from_request(_: &'a Request<'r>) -> Outcome { 66 | match DB_POOL.get() { 67 | Ok(conn) => Success(DB(conn)), 68 | Err(e) => Failure((Status::InternalServerError, e)), 69 | } 70 | } 71 | } 72 | 73 | #[get("/count")] 74 | fn count(db: DB) -> JSON { 75 | use mlib::schema::counts::dsl::*; 76 | let result = counts.first::(db.conn()) 77 | .expect("Error loading clicks"); 78 | 79 | JSON(Clicks { 80 | count: result.clicks, 81 | }) 82 | } 83 | 84 | #[put("/count")] 85 | fn count_update(db: DB) -> JSON { 86 | use mlib::schema::counts::dsl::*; 87 | let query = counts.first::(db.conn()) 88 | .expect("Error loading clicks"); 89 | let val = query.clicks + 1; 90 | 91 | update(counts.find(1)) 92 | .set(clicks.eq(val)) 93 | .execute(db.conn()) 94 | .unwrap(); 95 | 96 | JSON(Clicks { 97 | count: val, 98 | }) 99 | } 100 | 101 | #[derive(Deserialize, Serialize)] 102 | pub struct Clicks { 103 | pub count: i32, 104 | } 105 | -------------------------------------------------------------------------------- /template/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate diesel_codegen; 3 | #[macro_use] 4 | extern crate diesel; 5 | extern crate dotenv; 6 | extern crate r2d2; 7 | extern crate r2d2_diesel; 8 | 9 | pub mod schema; 10 | pub mod models; 11 | 12 | use diesel::pg::PgConnection; 13 | use r2d2::{ Pool, Config }; 14 | use r2d2_diesel::ConnectionManager; 15 | use dotenv::dotenv; 16 | use std::env; 17 | 18 | pub fn create_db_pool() -> Pool> { 19 | dotenv().ok(); 20 | 21 | let database_url = env::var("DATABASE_URL") 22 | .expect("DATABASE_URL must be set"); 23 | let config = Config::default(); 24 | let manager = ConnectionManager::::new(database_url); 25 | Pool::new(config, manager).expect("Failed to create pool.") 26 | } 27 | -------------------------------------------------------------------------------- /template/src/models.rs: -------------------------------------------------------------------------------- 1 | #[derive(Queryable, Debug)] 2 | pub struct Count { 3 | pub id: i32, 4 | pub clicks: i32, 5 | } 6 | -------------------------------------------------------------------------------- /template/src/schema.rs: -------------------------------------------------------------------------------- 1 | infer_schema!("dotenv:DATABASE_URL"); 2 | --------------------------------------------------------------------------------