1
0
Fork 0
mirror of https://github.com/SinTan1729/chhoto-url synced 2024-10-16 13:27:03 -05:00

Use one database connection throghout

This commit is contained in:
Sayantan Santra 2023-04-03 18:52:17 -05:00
parent e4ff2df3f1
commit 71d7253248
3 changed files with 49 additions and 28 deletions

View file

@ -1,8 +1,6 @@
use rusqlite::Connection; use rusqlite::Connection;
pub fn find_url(shortlink: &str) -> String { pub fn find_url(shortlink: &str, db: &Connection) -> String {
let db = Connection::open("./urls.sqlite").expect("Unable to open database!");
let mut statement = db let mut statement = db
.prepare_cached("SELECT long_url FROM urls WHERE short_url = ?1") .prepare_cached("SELECT long_url FROM urls WHERE short_url = ?1")
.unwrap(); .unwrap();
@ -19,8 +17,7 @@ pub fn find_url(shortlink: &str) -> String {
longlink longlink
} }
pub fn getall() -> Vec<String> { pub fn getall(db: &Connection) -> Vec<String> {
let db = Connection::open("./urls.sqlite").expect("Unable to open database!");
let mut statement = db.prepare_cached("SELECT * FROM urls").unwrap(); let mut statement = db.prepare_cached("SELECT * FROM urls").unwrap();
let mut data = statement.query([]).unwrap(); let mut data = statement.query([]).unwrap();
@ -36,8 +33,7 @@ pub fn getall() -> Vec<String> {
links links
} }
pub fn add_hit(shortlink: &str) -> () { pub fn add_hit(shortlink: &str, db: &Connection) -> () {
let db = Connection::open("./urls.sqlite").expect("Unable to open database!");
db.execute( db.execute(
"UPDATE urls SET hits = hits + 1 WHERE short_url = ?1", "UPDATE urls SET hits = hits + 1 WHERE short_url = ?1",
[shortlink], [shortlink],
@ -45,9 +41,7 @@ pub fn add_hit(shortlink: &str) -> () {
.unwrap(); .unwrap();
} }
pub fn add_link(shortlink: String, longlink: String) -> bool { pub fn add_link(shortlink: String, longlink: String, db: &Connection) -> bool {
let db = Connection::open("./urls.sqlite").expect("Unable to open database!");
match db.execute( match db.execute(
"INSERT INTO urls (long_url, short_url, hits) VALUES (?1, ?2, ?3)", "INSERT INTO urls (long_url, short_url, hits) VALUES (?1, ?2, ?3)",
(longlink, shortlink, 0), (longlink, shortlink, 0),
@ -57,8 +51,22 @@ pub fn add_link(shortlink: String, longlink: String) -> bool {
} }
} }
pub fn delete_link(shortlink: String) -> () { pub fn delete_link(shortlink: String, db: &Connection) -> () {
let db = Connection::open("./urls.sqlite").expect("Unable to open database!");
db.execute("DELETE FROM urls WHERE short_url = ?1", [shortlink]) db.execute("DELETE FROM urls WHERE short_url = ?1", [shortlink])
.unwrap(); .unwrap();
} }
pub fn open_db(path: String) -> Connection {
let db = Connection::open(path).expect("Unable to open database!");
db.execute(
"CREATE TABLE IF NOT EXISTS urls (
id INTEGER PRIMARY KEY AUTOINCREMENT,
long_url TEXT NOT NULL,
short_url TEXT NOT NULL,
hits INTEGER NOT NULL
)",
[],
)
.unwrap();
db
}

View file

@ -6,15 +6,21 @@ use actix_web::{
web::{self, Redirect}, web::{self, Redirect},
App, HttpResponse, HttpServer, Responder, App, HttpResponse, HttpServer, Responder,
}; };
use rusqlite::Connection;
mod database; mod database;
mod utils; mod utils;
// This struct represents state
struct AppState {
db: Connection,
}
// Define the routes // Define the routes
// Add new links // Add new links
#[post("/api/new")] #[post("/api/new")]
async fn add_link(req: String) -> HttpResponse { async fn add_link(req: String, data: web::Data<AppState>) -> HttpResponse {
let out = utils::add_link(req); let out = utils::add_link(req, &data.db);
if out.0 { if out.0 {
println!("ok{}", out.1); println!("ok{}", out.1);
HttpResponse::Ok().body(out.1) HttpResponse::Ok().body(out.1)
@ -26,8 +32,8 @@ async fn add_link(req: String) -> HttpResponse {
// Return all active links // Return all active links
#[get("/api/all")] #[get("/api/all")]
async fn getall() -> HttpResponse { async fn getall(data: web::Data<AppState>) -> HttpResponse {
HttpResponse::Ok().body(utils::getall()) HttpResponse::Ok().body(utils::getall(&data.db))
} }
// Get the site URL // Get the site URL
@ -45,21 +51,21 @@ async fn error404() -> impl Responder {
// Handle a given shortlink // Handle a given shortlink
#[get("/{shortlink}")] #[get("/{shortlink}")]
async fn link_handler(shortlink: web::Path<String>) -> impl Responder { async fn link_handler(shortlink: web::Path<String>, data: web::Data<AppState>) -> impl Responder {
let shortlink_str = shortlink.to_string(); let shortlink_str = shortlink.to_string();
let longlink = utils::get_longurl(shortlink_str); let longlink = utils::get_longurl(shortlink_str, &data.db);
if longlink == "".to_string() { if longlink == "".to_string() {
Redirect::to("/err/404") Redirect::to("/err/404")
} else { } else {
database::add_hit(shortlink.as_str()); database::add_hit(shortlink.as_str(), &data.db);
Redirect::to(longlink).permanent() Redirect::to(longlink).permanent()
} }
} }
// Delete a given shortlink // Delete a given shortlink
#[delete("/api/del/{shortlink}")] #[delete("/api/del/{shortlink}")]
async fn delete_link(shortlink: web::Path<String>) -> HttpResponse { async fn delete_link(shortlink: web::Path<String>, data: web::Data<AppState>) -> HttpResponse {
database::delete_link(shortlink.to_string()); database::delete_link(shortlink.to_string(), &data.db);
HttpResponse::Ok().body("") HttpResponse::Ok().body("")
} }
@ -67,6 +73,9 @@ async fn delete_link(shortlink: web::Path<String>) -> HttpResponse {
async fn main() -> std::io::Result<()> { async fn main() -> std::io::Result<()> {
HttpServer::new(|| { HttpServer::new(|| {
App::new() App::new()
.app_data(web::Data::new(AppState {
db: database::open_db("./urls.sqlite".to_string()),
}))
.service(link_handler) .service(link_handler)
.service(error404) .service(error404)
.service(getall) .service(getall)

View file

@ -1,10 +1,11 @@
use crate::database; use crate::database;
use rand::seq::SliceRandom; use rand::seq::SliceRandom;
use regex::Regex; use regex::Regex;
use rusqlite::Connection;
pub fn get_longurl(shortlink: String) -> String { pub fn get_longurl(shortlink: String, db: &Connection) -> String {
if validate_link(&shortlink) { if validate_link(&shortlink) {
database::find_url(shortlink.as_str()) database::find_url(shortlink.as_str(), db)
} else { } else {
"".to_string() "".to_string()
} }
@ -15,12 +16,12 @@ fn validate_link(link: &str) -> bool {
re.is_match(link) re.is_match(link)
} }
pub fn getall() -> String { pub fn getall(db: &Connection) -> String {
let links = database::getall(); let links = database::getall(db);
links.join("\n") links.join("\n")
} }
pub fn add_link(req: String) -> (bool, String) { pub fn add_link(req: String, db: &Connection) -> (bool, String) {
let chunks: Vec<&str> = req.split(';').collect(); let chunks: Vec<&str> = req.split(';').collect();
let longlink = chunks[0].to_string(); let longlink = chunks[0].to_string();
@ -34,8 +35,11 @@ pub fn add_link(req: String) -> (bool, String) {
shortlink = random_name(); shortlink = random_name();
} }
if validate_link(shortlink.as_str()) && get_longurl(shortlink.clone()) == "".to_string() { if validate_link(shortlink.as_str()) && get_longurl(shortlink.clone(), db) == "".to_string() {
(database::add_link(shortlink.clone(), longlink), shortlink) (
database::add_link(shortlink.clone(), longlink, db),
shortlink,
)
} else { } else {
(false, "shortUrl not valid or already in use".to_string()) (false, "shortUrl not valid or already in use".to_string())
} }