mirror of
https://github.com/SinTan1729/chhoto-url
synced 2025-04-30 12:56:52 -05:00
Compare commits
7 commits
Author | SHA1 | Date | |
---|---|---|---|
bbf5811e13 | |||
efc2b03415 | |||
3aa8884676 | |||
084334cd11 | |||
4eb88f3beb | |||
c23fcdc9bd | |||
21f76f2962 |
6 changed files with 44 additions and 40 deletions
19
README.md
19
README.md
|
@ -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
26
actix/Cargo.lock
generated
|
@ -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",
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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!"))
|
||||
|
|
Loading…
Reference in a new issue