Files
paste/.llm/analysis.md
Aleksander Cynarski c9132e836a
Some checks failed
Build CI / pre-build-checks (push) Failing after 16s
Build CI / build (amd64) (push) Has been skipped
Build CI / build (arm64) (push) Has been skipped
feat: markdown rendering /m/<id>
2026-04-21 16:24:08 +02:00

8.3 KiB
Raw Permalink Blame History

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 /<id>  surowe pobranie pasty
│   │   ├── pretty_retrieve.rs   # GET /p/<id>  wyświetlanie z podświetlaniem
│   │   └── static_files.rs      # GET /static/<file>  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/<file> Zasoby statyczne (CSS, JS, czcionki)
POST / Upload pliku binarnego → zwraca ID
POST /submit Formularz tekstowy → redirect do /p/<id>.<ext>
GET /<id> Surowa treść pasty
GET /<id>.<ext> Surowa treść z rozszerzeniem (rank=1)
GET /p/<id> Pasta z podświetlaniem składni (HTML)
GET /p/<id>.<ext> 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

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

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

enum ResponseWrapper<R> {
    MetaInterfaceResponse(R),
    PrettyPasteContentResponse(R, SystemTime),
    RawPasteContentResponse(R, SystemTime),
    Redirect(Box<Redirect>),
    NotFound(String),
    ServerError(String),
}

Centralnie zarządza nagłówkami HTTP:

  • Server: bin v.<VERSION> (<GIT_HASH>)
  • 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_)

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 ParamsPasteId i PasteIdSyntax implementują trait FromParam — Rocket automatycznie waliduje parametry URL.

  4. Lazy StaticBINARY_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/<id>/<id>
  • 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/<id> (kolorowanie)
4. Inaczej → /<id> (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