Use one database connection throghout

This commit is contained in:
SinTan1729 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;
pub fn find_url(shortlink: &str) -> String {
let db = Connection::open("./urls.sqlite").expect("Unable to open database!");
pub fn find_url(shortlink: &str, db: &Connection) -> String {
let mut statement = db
.prepare_cached("SELECT long_url FROM urls WHERE short_url = ?1")
.unwrap();
@ -19,8 +17,7 @@ pub fn find_url(shortlink: &str) -> String {
longlink
}
pub fn getall() -> Vec<String> {
let db = Connection::open("./urls.sqlite").expect("Unable to open database!");
pub fn getall(db: &Connection) -> Vec<String> {
let mut statement = db.prepare_cached("SELECT * FROM urls").unwrap();
let mut data = statement.query([]).unwrap();
@ -36,8 +33,7 @@ pub fn getall() -> Vec<String> {
links
}
pub fn add_hit(shortlink: &str) -> () {
let db = Connection::open("./urls.sqlite").expect("Unable to open database!");
pub fn add_hit(shortlink: &str, db: &Connection) -> () {
db.execute(
"UPDATE urls SET hits = hits + 1 WHERE short_url = ?1",
[shortlink],
@ -45,9 +41,7 @@ pub fn add_hit(shortlink: &str) -> () {
.unwrap();
}
pub fn add_link(shortlink: String, longlink: String) -> bool {
let db = Connection::open("./urls.sqlite").expect("Unable to open database!");
pub fn add_link(shortlink: String, longlink: String, db: &Connection) -> bool {
match db.execute(
"INSERT INTO urls (long_url, short_url, hits) VALUES (?1, ?2, ?3)",
(longlink, shortlink, 0),
@ -57,8 +51,22 @@ pub fn add_link(shortlink: String, longlink: String) -> bool {
}
}
pub fn delete_link(shortlink: String) -> () {
let db = Connection::open("./urls.sqlite").expect("Unable to open database!");
pub fn delete_link(shortlink: String, db: &Connection) -> () {
db.execute("DELETE FROM urls WHERE short_url = ?1", [shortlink])
.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},
App, HttpResponse, HttpServer, Responder,
};
use rusqlite::Connection;
mod database;
mod utils;
// This struct represents state
struct AppState {
db: Connection,
}
// Define the routes
// Add new links
#[post("/api/new")]
async fn add_link(req: String) -> HttpResponse {
let out = utils::add_link(req);
async fn add_link(req: String, data: web::Data<AppState>) -> HttpResponse {
let out = utils::add_link(req, &data.db);
if out.0 {
println!("ok{}", out.1);
HttpResponse::Ok().body(out.1)
@ -26,8 +32,8 @@ async fn add_link(req: String) -> HttpResponse {
// Return all active links
#[get("/api/all")]
async fn getall() -> HttpResponse {
HttpResponse::Ok().body(utils::getall())
async fn getall(data: web::Data<AppState>) -> HttpResponse {
HttpResponse::Ok().body(utils::getall(&data.db))
}
// Get the site URL
@ -45,21 +51,21 @@ async fn error404() -> impl Responder {
// Handle a given 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 longlink = utils::get_longurl(shortlink_str);
let longlink = utils::get_longurl(shortlink_str, &data.db);
if longlink == "".to_string() {
Redirect::to("/err/404")
} else {
database::add_hit(shortlink.as_str());
database::add_hit(shortlink.as_str(), &data.db);
Redirect::to(longlink).permanent()
}
}
// Delete a given shortlink
#[delete("/api/del/{shortlink}")]
async fn delete_link(shortlink: web::Path<String>) -> HttpResponse {
database::delete_link(shortlink.to_string());
async fn delete_link(shortlink: web::Path<String>, data: web::Data<AppState>) -> HttpResponse {
database::delete_link(shortlink.to_string(), &data.db);
HttpResponse::Ok().body("")
}
@ -67,6 +73,9 @@ async fn delete_link(shortlink: web::Path<String>) -> HttpResponse {
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.app_data(web::Data::new(AppState {
db: database::open_db("./urls.sqlite".to_string()),
}))
.service(link_handler)
.service(error404)
.service(getall)

View File

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