readme
This commit is contained in:
parent
5e83c1218b
commit
a5753a044e
10 changed files with 141 additions and 179 deletions
|
@ -1,3 +1,4 @@
|
|||
DATABASE_URL=postgresql://user:password@localhost/dbname
|
||||
SERVER_HOST=127.0.0.1
|
||||
SERVER_PORT=8080
|
||||
JWT_SECRET=change-me-in-production
|
||||
|
|
64
Cargo.lock
generated
64
Cargo.lock
generated
|
@ -1857,6 +1857,40 @@ dependencies = [
|
|||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-embed"
|
||||
version = "6.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a36224c3276f8c4ebc8c20f158eca7ca4359c8db89991c4925132aaaf6702661"
|
||||
dependencies = [
|
||||
"rust-embed-impl",
|
||||
"rust-embed-utils",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-embed-impl"
|
||||
version = "6.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49b94b81e5b2c284684141a2fb9e2a31be90638caf040bf9afbc5a0416afe1ac"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rust-embed-utils",
|
||||
"syn",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-embed-utils"
|
||||
version = "7.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d38ff6bf570dc3bb7100fce9f7b60c33fa71d80e88da3f2580df4ff2bdded74"
|
||||
dependencies = [
|
||||
"sha2",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.24"
|
||||
|
@ -1897,6 +1931,15 @@ version = "1.0.18"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "schannel"
|
||||
version = "0.1.27"
|
||||
|
@ -2068,8 +2111,10 @@ dependencies = [
|
|||
"dotenv",
|
||||
"jsonwebtoken",
|
||||
"lazy_static",
|
||||
"mime_guess",
|
||||
"rand",
|
||||
"regex",
|
||||
"rust-embed",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sqlx",
|
||||
|
@ -2736,6 +2781,16 @@ version = "0.9.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
|
@ -2832,6 +2887,15 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||
dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
|
|
|
@ -8,6 +8,7 @@ name = "simplelink"
|
|||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
rust-embed = "6.8"
|
||||
jsonwebtoken = "9"
|
||||
actix-web = "4.4"
|
||||
actix-files = "0.6"
|
||||
|
@ -28,4 +29,5 @@ chrono = { version = "0.4", features = ["serde"] }
|
|||
regex = "1.10"
|
||||
lazy_static = "1.4"
|
||||
argon2 = "0.5.3"
|
||||
rand = { version = "0.8", features = ["std"] }
|
||||
rand = { version = "0.8", features = ["std"] }
|
||||
mime_guess = "2.0.5"
|
||||
|
|
38
README.md
Normal file
38
README.md
Normal file
|
@ -0,0 +1,38 @@
|
|||
# SimpleLink
|
||||
A very performant and light (6mb in memory) link shortener and tracker. Written in Rust and React and uses Postgres.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Build
|
||||
|
||||
### From Source
|
||||
First configure .env.example and save it to .env
|
||||
|
||||
The project will not run withot DATABASE_URL set. (TODO add sqlite support)
|
||||
|
||||
```bash
|
||||
#set api-domain to where you will be deploying the link shortener, eg: link.example.com, default is localhost:8080
|
||||
git clone https://github.com/waveringana/simplelink && cd simplelink
|
||||
./build.sh api-domain=localhost:8080
|
||||
cargo run
|
||||
```
|
||||
|
||||
Alternatively if you want a binary form
|
||||
```bash
|
||||
./build.sh --binary
|
||||
```
|
||||
then check /target/release for the binary named `SimpleGit`
|
||||
|
||||
### From Docker
|
||||
```bash
|
||||
docker build --build-arg API_URL=http://localhost:8080 -t simplelink .
|
||||
docker run simplelink -p 8080:8080 \
|
||||
-e JWT_SECRET=change-me-in-production \
|
||||
-e DATABASE_URL=postgres://user:password@host:port/database \
|
||||
simplelink
|
||||
```
|
||||
|
||||
### From Docker Compose
|
||||
Adjust the included docker-compose.yml to your liking, it includes a postgres config as well.
|
16
build.sh
16
build.sh
|
@ -3,6 +3,7 @@
|
|||
# Default values
|
||||
API_URL="http://localhost:8080"
|
||||
RELEASE_MODE=false
|
||||
BINARY_MODE=false
|
||||
|
||||
# Parse command line arguments
|
||||
for arg in "$@"
|
||||
|
@ -16,6 +17,10 @@ do
|
|||
RELEASE_MODE=true
|
||||
shift
|
||||
;;
|
||||
--binary)
|
||||
BINARY_MODE=true
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
|
@ -45,13 +50,9 @@ npm install
|
|||
npm run build
|
||||
cd ..
|
||||
|
||||
# Create static directory if it doesn't exist
|
||||
# Create static directory and copy frontend build
|
||||
mkdir -p static
|
||||
|
||||
# Clean existing static files
|
||||
rm -rf static/*
|
||||
|
||||
# Copy built files to static directory
|
||||
cp -r frontend/dist/* static/
|
||||
|
||||
# Build Rust project
|
||||
|
@ -62,15 +63,16 @@ if [ "$RELEASE_MODE" = true ]; then
|
|||
# Create release directory
|
||||
mkdir -p release
|
||||
|
||||
# Copy binary and static files to release directory
|
||||
# Copy only the binary to release directory
|
||||
cp target/release/simplelink release/
|
||||
cp -r static release/
|
||||
cp .env.example release/.env
|
||||
|
||||
# Create a tar archive
|
||||
tar -czf release.tar.gz release/
|
||||
|
||||
echo "Release archive created: release.tar.gz"
|
||||
elif [ "$BINARY_MODE" = true ]; then
|
||||
cargo build --release
|
||||
else
|
||||
cargo build
|
||||
fi
|
||||
|
|
|
@ -26,11 +26,12 @@ services:
|
|||
- API_URL=${API_URL:-http://localhost:3000}
|
||||
container_name: shortener-app
|
||||
ports:
|
||||
- "3000:3000"
|
||||
- "8080:8080"
|
||||
environment:
|
||||
- DATABASE_URL=postgresql://shortener:shortener123@db:5432/shortener
|
||||
- SERVER_HOST=0.0.0.0
|
||||
- SERVER_PORT=3000
|
||||
- SERVER_PORT=8080
|
||||
- JWT_SECRET=change-me-in-production
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
|
|
166
frontend/package-lock.json
generated
166
frontend/package-lock.json
generated
|
@ -9,7 +9,6 @@
|
|||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.14.0",
|
||||
"@headlessui/react": "^2.2.0",
|
||||
"@hookform/resolvers": "^3.10.0",
|
||||
"@icons-pack/react-simple-icons": "^11.2.0",
|
||||
"@mantine/core": "^7.16.1",
|
||||
|
@ -29,9 +28,7 @@
|
|||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-hook-form": "^7.54.2",
|
||||
"react-simple-icons": "^1.0.0-beta.5",
|
||||
"recharts": "^2.15.0",
|
||||
"simple-icons": "^14.4.0",
|
||||
"tailwind-merge": "^2.6.0",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"zod": "^3.24.1"
|
||||
|
@ -595,25 +592,6 @@
|
|||
"version": "0.2.9",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@headlessui/react": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.2.0.tgz",
|
||||
"integrity": "sha512-RzCEg+LXsuI7mHiSomsu/gBJSjpupm6A1qIZ5sWjd7JhARNlMiSA4kKfJpCKwU9tE+zMRterhhrP74PvfJrpXQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@floating-ui/react": "^0.26.16",
|
||||
"@react-aria/focus": "^3.17.1",
|
||||
"@react-aria/interactions": "^3.21.3",
|
||||
"@tanstack/react-virtual": "^3.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18 || ^19 || ^19.0.0-rc",
|
||||
"react-dom": "^18 || ^19 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/@hookform/resolvers": {
|
||||
"version": "3.10.0",
|
||||
"license": "MIT",
|
||||
|
@ -722,10 +700,6 @@
|
|||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@jxnblk/simple-icons": {
|
||||
"version": "1.0.0",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@mantine/core": {
|
||||
"version": "7.16.1",
|
||||
"license": "MIT",
|
||||
|
@ -1395,92 +1369,6 @@
|
|||
"version": "1.1.0",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@react-aria/focus": {
|
||||
"version": "3.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.19.1.tgz",
|
||||
"integrity": "sha512-bix9Bu1Ue7RPcYmjwcjhB14BMu2qzfJ3tMQLqDc9pweJA66nOw8DThy3IfVr8Z7j2PHktOLf9kcbiZpydKHqzg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@react-aria/interactions": "^3.23.0",
|
||||
"@react-aria/utils": "^3.27.0",
|
||||
"@react-types/shared": "^3.27.0",
|
||||
"@swc/helpers": "^0.5.0",
|
||||
"clsx": "^2.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1",
|
||||
"react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-aria/interactions": {
|
||||
"version": "3.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.23.0.tgz",
|
||||
"integrity": "sha512-0qR1atBIWrb7FzQ+Tmr3s8uH5mQdyRH78n0krYaG8tng9+u1JlSi8DGRSaC9ezKyNB84m7vHT207xnHXGeJ3Fg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@react-aria/ssr": "^3.9.7",
|
||||
"@react-aria/utils": "^3.27.0",
|
||||
"@react-types/shared": "^3.27.0",
|
||||
"@swc/helpers": "^0.5.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1",
|
||||
"react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-aria/ssr": {
|
||||
"version": "3.9.7",
|
||||
"resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.7.tgz",
|
||||
"integrity": "sha512-GQygZaGlmYjmYM+tiNBA5C6acmiDWF52Nqd40bBp0Znk4M4hP+LTmI0lpI1BuKMw45T8RIhrAsICIfKwZvi2Gg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@swc/helpers": "^0.5.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 12"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-aria/utils": {
|
||||
"version": "3.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.27.0.tgz",
|
||||
"integrity": "sha512-p681OtApnKOdbeN8ITfnnYqfdHS0z7GE+4l8EXlfLnr70Rp/9xicBO6d2rU+V/B3JujDw2gPWxYKEnEeh0CGCw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@react-aria/ssr": "^3.9.7",
|
||||
"@react-stately/utils": "^3.10.5",
|
||||
"@react-types/shared": "^3.27.0",
|
||||
"@swc/helpers": "^0.5.0",
|
||||
"clsx": "^2.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1",
|
||||
"react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-stately/utils": {
|
||||
"version": "3.10.5",
|
||||
"resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.10.5.tgz",
|
||||
"integrity": "sha512-iMQSGcpaecghDIh3mZEpZfoFH3ExBwTtuBEcvZ2XnGzCgQjeYXcMdIUwAfVQLXFTdHUHGF6Gu6/dFrYsCzySBQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@swc/helpers": "^0.5.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-types/shared": {
|
||||
"version": "3.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.27.0.tgz",
|
||||
"integrity": "sha512-gvznmLhi6JPEf0bsq7SwRYTHAKKq/wcmKqFez9sRdbED+SPMUmK5omfZ6w3EwUFQHbYUa4zPBYedQ7Knv70RMw==",
|
||||
"license": "Apache-2.0",
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||
"version": "4.32.0",
|
||||
"cpu": [
|
||||
|
@ -1492,15 +1380,6 @@
|
|||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@swc/helpers": {
|
||||
"version": "0.5.15",
|
||||
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
|
||||
"integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"tslib": "^2.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/node": {
|
||||
"version": "4.0.0",
|
||||
"license": "MIT",
|
||||
|
@ -1570,33 +1449,6 @@
|
|||
"vite": "^5.2.0 || ^6"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/react-virtual": {
|
||||
"version": "3.11.3",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.11.3.tgz",
|
||||
"integrity": "sha512-vCU+OTylXN3hdC8RKg68tPlBPjjxtzon7Ys46MgrSLE+JhSjSTPvoQifV6DQJeJmA8Q3KT6CphJbejupx85vFw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@tanstack/virtual-core": "3.11.3"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/tannerlinsley"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/virtual-core": {
|
||||
"version": "3.11.3",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.11.3.tgz",
|
||||
"integrity": "sha512-v2mrNSnMwnPJtcVqNvV0c5roGCBqeogN8jDtgtuHCphdwBasOZ17x8UV8qpHUh+u0MLfX43c0uUHKje0s+Zb0w==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/tannerlinsley"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/babel__core": {
|
||||
"version": "7.20.5",
|
||||
"dev": true,
|
||||
|
@ -3488,13 +3340,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-simple-icons": {
|
||||
"version": "1.0.0-beta.5",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jxnblk/simple-icons": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-smooth": {
|
||||
"version": "4.0.4",
|
||||
"license": "MIT",
|
||||
|
@ -3715,17 +3560,6 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/simple-icons": {
|
||||
"version": "14.4.0",
|
||||
"license": "CC0-1.0",
|
||||
"engines": {
|
||||
"node": ">=0.12.18"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/simple-icons"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.5.7",
|
||||
"license": "BSD-3-Clause",
|
||||
|
|
BIN
readme_img/mainview.jpg
Normal file
BIN
readme_img/mainview.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 88 KiB |
BIN
readme_img/statview.jpg
Normal file
BIN
readme_img/statview.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 112 KiB |
26
src/main.rs
26
src/main.rs
|
@ -1,12 +1,28 @@
|
|||
use actix_cors::Cors;
|
||||
use actix_files as fs;
|
||||
use actix_web::{web, App, HttpServer};
|
||||
use actix_web::{web, App, HttpResponse, HttpServer};
|
||||
use anyhow::Result;
|
||||
use rust_embed::RustEmbed;
|
||||
use simplelink::check_and_generate_admin_token;
|
||||
use simplelink::{handlers, AppState};
|
||||
use sqlx::postgres::PgPoolOptions;
|
||||
use tracing::info;
|
||||
|
||||
#[derive(RustEmbed)]
|
||||
#[folder = "static/"]
|
||||
struct Asset;
|
||||
|
||||
async fn serve_static_file(path: &str) -> HttpResponse {
|
||||
match Asset::get(path) {
|
||||
Some(content) => {
|
||||
let mime = mime_guess::from_path(path).first_or_octet_stream();
|
||||
HttpResponse::Ok()
|
||||
.content_type(mime.as_ref())
|
||||
.body(content.data.into_owned())
|
||||
}
|
||||
None => HttpResponse::NotFound().body("404 Not Found"),
|
||||
}
|
||||
}
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> Result<()> {
|
||||
// Load environment variables from .env file
|
||||
|
@ -68,7 +84,11 @@ async fn main() -> Result<()> {
|
|||
.route("/health", web::get().to(handlers::health_check)),
|
||||
)
|
||||
.service(web::resource("/{short_code}").route(web::get().to(handlers::redirect_to_url)))
|
||||
.service(fs::Files::new("/", "./static").index_file("index.html"))
|
||||
.default_service(web::route().to(|req: actix_web::HttpRequest| async move {
|
||||
let path = req.path().trim_start_matches('/');
|
||||
let path = if path.is_empty() { "index.html" } else { path };
|
||||
serve_static_file(path).await
|
||||
}))
|
||||
})
|
||||
.workers(2)
|
||||
.backlog(10_000)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue