photoprism/internal/server
Michael Mayer 50976f427e Auth: Add RP-initiated OIDC logout via PHOTOPRISM_OIDC_LOGOUT #5684 #5433
Sign-out of an OIDC session redirects the browser to the provider's
discovered end_session_endpoint (id_token_hint + absolute
post_logout_redirect_uri) when PHOTOPRISM_OIDC_LOGOUT is enabled, so the
provider SSO session ends and the next login re-prompts. Opt-in (default
off); local/LDAP logout and providers without an end-session endpoint fall
back to local logout.

Adds the shared CE /api/v1/oauth/logout route and OAuthLogoutHandler hook
plus the Portal OP end_session_endpoint advertised in the Portal discovery
document, for Portal builds to serve via the override hook.
2026-06-24 17:21:00 +02:00
..
limiter Links: Use canonical trailing-slash form for website URLs 2026-06-24 17:20:30 +02:00
process Links: Use canonical trailing-slash form for website URLs 2026-06-24 17:20:30 +02:00
wellknown Auth: Add RP-initiated OIDC logout via PHOTOPRISM_OIDC_LOGOUT #5684 #5433 2026-06-24 17:21:00 +02:00
api.go WebDAV: Improve redirect and read/write request method handling 2026-02-10 11:45:32 +01:00
api_docs.go Backend: Remove legacy Go build tags #5330 2025-11-22 09:24:28 +01:00
autotls.go HTTP: Refactor Unix socket support #2337 #3595 2023-08-14 10:43:05 +02:00
compress.go Server: Compact verbose comments in compress and static helpers 2026-05-15 17:50:08 +00:00
compress_negotiate.go Backend: Use strings.SplitSeq for split-and-iterate loops #5599 2026-05-30 09:49:47 +00:00
compress_negotiate_test.go Server: Add zstd compression support #5550 2026-05-03 10:10:33 +00:00
compress_predicate.go Server: Serve precompressed static asset siblings #5552 2026-05-03 13:43:59 +00:00
compress_predicate_test.go Server: Serve precompressed static asset siblings #5552 2026-05-03 13:43:59 +00:00
extensions.go Config: Show error if originals and storage path seem identical #1642 2024-01-21 14:22:16 +01:00
fail.go Go: Apply go fix modernizations across backend packages 2026-02-20 03:54:33 +01:00
gzip_test.go Server: Add zstd compression support #5550 2026-05-03 10:10:33 +00:00
logger.go Security: Add http rate limiter and auto tls mode #98 2022-10-11 22:44:11 +02:00
README.md Docs: Drop private subrepo references from public files 2026-05-05 09:40:18 +00:00
recovery.go CI: Apply Go linter recommendations to "internal/server" package #5330 2025-11-22 13:09:32 +01:00
routes.go Auth: Add RP-initiated OIDC logout via PHOTOPRISM_OIDC_LOGOUT #5684 #5433 2026-06-24 17:21:00 +02:00
routes_sharing.go API: Add missing Swagger annotations and update swagger.json 2025-10-30 11:00:16 +01:00
routes_static.go Server: Serve precompressed static asset siblings #5552 2026-05-03 13:43:59 +00:00
routes_test.go PWA: Use scope-relative manifest URLs for iOS path-based installs 2026-03-01 23:33:44 +01:00
routes_webapp.go PWA: Use scope-relative manifest URLs for iOS path-based installs 2026-03-01 23:33:44 +01:00
routes_webdav.go Backend: Refactor middleware naming and improve code comments #5235 2025-09-30 23:25:53 +02:00
routes_wellknown.go Cluster: Add Portal OIDC discovery doc at /.well-known/openid-configuration 2026-05-24 06:43:11 +00:00
security.go WebDAV: Harden response headers for interoperability #5472 2026-03-04 15:23:10 +01:00
security_test.go WebDAV: Harden response headers for interoperability #5472 2026-03-04 15:23:10 +01:00
server.go Links: Use canonical trailing-slash form for website URLs 2026-06-24 17:20:30 +02:00
server_test.go WebDAV: Improve redirect and read/write request method handling 2026-02-10 11:45:32 +01:00
start.go Server: Add zstd compression support #5550 2026-05-03 10:10:33 +00:00
start_test.go Server: Use canonical host for AutoTLS HTTP redirects 2026-03-07 14:31:03 +01:00
static.go WebDAV: Improve redirect and read/write request method handling 2026-02-10 11:45:32 +01:00
static_precompressed.go Backend: Compact code comments and drop duplicate package headers 2026-05-25 11:47:44 +00:00
static_precompressed_test.go Server: Serve precompressed static asset siblings #5552 2026-05-03 13:43:59 +00:00
sw_fallback.go Config: Add StaticBuildFile() and StaticImgFile() functions #5274 2025-10-18 09:09:56 +02:00
sw_fallback.js Cleanup: Use US English spelling in code comments 2026-05-17 13:46:24 +00:00
sw_scope_cleanup_fallback.go Frontend: Namespace local storage to run multiple nodes on a domain #98 2026-02-08 18:35:05 +01:00
sw_scope_cleanup_fallback.js Frontend: Namespace local storage to run multiple nodes on a domain #98 2026-02-08 18:35:05 +01:00
webdav.go WebDAV: Limit PUT upload size to the configured originals limit 2026-06-10 20:40:28 +00:00
webdav_actions_test.go CI: Apply Go linter recommendations to "internal/server" package #5330 2025-11-22 13:09:32 +01:00
webdav_auth.go Auth: Revoke derived sessions & gate app passwords by login state #5647 2026-06-15 23:41:01 +00:00
webdav_auth_session.go Logs: Add package pkg/log/status to provide generic outcome constants 2025-10-21 14:42:05 +02:00
webdav_auth_test.go Auth: Gate app passwords behind a settings feature flag #5647 2026-06-09 17:36:24 +00:00
webdav_path.go WebDAV: Harden response headers for interoperability #5472 2026-03-04 15:23:10 +01:00
webdav_path_test.go WebDAV: Harden response headers for interoperability #5472 2026-03-04 15:23:10 +01:00
webdav_propfind_test.go WebDAV: Harden response headers for interoperability #5472 2026-03-04 15:23:10 +01:00
webdav_response.go Server: Export WebDAV response helper for PROPFIND content type #5472 2026-03-04 16:03:33 +01:00
webdav_secure_test.go WebDAV: Harden joinUnderBase against drive-letter and backslash paths 2026-06-10 17:44:13 +00:00
webdav_write_test.go WebDAV: Limit PUT upload size to the configured originals limit 2026-06-10 20:40:28 +00:00
zstd_test.go Server: Serve precompressed static asset siblings #5552 2026-05-03 13:43:59 +00:00

PhotoPrism — HTTP Server

Last Updated: May 3, 2026

Overview

internal/server wires Gin, middleware, and configuration into the PhotoPrism HTTP/HTTPS/WebDAV servers. It owns startup/shutdown orchestration, route registration, and helpers for recovery/logging. Subpackages (process, limits, etc.) are kept lightweight so CLI commands and workers can embed the same server behavior without duplicating boilerplate.

Constraints

  • Uses the configured config.Config to decide TLS, AutoTLS, Unix sockets, proxies, compression, and trusted headers.
  • Middleware must stay small and deterministic because it runs on every request; heavy logic belongs in handlers.
  • Panics are recovered by Recovery() which logs stack traces and returns 500.
  • Startup supports mutually exclusive endpoints: Unix socket, HTTPS with certs, AutoTLS (with redirect listener), or plain HTTP.

Goals

  • Provide a single entrypoint (Start) that configures listeners, middleware, and routes consistently.
  • Keep health/readiness endpoints lightweight and cache-safe.
  • Ensure redirect and TLS listeners include sensible header and idle limits.

Non-Goals

  • Managing Docker/Traefik lifecycle (handled by compose files).
  • Serving static files directly; templates are loaded via Gin and routed by routes_webapp.go.

Package Layout (Code Map)

  • start.go — main startup flow, listener selection (HTTP/HTTPS/AutoTLS/Unix socket), graceful shutdown.
  • routes_webapp.go — Web UI routes and shared method helpers (MethodsGetHead).
  • static_precompressed.goPrecompressedStatic handler that serves bundled /static/* assets from precompressed siblings emitted by frontend/scripts/precompress.js; the same handler accepts operator-supplied siblings for /c/static/* and falls back to identity when none exist. Range requests always serve identity, and http.ServeContent continues to handle Last-Modified + If-Modified-Since revalidation for both encoded and identity responses (the handler does not set an ETag, so If-None-Match is latent rather than active).
  • recovery.go — panic recovery middleware with stack trace logging.
  • logger.go — request logging middleware (enabled in debug mode).
  • security.go — security headers and trusted proxy/platform handling.
  • webdav_*.go & tests — WebDAV handlers and regression tests for overwrite, traversal, and metadata flags.
  • webdav_path.go — shared helper to classify built-in and path-proxied WebDAV routes.
  • process/ — light wrappers for server process metadata.
  • internal/api — registers REST endpoints consumed by registerRoutes.
  • internal/config — supplies HTTP/TLS/socket settings, compression, proxies, and base URI paths.
  • internal/server/process — exposes process ID for logging.
  • pkg/http/header — shared HTTP header constants used by health endpoints.

Configuration & Safety Notes

  • Compression: configured via PHOTOPRISM_HTTP_COMPRESSION / --http-compression as a comma-separated preference list. Supported tokens are zstd, gzip, and none (empty value also disables compression). The default ships as zstd,gzip so capable clients receive zstd while everyone else falls back to gzip; unknown tokens are ignored with a startup warning.
  • Bundled frontend assets under /static/* are served with precompressed .zst / .gz siblings produced at build time by frontend/scripts/precompress.js (the npm postbuild hook for make build-js), selected via PrecompressedStatic in static_precompressed.go. Custom static assets under /c/static/* go through the same handler so extensions and operators may ship precompressed siblings alongside their files; without siblings the route serves identity. The runtime middleware bypasses both routes so it never re-encodes an already-encoded body and so PHOTOPRISM_HTTP_COMPRESSION=none consistently disables every encoded code path on these routes.
  • Trusted proxies/platform headers are read from config; keep the list tight.
  • If no trusted proxy ranges are configured (or the configured ranges are invalid), proxy trust is disabled and client IP resolution falls back to the TCP peer address.
  • HTTP hardening defaults:
    • ReadHeaderTimeout is configured via PHOTOPRISM_HTTP_HEADER_TIMEOUT / --http-header-timeout (default 15s).
    • MaxHeaderBytes is configured via PHOTOPRISM_HTTP_HEADER_BYTES / --http-header-bytes (default 1 MiB).
    • IdleTimeout is configured via PHOTOPRISM_HTTP_IDLE_TIMEOUT / --http-idle-timeout (default 180s).
    • Global ReadTimeout / WriteTimeout remain disabled to avoid breaking large transfers.
  • WebDAV response behavior:
    • Built-in security middleware skips browser-document headers (Content-Security-Policy, X-Frame-Options) on /originals and /import paths.
    • PROPFIND 207 Multi-Status responses normalize XML media type to application/xml; charset=utf-8.
  • AutoTLS: uses autocert and spins up a redirect listener; ensure ports 80/443 are reachable.
  • Unix sockets: optional force query removes stale sockets; permissions can be set via mode query.
  • Health endpoints (/livez, /health, /healthz, /readyz) return Cache-Control: no-store and Access-Control-Allow-Origin: *.

Testing

  • Lint & unit tests: golangci-lint run ./internal/server... and go test ./internal/server/...
  • WebDAV behaviors are covered by webdav_*_test.go; they rely on temp directories and in-memory routers, including PROPFIND 207 XML/header assertions and path classification checks.

Operational Tips

  • Prefer Start with context cancellation so graceful shutdown is triggered (server.Close()).
  • When adding routes, register them in registerRoutes and reuse MethodsGetHead for safe verbs.
  • Keep middleware light; log or enforce security at the edge (Traefik) when possible, but maintain server-side defaults for defense in depth.