Add rate limiting, improve memory usage
This commit is contained in:
215
Cargo.lock
generated
215
Cargo.lock
generated
@@ -125,6 +125,15 @@ version = "0.22.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bincode"
|
||||||
|
version = "1.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.5.0"
|
version = "2.5.0"
|
||||||
@@ -202,6 +211,12 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.8.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crypto-common"
|
name = "crypto-common"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
@@ -212,6 +227,19 @@ dependencies = [
|
|||||||
"typenum",
|
"typenum",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dashmap"
|
||||||
|
version = "5.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"hashbrown",
|
||||||
|
"lock_api",
|
||||||
|
"once_cell",
|
||||||
|
"parking_lot_core",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "data-encoding"
|
name = "data-encoding"
|
||||||
version = "2.6.0"
|
version = "2.6.0"
|
||||||
@@ -275,6 +303,31 @@ dependencies = [
|
|||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "forwarded-header-value"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8835f84f38484cc86f110a805655697908257fb9a7af005234060891557198e9"
|
||||||
|
dependencies = [
|
||||||
|
"nonempty",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures"
|
||||||
|
version = "0.3.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
|
||||||
|
dependencies = [
|
||||||
|
"futures-channel",
|
||||||
|
"futures-core",
|
||||||
|
"futures-executor",
|
||||||
|
"futures-io",
|
||||||
|
"futures-sink",
|
||||||
|
"futures-task",
|
||||||
|
"futures-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-channel"
|
name = "futures-channel"
|
||||||
version = "0.3.30"
|
version = "0.3.30"
|
||||||
@@ -282,6 +335,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
|
checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
"futures-sink",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -290,6 +344,34 @@ version = "0.3.30"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
|
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-executor"
|
||||||
|
version = "0.3.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-task",
|
||||||
|
"futures-util",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-io"
|
||||||
|
version = "0.3.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-macro"
|
||||||
|
version = "0.3.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-sink"
|
name = "futures-sink"
|
||||||
version = "0.3.30"
|
version = "0.3.30"
|
||||||
@@ -302,15 +384,25 @@ version = "0.3.30"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
|
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-timer"
|
||||||
|
version = "3.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-util"
|
name = "futures-util"
|
||||||
version = "0.3.30"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
|
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
"futures-io",
|
||||||
|
"futures-macro",
|
||||||
"futures-sink",
|
"futures-sink",
|
||||||
"futures-task",
|
"futures-task",
|
||||||
|
"memchr",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"pin-utils",
|
"pin-utils",
|
||||||
"slab",
|
"slab",
|
||||||
@@ -343,6 +435,32 @@ version = "0.28.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
|
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "governor"
|
||||||
|
version = "0.6.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "68a7f542ee6b35af73b06abc0dad1c1bae89964e4e253bc4b587b91c9637867b"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"dashmap",
|
||||||
|
"futures",
|
||||||
|
"futures-timer",
|
||||||
|
"no-std-compat",
|
||||||
|
"nonzero_ext",
|
||||||
|
"parking_lot",
|
||||||
|
"portable-atomic",
|
||||||
|
"quanta",
|
||||||
|
"rand",
|
||||||
|
"smallvec",
|
||||||
|
"spinning_top",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.14.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
@@ -524,6 +642,16 @@ version = "2.7.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
|
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memory-stats"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34f79cf9964c5c9545493acda1263f1912f8d2c56c8a2ffee2606cb960acaacc"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mime"
|
name = "mime"
|
||||||
version = "0.3.17"
|
version = "0.3.17"
|
||||||
@@ -560,6 +688,24 @@ dependencies = [
|
|||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "no-std-compat"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nonempty"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nonzero_ext"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nu-ansi-term"
|
name = "nu-ansi-term"
|
||||||
version = "0.46.0"
|
version = "0.46.0"
|
||||||
@@ -615,13 +761,17 @@ name = "painter"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
|
"bincode",
|
||||||
|
"bytes",
|
||||||
"chrono",
|
"chrono",
|
||||||
"dotenv",
|
"dotenv",
|
||||||
|
"memory-stats",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"socketioxide",
|
"socketioxide",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tower-http",
|
"tower-http",
|
||||||
|
"tower_governor",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
]
|
]
|
||||||
@@ -687,6 +837,12 @@ version = "0.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "portable-atomic"
|
||||||
|
version = "1.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.17"
|
version = "0.2.17"
|
||||||
@@ -702,6 +858,21 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quanta"
|
||||||
|
version = "0.12.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e5167a477619228a0b284fac2674e3c388cba90631d7b7de620e6f1fcd08da5"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils",
|
||||||
|
"libc",
|
||||||
|
"once_cell",
|
||||||
|
"raw-cpuid",
|
||||||
|
"wasi",
|
||||||
|
"web-sys",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.36"
|
version = "1.0.36"
|
||||||
@@ -741,6 +912,15 @@ dependencies = [
|
|||||||
"getrandom",
|
"getrandom",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "raw-cpuid"
|
||||||
|
version = "11.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e29830cbb1290e404f24c73af91c5d8d631ce7e128691e9477556b540cd01ecd"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
@@ -903,6 +1083,15 @@ dependencies = [
|
|||||||
"tower",
|
"tower",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spinning_top"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.63"
|
version = "2.0.63"
|
||||||
@@ -1079,6 +1268,22 @@ version = "0.3.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
|
checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tower_governor"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "313fa625fea5790ed56360a30ea980e41229cf482b4835801a67ef1922bf63b9"
|
||||||
|
dependencies = [
|
||||||
|
"axum",
|
||||||
|
"forwarded-header-value",
|
||||||
|
"governor",
|
||||||
|
"http",
|
||||||
|
"pin-project",
|
||||||
|
"thiserror",
|
||||||
|
"tower",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing"
|
name = "tracing"
|
||||||
version = "0.1.40"
|
version = "0.1.40"
|
||||||
@@ -1281,6 +1486,16 @@ version = "0.2.92"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
|
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "web-sys"
|
||||||
|
version = "0.3.69"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef"
|
||||||
|
dependencies = [
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
|||||||
@@ -7,12 +7,16 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
axum = "0.7.5"
|
axum = "0.7.5"
|
||||||
|
bincode = "1.3.3"
|
||||||
|
bytes = "1.6.0"
|
||||||
chrono = "0.4.38"
|
chrono = "0.4.38"
|
||||||
dotenv = "0.15.0"
|
dotenv = "0.15.0"
|
||||||
|
memory-stats = "1.1.0"
|
||||||
serde = { version = "1.0.201", features = ["derive"] }
|
serde = { version = "1.0.201", features = ["derive"] }
|
||||||
serde_json = "1.0.117"
|
serde_json = "1.0.117"
|
||||||
socketioxide = "0.13.1"
|
socketioxide = "0.13.1"
|
||||||
tokio = { version = "1.37.0", features = ["full"] }
|
tokio = { version = "1.37.0", features = ["full"] }
|
||||||
tower-http = { version = "0.5.2", features = ["cors", "fs"] }
|
tower-http = { version = "0.5.2", features = ["cors", "fs"] }
|
||||||
|
tower_governor = "0.4.2"
|
||||||
tracing = "0.1.40"
|
tracing = "0.1.40"
|
||||||
tracing-subscriber = "0.3.18"
|
tracing-subscriber = "0.3.18"
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
import socket from "./socket.js";
|
|
||||||
import {
|
import {
|
||||||
hexToU32,
|
hexToU32,
|
||||||
u32ToHex,
|
u32ToHex,
|
||||||
getColorFromElementCSS,
|
getColorFromElementCSS,
|
||||||
rgbToHex,
|
rgbToHex,
|
||||||
} from "./utils.js";
|
} from "./utils.js";
|
||||||
import { pixelSize, pixelCooldown } from "./constants.js";
|
import {
|
||||||
|
pixelSize,
|
||||||
|
pixelCooldown,
|
||||||
|
canvasEndpoint,
|
||||||
|
WIDTH,
|
||||||
|
HEIGHT,
|
||||||
|
} from "./constants.js";
|
||||||
|
|
||||||
|
let socket = null;
|
||||||
|
|
||||||
const canvas = document.getElementById("canvas");
|
const canvas = document.getElementById("canvas");
|
||||||
const ctx = canvas.getContext("2d");
|
const ctx = canvas.getContext("2d");
|
||||||
@@ -97,37 +104,29 @@ const handleColorPicker = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
handleColorPicker();
|
const fetchCanvasState = async () => {
|
||||||
|
fetch(canvasEndpoint)
|
||||||
|
.then((response) => response.json())
|
||||||
|
.then((data) => {
|
||||||
|
canvasState = data;
|
||||||
|
drawCanvasState(data);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
alert("Error fetching canvas state from server. Please try again later.");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const drawCanvasState = (canvasState) => {
|
const drawCanvasState = (canvasState) => {
|
||||||
for (let y = 0; y < canvasState.length; y++) {
|
for (let y = 0; y < HEIGHT; y++) {
|
||||||
for (let x = 0; x < canvasState[y].length; x++) {
|
for (let x = 0; x < WIDTH; x++) {
|
||||||
const color = u32ToHex(canvasState[y][x]);
|
const index = y * WIDTH + x;
|
||||||
|
const color = u32ToHex(canvasState[index]);
|
||||||
ctx.fillStyle = color;
|
ctx.fillStyle = color;
|
||||||
ctx.fillRect(x * pixelSize, y * pixelSize, pixelSize, pixelSize);
|
ctx.fillRect(x * pixelSize, y * pixelSize, pixelSize, pixelSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
socket.on("init-canvas", (data) => {
|
|
||||||
const canvasData = JSON.parse(data);
|
|
||||||
drawCanvasState(canvasData);
|
|
||||||
canvasState = canvasData;
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on("pixel-updated", (update) => {
|
|
||||||
const color = u32ToHex(update.color);
|
|
||||||
ctx.fillStyle = color;
|
|
||||||
ctx.fillRect(
|
|
||||||
update.x * pixelSize,
|
|
||||||
update.y * pixelSize,
|
|
||||||
pixelSize,
|
|
||||||
pixelSize
|
|
||||||
);
|
|
||||||
|
|
||||||
canvasState[update.y][update.x] = update.color;
|
|
||||||
});
|
|
||||||
|
|
||||||
const checkIfCanPlacePixel = () => {
|
const checkIfCanPlacePixel = () => {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
return now - lastPixelTime >= pixelCooldown;
|
return now - lastPixelTime >= pixelCooldown;
|
||||||
@@ -145,7 +144,8 @@ const handlePlacePixel = (pixelData) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
socket.emit("place-pixel", pixelData);
|
socket.emit("place-pixel", pixelData);
|
||||||
canvasState[pixelData.y][pixelData.x] = pixelData.color;
|
const index = pixelData.y * WIDTH + pixelData.x;
|
||||||
|
canvasState[index] = pixelData.color;
|
||||||
setLastPixelTime();
|
setLastPixelTime();
|
||||||
pixelData = null;
|
pixelData = null;
|
||||||
};
|
};
|
||||||
@@ -218,8 +218,6 @@ const handleToggleGrid = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
handleToggleGrid();
|
|
||||||
|
|
||||||
window.onkeydown = (event) => {
|
window.onkeydown = (event) => {
|
||||||
// on enter (keycode 13 is enter)
|
// on enter (keycode 13 is enter)
|
||||||
if (event.keyCode === 13) {
|
if (event.keyCode === 13) {
|
||||||
@@ -243,3 +241,27 @@ saveCanvasButton.addEventListener("click", () => {
|
|||||||
a.download = "canvas.png";
|
a.download = "canvas.png";
|
||||||
a.click();
|
a.click();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
handleColorPicker();
|
||||||
|
handleToggleGrid();
|
||||||
|
|
||||||
|
export const handleSocketEvents = (_socket) => {
|
||||||
|
socket = _socket;
|
||||||
|
socket.on("connect", () => {
|
||||||
|
fetchCanvasState();
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on("pixel-updated", (update) => {
|
||||||
|
const color = u32ToHex(update.color);
|
||||||
|
ctx.fillStyle = color;
|
||||||
|
ctx.fillRect(
|
||||||
|
update.x * pixelSize,
|
||||||
|
update.y * pixelSize,
|
||||||
|
pixelSize,
|
||||||
|
pixelSize
|
||||||
|
);
|
||||||
|
|
||||||
|
const index = update.y * WIDTH + update.x;
|
||||||
|
canvasState[index] = update.color;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,2 +1,6 @@
|
|||||||
export const pixelSize = 10;
|
export const pixelSize = 10;
|
||||||
export const pixelCooldown = 60 * 1000; // 1 minute
|
export const pixelCooldown = 10 * 1000; // 10 seconds
|
||||||
|
export const canvasEndpoint = "http://localhost:3000/canvas/";
|
||||||
|
export const checkEndpoint = "http://localhost:3000/check/";
|
||||||
|
export const WIDTH = 500;
|
||||||
|
export const HEIGHT = 500;
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import socket from "./socket.js";
|
import { connectToWS } from "./socket.js";
|
||||||
import "./canvas.js";
|
import "./canvas.js";
|
||||||
import "./counter.js";
|
import "./counter.js";
|
||||||
import { updateCountdown } from "./counter.js";
|
import { updateCountdown } from "./counter.js";
|
||||||
import { pixelSize } from "./constants.js";
|
import { checkEndpoint, pixelSize } from "./constants.js";
|
||||||
|
import { handleSocketEvents } from "./canvas.js";
|
||||||
|
|
||||||
const isDebug = import.meta.env.VITE_IS_DEBUG === "true";
|
const isDebug = import.meta.env.VITE_IS_DEBUG === "true";
|
||||||
|
|
||||||
@@ -11,27 +12,46 @@ const currentSoldiersSpan = document.getElementById("current-soldiers");
|
|||||||
let coords = [];
|
let coords = [];
|
||||||
const canvas = document.getElementById("canvas");
|
const canvas = document.getElementById("canvas");
|
||||||
const coordsText = document.getElementById("coords");
|
const coordsText = document.getElementById("coords");
|
||||||
|
const ogCanvasStyle = canvas.style.display;
|
||||||
|
canvas.style.display = "none";
|
||||||
|
|
||||||
socket.on("connect", () => {
|
fetch(checkEndpoint)
|
||||||
console.log("connect");
|
.then((response) => {
|
||||||
});
|
if (response.ok) {
|
||||||
|
const socket = connectToWS();
|
||||||
|
|
||||||
socket.on("error", (message) => {
|
socket.on("connect", () => {
|
||||||
alert(message);
|
canvas.style.display = ogCanvasStyle;
|
||||||
});
|
console.log("connect");
|
||||||
|
});
|
||||||
|
|
||||||
socket.on("current_soldiers", (currentSoldiers) => {
|
socket.on("error", (message) => {
|
||||||
currentSoldiersSpan.textContent = currentSoldiers;
|
alert(message);
|
||||||
});
|
});
|
||||||
|
|
||||||
requestAnimationFrame(updateCountdown);
|
socket.on("current_soldiers", (currentSoldiers) => {
|
||||||
|
currentSoldiersSpan.textContent = currentSoldiers;
|
||||||
|
});
|
||||||
|
|
||||||
window.addEventListener("mousemove", (event) => {
|
handleSocketEvents(socket);
|
||||||
// get coordinates of the mouse inside the canvas
|
|
||||||
const rect = canvas.getBoundingClientRect();
|
|
||||||
const x = Math.floor((event.clientX - rect.left) / pixelSize);
|
|
||||||
const y = Math.floor((event.clientY - rect.top) / pixelSize);
|
|
||||||
coords = [x, y];
|
|
||||||
|
|
||||||
coordsText.textContent = `${x}, ${y}`;
|
requestAnimationFrame(updateCountdown);
|
||||||
});
|
|
||||||
|
window.addEventListener("mousemove", (event) => {
|
||||||
|
// get coordinates of the mouse inside the canvas
|
||||||
|
const rect = canvas.getBoundingClientRect();
|
||||||
|
const x = Math.floor((event.clientX - rect.left) / pixelSize);
|
||||||
|
const y = Math.floor((event.clientY - rect.top) / pixelSize);
|
||||||
|
coords = [x, y];
|
||||||
|
|
||||||
|
coordsText.textContent = `${x}, ${y}`;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
throw new Error("Can't connect to the server");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
alert(
|
||||||
|
"You have already connected to the server from another tab or window. Please close the other tab or window and refresh this page."
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|||||||
@@ -6,12 +6,16 @@ const wsHost = window.location.host;
|
|||||||
|
|
||||||
let socket;
|
let socket;
|
||||||
|
|
||||||
if (isDebug) {
|
export const connectToWS = () => {
|
||||||
socket = io("ws://localhost:3000");
|
if (isDebug) {
|
||||||
} else {
|
socket = io("ws://localhost:3000");
|
||||||
socket = io(`${wsProtocol}//${wsHost}`, {
|
} else {
|
||||||
transports: ["websocket"],
|
socket = io(`${wsProtocol}//${wsHost}`, {
|
||||||
});
|
transports: ["websocket"],
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return socket;
|
||||||
|
};
|
||||||
|
|
||||||
export default socket;
|
export default socket;
|
||||||
|
|||||||
@@ -6,8 +6,6 @@
|
|||||||
.rainbow-border {
|
.rainbow-border {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
border-radius: 0.5rem; /* Rounded corners */
|
|
||||||
padding: 5px; /* Space for the border */
|
|
||||||
background: linear-gradient(to right, red, orange, yellow, green, blue, indigo, violet);
|
background: linear-gradient(to right, red, orange, yellow, green, blue, indigo, violet);
|
||||||
}
|
}
|
||||||
.rainbow-border::before {
|
.rainbow-border::before {
|
||||||
@@ -17,8 +15,6 @@
|
|||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
margin: -5px; /* Negative margin to overlap the gradient */
|
|
||||||
border-radius: 0.5rem; /* Match the rounded corners */
|
|
||||||
background: white;
|
background: white;
|
||||||
z-index: -1; /* Place behind the content */
|
z-index: -1; /* Place behind the content */
|
||||||
}
|
}
|
||||||
|
|||||||
213
src/main.rs
213
src/main.rs
@@ -1,16 +1,22 @@
|
|||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
|
net::SocketAddr,
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
};
|
};
|
||||||
|
|
||||||
use axum::Router;
|
use axum::{routing::get, Extension, Json, Router, ServiceExt};
|
||||||
use chrono::{DateTime, Duration, Utc};
|
use chrono::{DateTime, Duration, Utc};
|
||||||
|
use memory_stats::memory_stats;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use socketioxide::{
|
use socketioxide::{
|
||||||
extract::{Bin, Data, SocketRef},
|
extract::{Bin, Data, SocketRef},
|
||||||
SocketIo,
|
SocketIo,
|
||||||
};
|
};
|
||||||
|
use tower_governor::{
|
||||||
|
governor::{GovernorConfig, GovernorConfigBuilder},
|
||||||
|
GovernorLayer,
|
||||||
|
};
|
||||||
use tower_http::{
|
use tower_http::{
|
||||||
cors::{Any, CorsLayer},
|
cors::{Any, CorsLayer},
|
||||||
services::ServeDir,
|
services::ServeDir,
|
||||||
@@ -18,6 +24,10 @@ use tower_http::{
|
|||||||
use tracing::info;
|
use tracing::info;
|
||||||
use tracing_subscriber::FmtSubscriber;
|
use tracing_subscriber::FmtSubscriber;
|
||||||
|
|
||||||
|
type Canvas = Arc<Mutex<Vec<u32>>>;
|
||||||
|
type LastUpdate = Arc<Mutex<HashMap<String, DateTime<Utc>>>>;
|
||||||
|
type Soldiers = Arc<Mutex<HashSet<String>>>;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
struct PixelUpdate {
|
struct PixelUpdate {
|
||||||
x: u32,
|
x: u32,
|
||||||
@@ -25,99 +35,178 @@ struct PixelUpdate {
|
|||||||
color: u32,
|
color: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AppState {
|
async fn on_connect(
|
||||||
canvas: Mutex<Vec<Vec<u32>>>,
|
socket: SocketRef,
|
||||||
last_update: Mutex<HashMap<String, DateTime<Utc>>>,
|
canvas: Canvas,
|
||||||
soldiers: Mutex<HashSet<String>>,
|
last_update: LastUpdate,
|
||||||
}
|
soldiers: Soldiers,
|
||||||
|
) {
|
||||||
async fn on_connect(socket: SocketRef, state: Arc<AppState>) {
|
|
||||||
info!("Socket connected: {:?} {:?}", socket.ns(), socket.id,);
|
info!("Socket connected: {:?} {:?}", socket.ns(), socket.id,);
|
||||||
|
|
||||||
let canvas_state = state.canvas.lock().unwrap();
|
|
||||||
let serialized_canvas = serde_json::to_string(&*canvas_state).unwrap();
|
|
||||||
socket.emit("init-canvas", &serialized_canvas).ok();
|
|
||||||
let socket_id = socket.id.to_string();
|
let socket_id = socket.id.to_string();
|
||||||
|
|
||||||
let mut soldiers = state.soldiers.lock().unwrap();
|
{
|
||||||
soldiers.insert(socket_id.clone());
|
let mut soldiers = soldiers.lock().unwrap();
|
||||||
let soldiers_num = soldiers.len();
|
soldiers.insert(socket_id.clone());
|
||||||
socket.emit("current_soldiers", &soldiers_num).ok();
|
let soldiers_num = soldiers.len();
|
||||||
socket
|
|
||||||
.broadcast()
|
|
||||||
.emit("current_soldiers", &soldiers_num)
|
|
||||||
.ok();
|
|
||||||
|
|
||||||
let app_state = state.clone();
|
socket.emit("current_soldiers", &soldiers_num).ok();
|
||||||
let app_state_for_disconnect = state.clone();
|
socket
|
||||||
|
.broadcast()
|
||||||
|
.emit("current_soldiers", &soldiers_num)
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
info!("Memory usage after connection and before cloning state: ");
|
||||||
|
print_memory_usage();
|
||||||
|
|
||||||
|
let canvas_clone = canvas.clone();
|
||||||
|
let last_update_clone = last_update.clone();
|
||||||
|
|
||||||
|
info!("Memory usage after connection and after cloning state: ");
|
||||||
|
print_memory_usage();
|
||||||
|
|
||||||
socket.on(
|
socket.on(
|
||||||
"place-pixel",
|
"place-pixel",
|
||||||
move |socket: SocketRef, Data::<PixelUpdate>(update), Bin(_bin)| {
|
move |socket: SocketRef, Data::<PixelUpdate>(update), Bin(_bin)| {
|
||||||
let now = Utc::now();
|
let socket_id = socket.id.to_string();
|
||||||
let mut last_update = app_state.last_update.lock().unwrap();
|
let last_update = last_update_clone.clone();
|
||||||
|
let canvas = canvas_clone.clone();
|
||||||
|
|
||||||
if let Some(&last_time) = last_update.get(&socket_id) {
|
{
|
||||||
if now < last_time + Duration::minutes(1) {
|
let now = Utc::now();
|
||||||
let _ = socket.emit(
|
let mut last_update = last_update.lock().unwrap();
|
||||||
"error",
|
|
||||||
Value::String("You can only place one pixel per minute".to_string()),
|
if let Some(&last_time) = last_update.get(&socket_id) {
|
||||||
);
|
if now < last_time + Duration::seconds(10) {
|
||||||
return;
|
let _ = socket.emit(
|
||||||
|
"error",
|
||||||
|
Value::String("You can only place one pixel per minute".to_string()),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
last_update.insert(socket_id.clone(), now);
|
||||||
}
|
}
|
||||||
|
|
||||||
last_update.insert(socket_id.clone(), now);
|
|
||||||
|
|
||||||
info!("Received pixel update: {:?}", update);
|
info!("Received pixel update: {:?}", update);
|
||||||
let mut canvas = app_state.canvas.lock().unwrap();
|
let mut canvas = canvas.lock().unwrap();
|
||||||
canvas[update.y as usize][update.x as usize] = update.color;
|
canvas[update.y as usize * 500 + update.x as usize] = update.color;
|
||||||
|
|
||||||
info!("Emitting pixel update");
|
info!("Emitting pixel update");
|
||||||
socket.emit("pixel-updated", &update).ok(); // Send to the user who placed the pixel
|
socket.emit("pixel-updated", &update).ok(); // Send to the user who placed the pixel
|
||||||
socket.broadcast().emit("pixel-updated", &update).ok(); // Send to all other users
|
socket.broadcast().emit("pixel-updated", &update).ok(); // Send to all other users
|
||||||
|
|
||||||
|
info!("Memory usage after pixel update: ");
|
||||||
|
print_memory_usage();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
socket.on_disconnect(move |socket: SocketRef| {
|
socket.on_disconnect(move |socket: SocketRef| {
|
||||||
info!("Socket disconnected: {:?}", socket.id);
|
info!("Socket disconnected: {:?}", socket.id);
|
||||||
let mut soldiers = app_state_for_disconnect.soldiers.lock().unwrap();
|
info!("Memory usage after disconnection: ");
|
||||||
soldiers.remove(&socket.id.to_string());
|
print_memory_usage();
|
||||||
|
|
||||||
info!("Soldiers: {:?}", soldiers.len());
|
|
||||||
|
|
||||||
let mut last_update = app_state_for_disconnect.last_update.lock().unwrap();
|
|
||||||
let socket_id = socket.id.to_string();
|
let socket_id = socket.id.to_string();
|
||||||
last_update.remove(&socket_id);
|
|
||||||
|
|
||||||
info!("Last update: {:?}", last_update.len());
|
{
|
||||||
|
let mut soldiers = soldiers.lock().unwrap();
|
||||||
|
soldiers.remove(&socket_id.to_string());
|
||||||
|
info!("Soldiers: {:?}", soldiers.len());
|
||||||
|
|
||||||
let soldiers_num = soldiers.len();
|
let soldiers_num = soldiers.len();
|
||||||
socket
|
socket
|
||||||
.broadcast()
|
.broadcast()
|
||||||
.emit("current_soldiers", &soldiers_num)
|
.emit("current_soldiers", &soldiers_num)
|
||||||
.ok();
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut last_update = last_update.lock().unwrap();
|
||||||
|
last_update.remove(&socket_id);
|
||||||
|
|
||||||
|
info!("Last update: {:?}", last_update.len());
|
||||||
|
}
|
||||||
|
|
||||||
|
info!("Memory usage after disconnection and cleanup: ");
|
||||||
|
print_memory_usage();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn print_memory_usage() {
|
||||||
|
if let Some(usage) = memory_stats() {
|
||||||
|
info!(
|
||||||
|
"Current physical memory usage: {} MB",
|
||||||
|
usage.physical_mem as f64 / 1024.0 / 1024.0
|
||||||
|
);
|
||||||
|
info!(
|
||||||
|
"Current virtual memory usage: {} MB",
|
||||||
|
usage.virtual_mem as f64 / 1024.0 / 1024.0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_canvas_state(Extension(canvas): Extension<Canvas>) -> Json<Vec<u32>> {
|
||||||
|
let canvas = canvas.lock().unwrap();
|
||||||
|
Json(canvas.clone())
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
dotenv::dotenv().ok();
|
dotenv::dotenv().ok();
|
||||||
tracing::subscriber::set_global_default(FmtSubscriber::new())?;
|
tracing::subscriber::set_global_default(FmtSubscriber::new())?;
|
||||||
|
|
||||||
|
let rate_governor = Arc::new(
|
||||||
|
GovernorConfigBuilder::default()
|
||||||
|
.burst_size(6)
|
||||||
|
.per_second(10)
|
||||||
|
.finish()
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let governor = rate_governor.limiter().clone();
|
||||||
|
let interval = std::time::Duration::from_secs(1);
|
||||||
|
|
||||||
|
tokio::spawn(async move {
|
||||||
|
loop {
|
||||||
|
tokio::time::sleep(interval).await;
|
||||||
|
governor.retain_recent();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let (layer, io) = SocketIo::new_layer();
|
let (layer, io) = SocketIo::new_layer();
|
||||||
|
|
||||||
let app_state = Arc::new(AppState {
|
let canvas = Arc::new(Mutex::new(vec![0xFFFFFFFF; 500 * 500]));
|
||||||
canvas: Mutex::new(vec![vec![0xFFFFFFFF; 500]; 500]),
|
let last_update = Arc::new(Mutex::new(HashMap::new()));
|
||||||
last_update: Mutex::new(HashMap::new()),
|
let soldiers = Arc::new(Mutex::new(HashSet::new()));
|
||||||
soldiers: Mutex::new(HashSet::new()),
|
|
||||||
});
|
|
||||||
|
|
||||||
let app_state_for_ns = app_state.clone();
|
let used_memory = std::mem::size_of_val(&*canvas)
|
||||||
|
+ std::mem::size_of_val(&*last_update)
|
||||||
|
+ std::mem::size_of_val(&*soldiers);
|
||||||
|
info!(
|
||||||
|
"Used memory of state: {} bytes, {} KB, {} MB",
|
||||||
|
used_memory,
|
||||||
|
used_memory / 1024,
|
||||||
|
used_memory / 1024 / 1024
|
||||||
|
);
|
||||||
|
|
||||||
|
info!("Memory usage after state setup and before socket.io setup: ");
|
||||||
|
print_memory_usage();
|
||||||
|
|
||||||
|
let canvas_for_socket = canvas.clone();
|
||||||
|
|
||||||
io.ns("/", move |socket: SocketRef| {
|
io.ns("/", move |socket: SocketRef| {
|
||||||
tokio::spawn(on_connect(socket, app_state_for_ns.clone()));
|
tokio::spawn(on_connect(
|
||||||
|
socket,
|
||||||
|
canvas_for_socket.clone(),
|
||||||
|
last_update.clone(),
|
||||||
|
soldiers.clone(),
|
||||||
|
));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
info!("Memory usage after socket.io setup: ");
|
||||||
|
print_memory_usage();
|
||||||
|
|
||||||
let address = std::env::var("ADDRESS").unwrap_or_else(|_| "0.0.0.0".to_string());
|
let address = std::env::var("ADDRESS").unwrap_or_else(|_| "0.0.0.0".to_string());
|
||||||
let port: u16 = std::env::var("PORT")
|
let port: u16 = std::env::var("PORT")
|
||||||
.unwrap_or_else(|_| "3000".to_string())
|
.unwrap_or_else(|_| "3000".to_string())
|
||||||
@@ -137,8 +226,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let app = Router::new()
|
let app = Router::new()
|
||||||
.fallback_service(ServeDir::new("dist"))
|
.route("/canvas/", get(get_canvas_state))
|
||||||
.layer(layer);
|
.route("/check/", get(|| async { "OK" }))
|
||||||
|
.fallback_service(ServeDir::new("dist/"))
|
||||||
|
.layer(GovernorLayer {
|
||||||
|
config: rate_governor,
|
||||||
|
})
|
||||||
|
.layer(layer)
|
||||||
|
.layer(Extension(canvas.clone()));
|
||||||
|
|
||||||
let app = if let Some(cors) = cors {
|
let app = if let Some(cors) = cors {
|
||||||
app.layer(cors)
|
app.layer(cors)
|
||||||
@@ -149,7 +244,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
let server_address = format!("{}:{}", address, port);
|
let server_address = format!("{}:{}", address, port);
|
||||||
info!("Starting server on {}", server_address);
|
info!("Starting server on {}", server_address);
|
||||||
let listener = tokio::net::TcpListener::bind(server_address).await?;
|
let listener = tokio::net::TcpListener::bind(server_address).await?;
|
||||||
axum::serve(listener, app.into_make_service()).await?;
|
axum::serve(
|
||||||
|
listener,
|
||||||
|
app.into_make_service_with_connect_info::<SocketAddr>(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user