1
0
Fork 0
mirror of https://github.com/SinTan1729/chhoto-url synced 2025-04-30 12:56:52 -05:00

Compare commits

...

7 commits
5.7.0 ... main

6 changed files with 44 additions and 40 deletions

View file

@ -38,9 +38,9 @@ for small. URL means, well... URL. So the name simply means Small URL.
# Features
- Shortens URLs of any length to a randomly generated link.
- (Optional) Allows you to specify the shortened URL instead of the generated
one. (It's surprisingly missing in a surprising number of alternatives.)
one. (It's missing in a surprising number of alternatives.)
- Opening the shortened URL in your browser will instantly redirect you
to the correct long URL. (So no stupid redirecting pages.)
to the correct long URL. (So no stupid redirection pages.)
- Super lightweight and snappy. (The docker image is only ~6MB and RAM uasge
stays under 5MB under normal use.)
- Counts number of hits for each short link in a privacy respecting way
@ -52,8 +52,8 @@ for small. URL means, well... URL. So the name simply means Small URL.
- Allows setting the URL of your website, in case you want to conveniently
generate short links locally.
- Links are stored in an SQLite database.
- Available as a Docker container.
- Backend written in Rust using [Actix](https://actix.rs/), frontend
- Available as a Docker container with a provided compose file.
- Backend written in Rust using [Actix](https://actix.rs/), and frontend
written in plain HTML and vanilla JS, using [Pure CSS](https://purecss.io/)
for styling.
- Uses very basic authentication using a provided password. It's not encrypted in transport.
@ -61,17 +61,16 @@ for small. URL means, well... URL. So the name simply means Small URL.
encrypt the connection by SSL.
# Bloat that will not be implemented
- Tracking or spying of any kind. The only logs that still exist are
- **Tracking or spying of any kind.** The only logs that still exist are
errors printed to stderr and the basic logging (only warnings) provided by the
[`env_logger`](https://crates.io/crates/env_logger) crate.
- User management. If you need a shortener for your whole organization, either
- **User management.** If you need a shortener for your whole organization, either
run separate containers for everyone or use something else.
- Cookies, newsletters, "we value your privacy" popups or any of the multiple
- **Cookies, newsletters**, "we value your privacy" popups or any of the multiple
other ways modern web shows how anti-user it is. We all hate those, and they're
not needed here.
- Paywalls or messages begging for donations. If you want to support me (for
whatever reason), you can message me through GitHub issues.
- **Paywalls** or messages begging for donations. If you want to buy me a coffee,
you can message me through GitHub discussions or mail me.
# Screenshots
<p align="middle">
<img src="screenshot-desktop.webp" height="250" alt="desktop screenshot" />

26
actix/Cargo.lock generated
View file

@ -31,7 +31,7 @@ dependencies = [
"actix-web",
"bitflags",
"bytes",
"derive_more 0.99.19",
"derive_more 0.99.20",
"futures-core",
"http-range",
"log",
@ -458,7 +458,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chhoto-url"
version = "5.7.0"
version = "5.7.1"
dependencies = [
"actix-files",
"actix-session",
@ -562,9 +562,9 @@ dependencies = [
[[package]]
name = "derive_more"
version = "0.99.19"
version = "0.99.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3da29a38df43d6f156149c9b43ded5e018ddff2a855cf2cfd62e8cd7d079c69f"
checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f"
dependencies = [
"convert_case",
"proc-macro2",
@ -760,9 +760,9 @@ dependencies = [
[[package]]
name = "getrandom"
version = "0.2.15"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
dependencies = [
"cfg-if",
"libc",
@ -1059,9 +1059,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "jiff"
version = "0.2.9"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59ec30f7142be6fe14e1b021f50b85db8df2d4324ea6e91ec3e5dcde092021d0"
checksum = "5a064218214dc6a10fbae5ec5fa888d80c45d611aba169222fc272072bf7aef6"
dependencies = [
"jiff-static",
"log",
@ -1072,9 +1072,9 @@ dependencies = [
[[package]]
name = "jiff-static"
version = "0.2.9"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "526b834d727fd59d37b076b0c3236d9adde1b1729a4361e20b2026f738cc1dbe"
checksum = "199b7932d97e325aff3a7030e141eafe7f2c6268e1d1b24859b753a627f45254"
dependencies = [
"proc-macro2",
"quote",
@ -1407,7 +1407,7 @@ version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom 0.2.15",
"getrandom 0.2.16",
]
[[package]]
@ -1741,9 +1741,9 @@ dependencies = [
[[package]]
name = "tokio-util"
version = "0.7.14"
version = "0.7.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034"
checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df"
dependencies = [
"bytes",
"futures-core",

View file

@ -3,7 +3,7 @@
[package]
name = "chhoto-url"
version = "5.7.0"
version = "5.7.1"
edition = "2021"
authors = ["Sayantan Santra <sayantan[dot]santra689[at]gmail[dot]com"]
license = "mit"

View file

@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2023 Sayantan Santra <sayantan.santra689@gmail.com>
// SPDX-License-Identifier: MIT
use rusqlite::Connection;
use rusqlite::{Connection, Error};
use serde::Serialize;
// Struct for encoding a DB row
@ -67,12 +67,11 @@ pub fn add_hit(shortlink: &str, db: &Connection) {
}
// Insert a new link
pub fn add_link(shortlink: String, longlink: String, db: &Connection) -> bool {
pub fn add_link(shortlink: String, longlink: String, db: &Connection) -> Result<usize, Error> {
db.execute(
"INSERT INTO urls (long_url, short_url, hits) VALUES (?1, ?2, ?3)",
(longlink, shortlink, 0),
)
.is_ok()
}
// Delete and existing link

View file

@ -63,15 +63,9 @@ async fn main() -> Result<()> {
// Set the site_url without the quotes
env::set_var("site_url", url);
eprintln!("WARN: The site_url environment variable is encapsulated by quotes. Automatically adjusting to {}", url);
// Tell the user what URI the server will respond with
eprintln!("INFO: Public URI is: {url}:{port}.")
} else {
// No issues
eprintln!("INFO: Configured Site URL is: {site_url}.");
// Tell the user what URI the server will respond with
eprintln!("INFO: Public URI is: {site_url}:{port}.")
}
} else {
// Site URL is not configured

View file

@ -6,7 +6,7 @@ use actix_web::HttpRequest;
use nanoid::nanoid;
use rand::seq::IndexedRandom;
use regex::Regex;
use rusqlite::Connection;
use rusqlite::{ffi::SQLITE_CONSTRAINT_UNIQUE, Connection};
use serde::{Deserialize, Serialize};
use std::env;
@ -123,15 +123,27 @@ pub fn add_link(req: String, db: &Connection) -> (bool, String) {
len = 4;
}
if chunks.shortlink.is_empty() {
let shortlink_provided = if chunks.shortlink.is_empty() {
chunks.shortlink = gen_link(style, len);
}
false
} else {
true
};
if validate_link(chunks.shortlink.as_str()) {
if database::add_link(chunks.shortlink.clone(), chunks.longlink, db) {
(true, chunks.shortlink)
} else {
match database::add_link(chunks.shortlink.clone(), chunks.longlink, db) {
Ok(_) => (true, chunks.shortlink),
Err(error) => {
if error.sqlite_error().map(|err| err.extended_code)
== Some(SQLITE_CONSTRAINT_UNIQUE)
&& shortlink_provided
{
(false, String::from("Short URL is already in use!"))
} else {
// This should be super rare
(false, String::from("Something went wrong!"))
}
}
}
} else {
(false, String::from("Short URL is not valid!"))