Someone recently posted this on reddit, and I think that it's awesome. I challenged myself to make this into a web service in under five minutes, because let's face it -- who has time to pick a thing four times?
I'm setting up shuttle.rs because it's super fast to set up, and thruster as the web framework because I wrote it, so I better know how to use it.
mkdir pep-generator
cargo shuttle init --thruster
I'm adding a few quick deps, basically the shuttle stuff, thruster stuff, tokio, and askama for templating.
askama ="0.11.1"# For templatingchrono ="0.4.22"# For time stufflog ="0.4.17"# For teh logzrand ="0.8.5"# Random!shuttle-aws-rds = { version ="0.7.2", features = ["postgres"] } # For storing datashuttle-service = { version ="0.7.2", features = ["web-thruster"] } # For deploying easilysqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres", "chrono", "uuid"] } # For dealing with postgres
thruster = { version ="1.3.0", features = ["hyper_server"] } # For http framework stufftokio = { version ="1.20.1", features = ["macros"] } # For an async runtime
The Schema
Schemas are simple, the ideas behind twitter are simple, we'll probably never need to make a change to this, so here's the schema; throw it in schema.sql.
-- Creating the users tableCREATETABLEIFNOTEXISTS first_list ( id SERIALPRIMARY KEY, item TEXTNOT NULL);CREATETABLEIFNOTEXISTS second_list ( id SERIALPRIMARY KEY, item TEXTNOT NULL);CREATETABLEIFNOTEXISTS third_list ( id SERIALPRIMARY KEY, item TEXTNOT NULL);CREATETABLEIFNOTEXISTS fourth_list ( id SERIALPRIMARY KEY, item TEXTNOT NULL);-- Okay... yes, this took more than five minutes for me to copy...INSERT INTO first_list (id, item)VALUES (1, 'Champ,'), (2, 'Fact:'), (3, 'Everybody says'), (4, 'Dang...'), (5, 'Check it:'), (6, 'Just saying...'), (7, 'Superstar,'), (8, 'Tiger,'), (9, 'Self,'), (10, 'Know this:'), (11, 'News alert:'), (12, 'Girl,'), (13, 'Ace,'), (14, 'Excuse me but'), (15, 'Experts agree:'), (16, 'In my opinion,'), (17, 'Hear ye, hear ye:'), (18, 'Okay, listen up:');INSERT INTO second_list (id, item)VALUES (1, 'the mere idea of you'), (2, 'your soul'), (3, 'your hair today'), (4, 'everything you do'), (5, 'your personal style'), (6, 'every thought you have'), (7, 'that sparkle in your eye'), (8, 'your presence here'), (9, 'what you got going on'), (10, 'the essential you'), (11, 'your life\'s journey'), (12, 'that saucy personality'), (13, 'your DNA'), (14, 'that brain of yours'), (15, 'your choice of attire'), (16, 'the way you roll'), (17, 'whatever your secretis'), (18, 'all of y\'all');INSERT INTO third_list (id, item)VALUES (1, 'has serious game,'), (2, 'rains magic,'), (3, 'deserves the Nobel Prize,'), (4, 'raises the roof,'), (5, 'breeds miracles,'), (6, 'is paying off big time,'), (7, 'shows mad skills,'), (8, 'just shimmers,'), (9, 'is a national treasure,'), (10, 'gets the party hopping,'), (11, 'is the next big thing,'), (12, 'roars like a lion,'), (13, 'is a rainbow factory,'), (14, 'is made of diamonds,'), (15, 'makes birds sing,'), (16, 'should be taught in school,'), (17, 'makes my world go \'round,'), (18, 'is100% legit,');INSERT INTO fourth_list (id, item)VALUES (1, '24/7.'), (2, 'can I get an amen?'), (3, 'and that\'s a fact.'), (4, 'so treat yourself.'), (5, 'you feel me?'), (6, 'that\'s just science.'), (7, 'would I lie?'), (8, 'for reals.'), (9, 'mic drop.'), (10, 'you hidden gem.'), (11, 'snuggle bear.'), (12, 'period.'), (13, 'can I get an amen?'), (14, 'now let\s dance.'), (15, 'high five.'), (16, 'say it again!'), (17, 'according to CNN.'), (18, 'so get used to it.');
The Code
We have the basic code in lib.rs, first let's populate the DB. If you aren't using an IDE that lets you auto import, then you should get one at this point.
#[shuttle_service::main]asyncfnthruster( #[shuttle_aws_rds::Postgres] pool:PgPool,) -> shuttle_service::ShuttleThruster<HyperServer<Ctx, ()>> {info!("Starting server..."); pool.execute(include_str!("../schema.sql")).await.map_err(|e| CustomError::new(e))?;info!("Server started...");Ok(HyperServer::new(// I changed the route here App::<HyperRequest, Ctx, ()>::create(generate_context, ()).get("/", m![hello]), ))}
I also need to add a pool for the middleware to make calls to, so I need to have a singleton on the server. So I used TypedHyperContext along with some structs to hold it. I had to delete some of the default imports that these override.