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

269 lines
8.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
```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<R>
```rust
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_`)
```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/<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
```