Compare commits
No commits in common. "247cfb0476f6919e35e10d49523974c4bdd9702c" and "2c56c686370f84bb7bbe9266390c5b8134387542" have entirely different histories.
247cfb0476
...
2c56c68637
39
README.md
39
README.md
@ -128,17 +128,6 @@ docker run -p 4567:4567 \
|
|||||||
-e site_url="https://www.example.com" \
|
-e site_url="https://www.example.com" \
|
||||||
-d chhoto-url:latest
|
-d chhoto-url:latest
|
||||||
```
|
```
|
||||||
1.c Optionally, set an API key to activate JSON result mode (optional)
|
|
||||||
|
|
||||||
```
|
|
||||||
docker run -p 4567:4567 \
|
|
||||||
-e password="password" \
|
|
||||||
-e api_key="SECURE_API_KEY" \
|
|
||||||
-v ./urls.sqlite:/urls.sqlite \
|
|
||||||
-e db_url=/urls.sqlite \
|
|
||||||
-e site_url="https://www.example.com" \
|
|
||||||
-d chhoto-url:latest
|
|
||||||
```
|
|
||||||
|
|
||||||
You can set the redirect method to Permanent 308 (default) or Temporary 307 by setting
|
You can set the redirect method to Permanent 308 (default) or Temporary 307 by setting
|
||||||
the `redirect_method` variable to `TEMPORARY` or `PERMANENT` (it's matched exactly). By
|
the `redirect_method` variable to `TEMPORARY` or `PERMANENT` (it's matched exactly). By
|
||||||
@ -159,7 +148,6 @@ served through a proxy.
|
|||||||
The application can be used from the terminal using something like `curl`. In all the examples
|
The application can be used from the terminal using something like `curl`. In all the examples
|
||||||
below, replace `http://localhost:4567` with where your instance of `chhoto-url` is accessible.
|
below, replace `http://localhost:4567` with where your instance of `chhoto-url` is accessible.
|
||||||
|
|
||||||
### Cookie validation
|
|
||||||
If you have set up
|
If you have set up
|
||||||
a password, first do the following to get an authentication cookie and store it in a file.
|
a password, first do the following to get an authentication cookie and store it in a file.
|
||||||
```bash
|
```bash
|
||||||
@ -185,33 +173,6 @@ curl -X DELETE http://localhost:4567/api/del/<shortlink>
|
|||||||
```
|
```
|
||||||
The server will send a confirmation.
|
The server will send a confirmation.
|
||||||
|
|
||||||
### API key validation
|
|
||||||
**This is required for programs that rely on a JSON response from Chhoto URL**
|
|
||||||
|
|
||||||
In order to use API key validation, set the `api_key` environment variable. If this is not set, the API will default to cookie validation (see section above).
|
|
||||||
If the API key is insecure, a warning will be outputted along with a generated API key which may be used.
|
|
||||||
|
|
||||||
To add a link:
|
|
||||||
``` bash
|
|
||||||
curl -X POST -H "Chhoto-Api-Key: <YOUR_API_KEY>" -d '{"shortlink":"<shortlink>", "longlink":"<longlink>"}' http://localhost:4567/api/new
|
|
||||||
```
|
|
||||||
|
|
||||||
To get a list of all the currently available links:
|
|
||||||
``` bash
|
|
||||||
curl -H "Chhoto-Api-Key: <YOUR_API_KEY>" http://localhost:4567/api/all
|
|
||||||
```
|
|
||||||
|
|
||||||
To delete a link:
|
|
||||||
``` bash
|
|
||||||
curl -X DELETE -H "Chhoto-Api-Key: <YOUR_API_KEY>" http://localhost:4567/api/del/<shortlink>
|
|
||||||
```
|
|
||||||
Where `<shortlink>` is name of the shortened link you would like to delete. For example, if the shortened link is `http://localhost:4567/example`, `<shortlink>` would be `example`.
|
|
||||||
|
|
||||||
The server will output when the instance is accessed over API, when an incorrect API key is received, etc.
|
|
||||||
|
|
||||||
|
|
||||||
In both modes, these routes are accessible:
|
|
||||||
|
|
||||||
You can get the version of `chhoto-url` the server is running using `curl http://localhost:4567/api/version` and
|
You can get the version of `chhoto-url` the server is running using `curl http://localhost:4567/api/version` and
|
||||||
get the siteurl using `curl http://localhost:4567/api/siteurl`.
|
get the siteurl using `curl http://localhost:4567/api/siteurl`.
|
||||||
|
|
||||||
|
80
actix/Cargo.lock
generated
80
actix/Cargo.lock
generated
@ -19,6 +19,21 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "actix-cors"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f9e772b3bcafe335042b5db010ab7c09013dad6eac4915c91d8d50902769f331"
|
||||||
|
dependencies = [
|
||||||
|
"actix-utils",
|
||||||
|
"actix-web",
|
||||||
|
"derive_more 0.99.18",
|
||||||
|
"futures-util",
|
||||||
|
"log",
|
||||||
|
"once_cell",
|
||||||
|
"smallvec",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "actix-files"
|
name = "actix-files"
|
||||||
version = "0.6.6"
|
version = "0.6.6"
|
||||||
@ -225,6 +240,21 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "actix-web-httpauth"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "456348ed9dcd72a13a1f4a660449fafdecee9ac8205552e286809eb5b0b29bd3"
|
||||||
|
dependencies = [
|
||||||
|
"actix-utils",
|
||||||
|
"actix-web",
|
||||||
|
"base64 0.22.1",
|
||||||
|
"futures-core",
|
||||||
|
"futures-util",
|
||||||
|
"log",
|
||||||
|
"pin-project-lite",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "addr2line"
|
name = "addr2line"
|
||||||
version = "0.24.2"
|
version = "0.24.2"
|
||||||
@ -478,12 +508,13 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||||||
name = "chhoto-url"
|
name = "chhoto-url"
|
||||||
version = "5.4.6"
|
version = "5.4.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"actix-cors",
|
||||||
"actix-files",
|
"actix-files",
|
||||||
"actix-session",
|
"actix-session",
|
||||||
"actix-web",
|
"actix-web",
|
||||||
|
"actix-web-httpauth",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"nanoid",
|
"nanoid",
|
||||||
"passwords",
|
|
||||||
"rand",
|
"rand",
|
||||||
"regex",
|
"regex",
|
||||||
"rusqlite",
|
"rusqlite",
|
||||||
@ -737,6 +768,7 @@ dependencies = [
|
|||||||
"futures-task",
|
"futures-task",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"pin-utils",
|
"pin-utils",
|
||||||
|
"slab",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1228,15 +1260,6 @@ dependencies = [
|
|||||||
"windows-targets",
|
"windows-targets",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "passwords"
|
|
||||||
version = "3.1.16"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "11407193a7c2bd14ec6b0ec3394da6fdcf7a4d5dcbc8c3cc38dfb17802c8d59c"
|
|
||||||
dependencies = [
|
|
||||||
"random-pick",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "paste"
|
name = "paste"
|
||||||
version = "1.0.15"
|
version = "1.0.15"
|
||||||
@ -1294,12 +1317,6 @@ dependencies = [
|
|||||||
"zerocopy",
|
"zerocopy",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "proc-macro-hack"
|
|
||||||
version = "0.5.20+deprecated"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.89"
|
version = "1.0.89"
|
||||||
@ -1348,37 +1365,6 @@ dependencies = [
|
|||||||
"getrandom",
|
"getrandom",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "random-number"
|
|
||||||
version = "0.1.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7fc8cdd49be664772ffc3dbfa743bb8c34b78f9cc6a9f50e56ae878546796067"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro-hack",
|
|
||||||
"rand",
|
|
||||||
"random-number-macro-impl",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "random-number-macro-impl"
|
|
||||||
version = "0.1.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f5135143cb48d14289139e4615bffec0d59b4cbfd4ea2398a3770bd2abfc4aa2"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro-hack",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "random-pick"
|
|
||||||
version = "1.2.16"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c179499072da789afe44127d5f4aa6012de2c2f96ef759990196b37387a2a0f8"
|
|
||||||
dependencies = [
|
|
||||||
"random-number",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.5.7"
|
version = "0.5.7"
|
||||||
|
@ -29,6 +29,8 @@ categories = ["web-programming"]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "4.5.1"
|
actix-web = "4.5.1"
|
||||||
actix-files = "0.6.5"
|
actix-files = "0.6.5"
|
||||||
|
actix-cors = "0.7.0"
|
||||||
|
actix-web-httpauth = "0.8.2"
|
||||||
rusqlite = { version = "0.32.0", features = ["bundled"] }
|
rusqlite = { version = "0.32.0", features = ["bundled"] }
|
||||||
regex = "1.10.3"
|
regex = "1.10.3"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// SPDX-FileCopyrightText: 2023 Sayantan Santra <sayantan.santra689@gmail.com>
|
// SPDX-FileCopyrightText: 2023 Sayantan Santra <sayantan.santra689@gmail.com>
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
use rusqlite::Connection;
|
use rusqlite::{Connection};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
// Struct for encoding a DB row
|
// Struct for encoding a DB row
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
use actix_files::NamedFile;
|
use actix_files::NamedFile;
|
||||||
use actix_session::Session;
|
use actix_session::Session;
|
||||||
use actix_web::{delete, get, http::StatusCode, post, web::{self, Redirect}, Either, HttpRequest, HttpResponse, Responder};
|
use actix_web::{delete, get, http::StatusCode, post, web::{self, Redirect}, Either, HttpRequest, HttpResponse, Responder};
|
||||||
use std::env;
|
use std::{env};
|
||||||
|
|
||||||
// Serialize JSON data
|
// Serialize JSON data
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
@ -25,14 +25,6 @@ struct Response {
|
|||||||
reason: String,
|
reason: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Needs to return the short URL to make it easier for programs leveraging the API
|
|
||||||
#[derive(Serialize)]
|
|
||||||
struct CreatedURL {
|
|
||||||
success: bool,
|
|
||||||
error: bool,
|
|
||||||
shorturl: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Define the routes
|
// Define the routes
|
||||||
|
|
||||||
// Add new links
|
// Add new links
|
||||||
@ -44,24 +36,9 @@ pub async fn add_link(req: String, data: web::Data<AppState>, session: Session,
|
|||||||
if result.success {
|
if result.success {
|
||||||
let out = utils::add_link(req, &data.db);
|
let out = utils::add_link(req, &data.db);
|
||||||
if out.0 {
|
if out.0 {
|
||||||
let port = env::var("port")
|
HttpResponse::Created().body(out.1)
|
||||||
.unwrap_or(String::from("4567"))
|
|
||||||
.parse::<u16>()
|
|
||||||
.expect("Supplied port is not an integer");
|
|
||||||
let url = format!("{}:{}", env::var("site_url").unwrap_or(String::from("http://localhost")), port);
|
|
||||||
let response = CreatedURL {
|
|
||||||
success: true,
|
|
||||||
error: false,
|
|
||||||
shorturl: format!("{}/{}", url, out.1)
|
|
||||||
};
|
|
||||||
HttpResponse::Created().json(response)
|
|
||||||
} else {
|
} else {
|
||||||
let response = Response {
|
HttpResponse::Conflict().body(out.1)
|
||||||
success: false,
|
|
||||||
error: true,
|
|
||||||
reason: out.1
|
|
||||||
};
|
|
||||||
HttpResponse::Conflict().json(response)
|
|
||||||
}
|
}
|
||||||
} else if result.error {
|
} else if result.error {
|
||||||
HttpResponse::Unauthorized().json(result)
|
HttpResponse::Unauthorized().json(result)
|
||||||
|
@ -18,7 +18,6 @@ struct URLPair {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Define JSON struct for response
|
// Define JSON struct for response
|
||||||
// Named "ReturnResponse" rather than "Response" because of the previous import.
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct Response {
|
pub struct Response {
|
||||||
pub(crate) success: bool,
|
pub(crate) success: bool,
|
||||||
@ -47,16 +46,10 @@ pub fn is_api_ok(http: HttpRequest) -> Response {
|
|||||||
let result = Response { success: false, error: false, reason: "Chhoto-Api-Key header not found".to_string(), pass: true };
|
let result = Response { success: false, error: false, reason: "Chhoto-Api-Key header not found".to_string(), pass: true };
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// If the API key isn't set, but an API Key header is provided
|
|
||||||
if let Some(_) = auth::api_header(&http) {
|
|
||||||
let result = Response {success: false, error: true, reason: "API key access was attempted, but no API key is configured".to_string(), pass: false};
|
|
||||||
result
|
|
||||||
} else {
|
} else {
|
||||||
let result = Response {success: false, error: false, reason: "".to_string(), pass: true};
|
let result = Response {success: false, error: false, reason: "".to_string(), pass: true};
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
13
compose.yaml
13
compose.yaml
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
chhoto-url:
|
chhoto-url:
|
||||||
image: sintan1729/chhoto-url:latest
|
image: chhoto-url
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
container_name: chhoto-url
|
container_name: chhoto-url
|
||||||
ports:
|
ports:
|
||||||
@ -25,10 +25,7 @@ services:
|
|||||||
|
|
||||||
- password=TopSecretPass
|
- password=TopSecretPass
|
||||||
|
|
||||||
# This needs to be set in order to use programs that use the JSON interface of Chhoto URL.
|
- api_key=test
|
||||||
# You will get a warning if this is insecure, and a generated value will be outputted
|
|
||||||
# You may use that value if you can't think of a secure key
|
|
||||||
# - api_key=SECURE_API_KEY
|
|
||||||
|
|
||||||
# Pass the redirect method, if needed. TEMPORARY and PERMANENT
|
# Pass the redirect method, if needed. TEMPORARY and PERMANENT
|
||||||
# are accepted values, defaults to PERMANENT.
|
# are accepted values, defaults to PERMANENT.
|
||||||
@ -38,12 +35,12 @@ services:
|
|||||||
# If you want UIDs, please change slug_style to UID.
|
# If you want UIDs, please change slug_style to UID.
|
||||||
# Supported values for slug_style are Pair and UID.
|
# Supported values for slug_style are Pair and UID.
|
||||||
# The length is 8 by default, and a minimum of 4 is allowed.
|
# The length is 8 by default, and a minimum of 4 is allowed.
|
||||||
# - slug_style=Pair
|
- slug_style=Pair
|
||||||
# - slug_length=8
|
- slug_length=8
|
||||||
|
|
||||||
# In case you want to provide public access to adding links (and not
|
# In case you want to provide public access to adding links (and not
|
||||||
# delete, or listing), change the following option to Enable.
|
# delete, or listing), change the following option to Enable.
|
||||||
# - public_mode=Disable
|
- public_mode=Disable
|
||||||
|
|
||||||
# By default, the server sends no Cache-Control headers. You can supply a
|
# By default, the server sends no Cache-Control headers. You can supply a
|
||||||
# comma separated list of valid header as per RFC 7234 §5.2 to send those
|
# comma separated list of valid header as per RFC 7234 §5.2 to send those
|
||||||
|
Loading…
Reference in New Issue
Block a user