1
0
Fork 0
mirror of https://github.com/SinTan1729/chhoto-url synced 2025-02-05 13:52:33 -06:00

new: Got the expand API path working

It replies with info for a single shortlink. May be useful for
applications using json interface.
This commit is contained in:
Sayantan Santra 2025-01-08 20:09:24 +05:30
parent f952cb88a0
commit 2b9fafe440
Signed by: SinTan1729
GPG key ID: 0538DD402EA50898
4 changed files with 50 additions and 9 deletions

View file

@ -13,14 +13,16 @@ pub struct DBRow {
} }
// Find a single URL // Find a single URL
pub fn find_url(shortlink: &str, db: &Connection) -> Option<String> { pub fn find_url(shortlink: &str, db: &Connection) -> (Option<String>, Option<i64>) {
let mut statement = db let mut statement = db
.prepare_cached("SELECT long_url FROM urls WHERE short_url = ?1") .prepare_cached("SELECT long_url,hits FROM urls WHERE short_url = ?1")
.expect("Error preparing SQL statement for find_url."); .expect("Error preparing SQL statement for find_url.");
statement let longlink = statement
.query_row([shortlink], |row| row.get("long_url")) .query_row([shortlink], |row| row.get("long_url"))
.ok() .ok();
let hits = statement.query_row([shortlink], |row| row.get("hits")).ok();
(longlink, hits)
} }
// Get all URLs in DB // Get all URLs in DB

View file

@ -82,6 +82,7 @@ async fn main() -> Result<()> {
.service(services::delete_link) .service(services::delete_link)
.service(services::login) .service(services::login)
.service(services::logout) .service(services::logout)
.service(services::expand)
.service(Files::new("/", "./resources/").index_file("index.html")) .service(Files::new("/", "./resources/").index_file("index.html"))
.default_service(actix_web::web::get().to(services::error404)) .default_service(actix_web::web::get().to(services::error404))
}) })

View file

@ -31,7 +31,7 @@ struct Response {
reason: String, reason: String,
} }
// Needs to return the short URL to make it easier for programs leveraging the API // Needed to return the short URL to make it easier for programs leveraging the API
#[derive(Serialize)] #[derive(Serialize)]
struct CreatedURL { struct CreatedURL {
success: bool, success: bool,
@ -39,6 +39,15 @@ struct CreatedURL {
shorturl: String, shorturl: String,
} }
// Struct for returning information about a shortlink
#[derive(Serialize)]
struct LinkInfo {
success: bool,
error: bool,
longurl: String,
hits: i64,
}
// Define the routes // Define the routes
// Add new links // Add new links
@ -123,6 +132,35 @@ pub async fn getall(
} }
} }
// Get information about a single shortlink
#[post("/api/expand")]
pub async fn expand(req: String, data: web::Data<AppState>, http: HttpRequest) -> HttpResponse {
let result = utils::is_api_ok(http);
if result.success {
let linkinfo = utils::get_longurl(req, &data.db);
if let Some(longlink) = linkinfo.0 {
let body = LinkInfo {
success: true,
error: false,
longurl: longlink,
hits: linkinfo
.1
.expect("Error getting hit count for existing shortlink."),
};
HttpResponse::Ok().json(body)
} else {
let body = Response {
success: false,
error: true,
reason: "The shortlink does not exist on the server.".to_string(),
};
HttpResponse::Unauthorized().json(body)
}
} else {
HttpResponse::Unauthorized().json(result)
}
}
// Get the site URL // Get the site URL
#[get("/api/siteurl")] #[get("/api/siteurl")]
pub async fn siteurl() -> HttpResponse { pub async fn siteurl() -> HttpResponse {
@ -154,7 +192,7 @@ pub async fn link_handler(
data: web::Data<AppState>, data: web::Data<AppState>,
) -> impl Responder { ) -> impl Responder {
let shortlink_str = shortlink.to_string(); let shortlink_str = shortlink.to_string();
if let Some(longlink) = utils::get_longurl(shortlink_str, &data.db) { if let Some(longlink) = utils::get_longurl(shortlink_str, &data.db).0 {
let redirect_method = env::var("redirect_method").unwrap_or(String::from("PERMANENT")); let redirect_method = env::var("redirect_method").unwrap_or(String::from("PERMANENT"));
database::add_hit(shortlink.as_str(), &data.db); database::add_hit(shortlink.as_str(), &data.db);
if redirect_method == "TEMPORARY" { if redirect_method == "TEMPORARY" {

View file

@ -80,11 +80,11 @@ pub fn is_api_ok(http: HttpRequest) -> Response {
} }
// Request the DB for searching an URL // Request the DB for searching an URL
pub fn get_longurl(shortlink: String, db: &Connection) -> Option<String> { pub fn get_longurl(shortlink: String, db: &Connection) -> (Option<String>, Option<i64>) {
if validate_link(&shortlink) { if validate_link(&shortlink) {
database::find_url(shortlink.as_str(), db) database::find_url(shortlink.as_str(), db)
} else { } else {
None (None, None)
} }
} }
@ -124,7 +124,7 @@ pub fn add_link(req: String, db: &Connection) -> (bool, String) {
} }
if validate_link(chunks.shortlink.as_str()) if validate_link(chunks.shortlink.as_str())
&& get_longurl(chunks.shortlink.clone(), db).is_none() && get_longurl(chunks.shortlink.clone(), db).0.is_none()
{ {
( (
database::add_link(chunks.shortlink.clone(), chunks.longlink, db), database::add_link(chunks.shortlink.clone(), chunks.longlink, db),