mirror of
https://github.com/LLukas22/Jellyswarrm.git
synced 2026-06-14 10:35:43 -04:00
5.5 KiB
5.5 KiB
Request and Response Processing
Jellyswarrm is a Jellyfin-aware reverse proxy. Clients see Jellyswarrm user IDs, media IDs, server IDs, and API keys. Upstream Jellyfin servers receive their original IDs and credentials.
The code keeps three concerns separate:
- Request preprocessing chooses the upstream server/session and rewrites the outgoing URL/auth.
- Request and response JSON processing rewrites IDs inside bodies.
- URL processing rewrites IDs and credentials in request URLs and embedded media delivery URLs.
Handlers should use the extractors module, ProxyProcessors, and AppState::process_response_json instead of calling low-level processors directly.
Request Flow
flowchart TD
A[Incoming Axum request] --> B{Route handler type}
B -->|Routed handler| C[Preprocessed / RequireUser / RequireSession / RequireUserSession]
B -->|Catch-all proxy_handler| D[Static asset check]
D -->|Asset found| E[Return asset]
D -->|No asset| F[preprocess_request]
C --> F
F --> G[axum_to_reqwest]
G --> H[extract_request_infos]
H --> I[Parse auth headers/query]
H --> J[Resolve user and device]
H --> K{JSON request body?}
K -->|yes| L[RequestAnalyzer]
L --> M[Find media/user/session hints]
K -->|no| N[No body hints]
M --> O[Load user sessions]
N --> O
J --> O
O --> P[resolve_server]
P --> Q[UrlProcessor.server_from_client_url]
Q --> R[Pick upstream server/session]
R --> S[remap_authorization]
S --> T[apply_to_request]
T --> U[Remove hop-by-hop headers]
T --> V[Set Host/Auth headers]
T --> W[UrlProcessor.client_to_server_url]
W --> X[Virtual IDs/API key -> upstream IDs/token in path/query]
X --> Y{Forwarded body is JSON?}
Y -->|yes| Z[ProxyProcessors.process_request_body]
Z --> AA[RequestProcessor rewrites JSON virtual IDs -> upstream IDs]
AA --> AB[set_json_body if modified]
Y -->|no| AC[Forward request]
AB --> AC
Response Flow
flowchart TD
A[Upstream response] --> B{Handler path}
B -->|Item/media JSON handlers| C[Deserialize as serde_json::Value]
B -->|Fallback JSON response| D[Deserialize as serde_json::Value]
B -->|Typed special handlers| E[Deserialize typed model]
B -->|Non-JSON response| F[Pass through]
E --> G[Run typed behavior]
G --> H[Example: playback session tracking]
G --> I[Serialize typed response to JSON if rewriting is needed]
C --> J[process_response_json profile: Media]
D --> K[process_response_json profile: BestEffortMedia]
I --> J
J --> L[ResponseProcessor]
K --> L
L --> M[Rewrite upstream media IDs -> virtual IDs]
L --> N[Rewrite ServerId -> proxy server id]
L --> O[Disable CanDelete/CanDownload]
L --> P[Optionally suffix names with server name]
L --> Q[DeliveryUrl/StreamUrl/TranscodingUrl]
Q --> R[UrlProcessor.server_to_client_delivery_url]
R --> S[Rewrite embedded path/query IDs and api_key]
S --> T[Processed JSON]
M --> T
N --> T
O --> T
P --> T
T --> U{Typed handler?}
U -->|yes| V[Deserialize JSON back to typed model]
U -->|no| W[Serialize JSON body]
V --> X[Return response]
W --> Y[Update Content-Length]
Y --> X
F --> X
Response Profiles
Media: full media response rewriting for explicitly routed media/item/playback/federated handlers.BestEffortMedia: full media-like rewriting for catch-all JSON responses. This keeps less common Jellyfin endpoints working even when they are not explicitly routed.Disabled: no response rewriting.
Media and BestEffortMedia currently rewrite the same fields. The main difference is how they are selected: explicit handlers use Media; the generic fallback uses BestEffortMedia. Name suffixing is still controlled separately by should_change_name and config.
Component Boundaries
extractors.rs: Axum extractors that run preprocessing and optionally require a resolved user, session, or both.request_preprocessing.rs: request identity extraction, session lookup, server selection, auth remapping, and outgoing URL/header rewriting.processors/url_processor.rs: all path/query URL rewriting for client-to-server request URLs, server-to-client delivery URLs, and request server detection.processors/request_analyzer.rs: scans incoming JSON bodies for media IDs, user IDs, and session IDs that help pick the upstream server/session.processors/request_processor.rs: rewrites JSON request body IDs from Jellyswarrm virtual IDs to upstream Jellyfin IDs.processors/response_processor.rs: rewrites JSON response fields from upstream Jellyfin IDs to Jellyswarrm virtual IDs and delegates embedded URL rewriting toUrlProcessor.processors/json_processor.rs: generic recursive JSON walker used by analyzers and processors.processors/field_matcher.rs: centralized field-name groups for JSON rewrite rules.ProxyProcessors: facade that constructs and coordinates request, response, analyzer, and URL processors.
Design Rules
- Prefer
serde_json::Valuefor pass-through media/item responses so unknown Jellyfin schema changes are preserved. - Keep typed models where the proxy performs behavior beyond simple transformation, such as playback session tracking and federated item interleaving.
- Keep URL rewriting centralized in
UrlProcessor; request URL rules and embedded delivery URL rules should not drift. - Keep handler signatures expressive: use
Preprocessed,RequireUser,RequireSession, orRequireUserSessioninstead of manually callingpreprocess_requestin routed handlers.