# Analiza repozytorium: bin (Pastebin) > Data analizy: 2026-04-21 --- ## 1. Cel projektu **Bin** to minimalistyczny, samodzielny serwis pastebin akceptujący zarówno tekst, jak i pliki binarne (obrazy, PDF-y itp.). Filozofia projektu opiera się na prostocie, łatwości wdrożenia i minimalizmie. W odróżnieniu od tradycyjnych pastebinów **nie wymaga bazy danych** — wszystkie pasty przechowywane są w płaskim systemie plików. Projekt zawiera klienty: interfejs webowy, CLI i integrację z Vimem. **Live demo:** https://basedbin.fly.dev **Docker:** `wantguns/bin` (multi-arch: amd64 + arm64) --- ## 2. Stack technologiczny | Warstwa | Technologia | |---------|-------------| | Język | Rust (Edition 2021) | | Framework web | Rocket 0.5.0-rc.1 (async) | | Szablony HTML | Tera (via rocket_dyn_templates) | | Kolorowanie składni | Syntect 4.6.0 + motyw Ayu Dark | | Frontend | Vanilla JavaScript, HTML, CSS (brak frameworków) | | Detekcja MIME | tree_magic 0.2.3 | | CLI args | clap 3.0.9 | | Kryptografia | sha256 (ETag) | | Obsadzanie zasobów | rust-embed 6.3.0 | | Konteneryzacja | Docker (obraz scratch) | | Deployment | Fly.io | --- ## 3. Struktura katalogów ``` bin/ ├── src/ # Kod źródłowy Rust │ ├── main.rs # Punkt wejścia, setup serwera, parsowanie CLI │ ├── routes/ # Handlery endpointów HTTP │ │ ├── mod.rs │ │ ├── index.rs # GET / – strona główna │ │ ├── upload.rs # POST / – upload pliku binarnego │ │ ├── submit.rs # POST /submit – formularz tekstowy │ │ ├── retrieve.rs # GET / – surowe pobranie pasty │ │ ├── pretty_retrieve.rs # GET /p/ – wyświetlanie z podświetlaniem │ │ └── static_files.rs # GET /static/ – zasoby statyczne │ └── models/ │ ├── mod.rs │ ├── paste_id.rs # Generowanie i walidacja ID pasty │ ├── pretty_syntax.rs # Parsowanie rozszerzenia z URL │ ├── pretty.rs # Logika podświetlania składni │ └── response_wrapper.rs # Abstrakcja odpowiedzi HTTP │ ├── templates/ # Szablony Tera │ ├── base.html.tera │ ├── index.html.tera │ └── pretty.html.tera │ ├── static/ # Zasoby osadzone w binarce │ ├── css/ │ ├── js/ │ ├── fonts/ # Iosevka (ttf + woff2) │ └── media/ # Favicony │ ├── resources/ # Zasoby binarne (syntaksy, motyw) ├── contrib/cli/client # Skrypt bash CLI ├── Cargo.toml # Manifest projektu ├── build.rs # Wstrzykiwanie git hash do binarki ├── Dockerfile # Wielostopniowy build ├── docker-compose.yml └── fly.toml # Konfiguracja Fly.io ``` --- ## 4. Endpointy API | Metoda | Ścieżka | Opis | |--------|---------|------| | GET | `/` | Strona główna z formularzem | | GET | `/static/` | Zasoby statyczne (CSS, JS, czcionki) | | POST | `/` | Upload pliku binarnego → zwraca ID | | POST | `/submit` | Formularz tekstowy → redirect do `/p/.` | | GET | `/` | Surowa treść pasty | | GET | `/.` | Surowa treść z rozszerzeniem (rank=1) | | GET | `/p/` | Pasta z podświetlaniem składni (HTML) | | GET | `/p/.` | Pasta z wymuszonym językiem (rank=1) | **Priorytet routingu:** trasy z rozszerzeniem (`rank=1`) są dopasowywane przed trasami generycznymi (`rank=2`). --- ## 5. Modele danych ### PasteId ```rust pub struct PasteId<'a>(Cow<'a, str>) ``` - Generuje losowe 6-znakowe ID alfanumeryczne (36^6 ≈ 2,1 mld kombinacji) - Implementuje `FromParam` dla automatycznej walidacji URL w Rocket ### PasteIdSyntax ```rust pub struct PasteIdSyntax<'a> { syn_id: Cow<'a, str> } ``` - Parsuje URL typu `/p/abc123.cpp` na nazwę pliku i rozszerzenie - `get_fname()` → `"abc123"`, `get_ext()` → `"cpp"` ### ResponseWrapper ```rust enum ResponseWrapper { MetaInterfaceResponse(R), PrettyPasteContentResponse(R, SystemTime), RawPasteContentResponse(R, SystemTime), Redirect(Box), NotFound(String), ServerError(String), } ``` Centralnie zarządza nagłówkami HTTP: - `Server: bin v. ()` - `ETag`, `Last-Modified`, `Cache-Control` --- ## 6. Zależności (Cargo.toml) | Crate | Wersja | Zastosowanie | |-------|--------|--------------| | `rand` | 0.8.4 | Generowanie ID | | `rocket` | 0.5.0-rc.1 | Framework web | | `tree_magic` | 0.2.3 | Detekcja MIME | | `syntect` | 4.6.0 | Podświetlanie składni | | `rust-embed` | 6.3.0 | Osadzanie zasobów | | `clap` | 3.0.9 | Parsowanie CLI | | `once_cell` | 1 | Lazy static | | `sha256` | 1 | ETag | | `time` | 0.3 | Formatowanie czasu | | `rocket_dyn_templates` | 0.1.0-rc.1 | Szablony Tera | --- ## 7. System budowania ### build.rs Przechwytuje hash commita git i wstrzykuje go jako stałą czasu kompilacji (`GIT_HASH`). ### .cargo/config.toml - Kompilacja statyczna: `-C target-feature=+crt-static` - Domyślny target: `x86_64-unknown-linux-gnu` - Cross-kompilacja ARM64: `aarch64-linux-gnu-gcc` ### Docker (wielostopniowy) 1. **Builder:** obraz Rust → `cargo build --release` 2. **Runner:** obraz `scratch` (pusty) + tylko binarka 3. Rezultat: minimalistyczny obraz (~20-30 MB) --- ## 8. Konfiguracja serwera ### Argumenty CLI | Flag | Domyślnie | Opis | |------|-----------|------| | `-a` | `127.0.0.1` | Adres nasłuchu | | `-p` | `6162` | Port | | `-u` | `./upload` | Katalog przechowywania plików | | `-b` | `100 MiB` | Limit rozmiaru uploadu binarnego | | `-c` | off | Pokaż opis klienta CLI na stronie głównej | ### Zmienne środowiskowe (prefiks `BIN_`) ```bash BIN_PORT=6163 BIN_ADDRESS=0.0.0.0 BIN_LIMITS={form="16 MiB"} BIN_WORKERS=8 BIN_IDENT=false ``` --- ## 9. Architektura i wzorce projektowe 1. **Embedded Resources** — wszystkie zasoby (CSS, JS, czcionki, definicje syntaksy) skompilowane w binarce (`rust-embed`). Zero zależności zewnętrznych. 2. **Response Wrapper** — generyczny wrapper abstrakcji odpowiedzi z centralizowaną logiką nagłówków HTTP. 3. **Type-Safe URL Params** — `PasteId` i `PasteIdSyntax` implementują trait `FromParam` — Rocket automatycznie waliduje parametry URL. 4. **Lazy Static** — `BINARY_ETAG` obliczany raz przy starcie (SHA256 wersji) via `once_cell::sync::Lazy`. 5. **Build-Time Version Injection** — hash git osadzony w czasie kompilacji, widoczny w nagłówku `Server`. 6. **Flat Filesystem Storage** — brak bazy danych; pasty jako pliki w katalogu `./upload`. --- ## 10. Frontend (JavaScript) ### index.js (~150 linii) - Drag-and-drop upload plików - Wklejanie obrazów ze schowka (`paste` event) - Tab jako 4 spacje (nie nawigacja formularza) - Ctrl+Enter → submit - Dynamiczne pokazywanie/ukrywanie UI - Fork przez localStorage ### pretty.js - Przełącznik zawijania: 3 stany (brak → auto → 80 znaków) - Fork: kopiuje treść do localStorage, przekierowuje na główną - Raw: przełącza `/p/` → `/` - New: przejście do strony głównej --- ## 11. Strategia cachowania | Typ odpowiedzi | Cache-Control | |----------------|---------------| | Pasta pretty | `max-age=604800, stale-while-revalidate=86400` | | Pasta raw | `max-age=604800, immutable` | | Meta/Statyczne | ETag (SHA256 wersji) → `304 Not Modified` | --- ## 12. Statystyki kodu | Metryka | Wartość | |---------|---------| | Pliki źródłowe Rust | 13 | | Linie kodu Rust | ~600 | | Szablony HTML | 3 | | Pliki JavaScript | 2 | | Arkusze CSS | 2 | | Obsługiwane języki (syntaksy) | 100+ | | Endpointy API | 7 | | Typy odpowiedzi HTTP | 6 | --- ## 13. Algorytmy kluczowe ### Generowanie ID ``` 1. rand::thread_rng() → thread-safe RNG 2. Alphanumeric distribution (a-z, A-Z, 0-9) 3. Pobierz 6 próbek → String 4. Opakuj w Cow::Owned ``` ### Detekcja MIME (upload binarny) ``` 1. Wczytaj bajty pliku 2. tree_magic::from_filepath() → MIME 3. MIME zawiera "text" → /p/ (kolorowanie) 4. Inaczej → / (surowe pobranie) ``` ### Renderowanie składni ``` 1. Parsuj URL /p/abc123.cpp 2. Wyodrębnij rozszerzenie ("cpp") 3. Znajdź definicję syntaxu w syntect 4. Fallback → plain_text 5. Renderuj HTML z motywem Ayu Dark ```