photoprism/internal/api
2025-12-12 11:31:03 +01:00
..
download Logs: Add package pkg/log/status to provide generic outcome constants 2025-10-21 14:42:05 +02:00
embed
testdata
abort.go Pkg: Move /service/http/... to /http/... and add package /http/dns 2025-10-19 21:08:48 +02:00
albums.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
albums_search.go Logs: Add package pkg/log/status to provide generic outcome constants 2025-10-21 14:42:05 +02:00
albums_search_test.go
albums_test.go API: Update endpoints to return HTTP 201 when a new resource was created 2025-10-20 16:46:59 +02:00
api.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
api_auth.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
api_auth_jwt.go Auth: Remove redundant preview/download token wiring for JWT #5230 2025-10-29 15:21:49 +01:00
api_auth_jwt_test.go Vision: Allow use of configured service key for API authentication #5299 2025-10-30 10:02:16 +01:00
api_auth_test.go Cluster: Rename RoleInstance to RoleApp in service/cluster/roles.go #98 2025-10-31 16:46:42 +01:00
api_client_config.go API: Refactor "GET /api/v1/config" endpoint for JWT sessions #5230 2025-10-29 12:29:12 +01:00
api_client_config_test.go Auth: Adjust JWT default scope and ACL, add tests #5230 2025-10-29 14:28:26 +01:00
api_event.go Logs: Add package pkg/log/status to provide generic outcome constants 2025-10-21 14:42:05 +02:00
api_log.go
api_methods.go API: Improve form and tests for POST /batch/photos/edit endpoint #271 2025-07-08 10:40:45 +02:00
api_request.go Pkg: Move /service/http/... to /http/... and add package /http/dns 2025-10-19 21:08:48 +02:00
api_response.go
api_response_headers.go Pkg: Move /service/http/... to /http/... and add package /http/dns 2025-10-19 21:08:48 +02:00
api_response_test.go Test: Use PascalCase names for all Go subtests in /internal 2025-10-02 14:50:02 +02:00
api_test.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
auth_tokens.go
batch_albums.go Upload: Update album YAML backups when photos have been added 2025-11-20 14:39:06 +01:00
batch_labels.go API: Improve logging of bad request errors across all endpoints #271 2025-07-10 09:38:36 +02:00
batch_photos.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
batch_photos_edit.go API: Improve logging in batch edit request handler #271 2025-11-27 17:54:05 +01:00
batch_photos_edit_test.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
batch_photos_test.go API: Update endpoints to return HTTP 201 when a new resource was created 2025-10-20 16:46:59 +02:00
cache.go Pkg: Move /service/http/... to /http/... and add package /http/dns 2025-10-19 21:08:48 +02:00
cache_test.go Pkg: Move /service/http/... to /http/... and add package /http/dns 2025-10-19 21:08:48 +02:00
cluster_metrics.go AI: Enhance "GET /api/v1/metrics" endpoint with additional stats #213 2025-10-31 15:38:10 +01:00
cluster_metrics_test.go Cluster: Refactor request/response structs and JSON serialization 2025-10-18 17:42:22 +02:00
cluster_nodes.go Cluster: Improve API endpoint and CLI command logs 2025-10-21 16:51:24 +02:00
cluster_nodes_redaction_test.go Cluster: Rename RoleInstance to RoleApp in service/cluster/roles.go #98 2025-10-31 16:46:42 +01:00
cluster_nodes_register.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
cluster_nodes_register_test.go Cluster: Rename RoleInstance to RoleApp in service/cluster/roles.go #98 2025-10-31 16:46:42 +01:00
cluster_nodes_test.go Cluster: Rename RoleInstance to RoleApp in service/cluster/roles.go #98 2025-10-31 16:46:42 +01:00
cluster_nodes_update_siteurl_test.go Cluster: Rename RoleInstance to RoleApp in service/cluster/roles.go #98 2025-10-31 16:46:42 +01:00
cluster_permissions_test.go Pkg: Move /service/http/... to /http/... and add package /http/dns 2025-10-19 21:08:48 +02:00
cluster_summary.go Logs: Add package pkg/log/status to provide generic outcome constants 2025-10-21 14:42:05 +02:00
cluster_theme.go Logs: Replace status string literals with generic constants 2025-10-21 15:08:10 +02:00
cluster_theme_test.go Cluster: Rename RoleInstance to RoleApp in service/cluster/roles.go #98 2025-10-31 16:46:42 +01:00
config_options.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
config_options_test.go
config_settings.go Auth: Extend user accounts with custom scope setting 2025-10-22 19:58:56 +02:00
config_settings_test.go
connect.go Backend: Add security-focused tests, harden WebDAV and use safe.Download 2025-09-22 10:42:53 +02:00
connect_test.go
covers.go Config: Add an option to disable the web user interface #5111 2025-07-14 19:30:24 +02:00
covers_test.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
doc_overrides.go API: Add const, func, and struct comments for easier troubleshooting 2025-09-30 22:02:43 +02:00
docs.go Backend: Remove legacy Go build tags #5330 2025-11-22 09:24:28 +01:00
download.go
download_album.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
download_album_test.go
download_test.go
echo.go PWA: Improve service worker server endpoint #5274 2025-10-18 12:30:38 +02:00
echo_test.go CLI: Added JWT issuance and diagnostics sub commands #5230 2025-09-26 02:38:49 +02:00
errors.go API: Improve Swagger annotations and update swagger.json 2025-10-30 11:50:31 +01:00
errors_test.go
faces.go API: Improve logging of bad request errors across all endpoints #271 2025-07-10 09:38:36 +02:00
faces_search.go API: Improve logging of bad request errors across all endpoints #271 2025-07-10 09:38:36 +02:00
faces_search_test.go
faces_test.go Auth: Refactor cluster configuration and provisioning API endpoints #98 2025-09-24 08:28:38 +02:00
feedback.go API: Improve Swagger annotations and update swagger.json 2025-10-30 11:47:40 +01:00
feedback_test.go
file_delete.go
file_delete_test.go Test: Use PascalCase names for all Go subtests in /internal 2025-10-02 14:50:02 +02:00
file_orientation.go Index: Refactor IndexOptions to determine vision tasks from Config #5167 2025-10-07 16:22:41 +02:00
files.go
files_test.go Test: Use PascalCase names for all Go subtests in /internal 2025-10-02 14:50:02 +02:00
folders_cover.go Config: Add an option to disable the web user interface #5111 2025-07-14 19:30:24 +02:00
folders_cover_test.go Auth: Refactor cluster configuration and provisioning API endpoints #98 2025-09-24 08:28:38 +02:00
folders_search.go Backend: Add security-focused tests, harden WebDAV and use safe.Download 2025-09-22 10:42:53 +02:00
folders_search_test.go Test: Use PascalCase names for all Go subtests in /internal 2025-10-02 14:50:02 +02:00
health.go API: Add cluster operations endpoints to manage and register nodes #98 2025-09-15 06:43:43 +02:00
import.go API: Add missing Swagger annotations and update swagger.json 2025-10-30 11:00:16 +01:00
import_test.go
index.go API: Add missing Swagger annotations and update swagger.json 2025-10-30 11:00:16 +01:00
index_test.go
labels.go API: Update Thumb/ThumbSrc for subjects and labels #4151 2025-10-03 23:17:07 +02:00
labels_search.go AI: Include NSFW flag & score when generating labels with Ollama #5232 2025-10-05 04:23:36 +02:00
labels_search_test.go
labels_test.go Test: Use PascalCase names for all Go subtests in /internal 2025-10-02 14:50:02 +02:00
links.go Backend: Add security-focused tests, harden WebDAV and use safe.Download 2025-09-22 10:42:53 +02:00
links_test.go Test: Use PascalCase names for all Go subtests in /internal 2025-10-02 14:50:02 +02:00
markers.go Batch Edit: Disable API endpoint if feature is disabled #271 2025-11-19 14:31:19 +01:00
markers_test.go API: Update endpoints to return HTTP 201 when a new resource was created 2025-10-20 16:46:59 +02:00
metrics.go Metrics: Use string constants in API endpoint #5355 2025-11-30 10:50:26 +01:00
metrics_test.go Metrics: Add file system and account usage info #5355 2025-11-30 10:43:58 +01:00
moments_time.go
moments_time_test.go Test: Use PascalCase names for all Go subtests in /internal 2025-10-02 14:50:02 +02:00
oauth_authorize.go Pkg: Move /service/http/... to /http/... and add package /http/dns 2025-10-19 21:08:48 +02:00
oauth_authorize_test.go
oauth_revoke.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
oauth_revoke_test.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
oauth_token.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
oauth_token_ratelimit_test.go Pkg: Move /service/http/... to /http/... and add package /http/dns 2025-10-19 21:08:48 +02:00
oauth_token_test.go Pkg: Move /service/http/... to /http/... and add package /http/dns 2025-10-19 21:08:48 +02:00
oauth_userinfo.go API: Add missing Swagger annotations and update swagger.json 2025-10-30 11:00:16 +01:00
oauth_userinfo_test.go
oidc_login.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
oidc_login_test.go
oidc_redirect.go OIDC: Merge groups, add inline code docs, and improve README.md #5334 2025-11-27 12:02:57 +01:00
oidc_redirect_test.go
options.go API: Update swagger endpoint documentation #5133 2025-08-28 11:00:19 +02:00
photo_label.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
photo_label_test.go UX: Add batch edit dialog and API endpoints #271 #5324 2025-11-19 11:20:34 +01:00
photo_unstack.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
photo_unstack_test.go Test: Use PascalCase names for all Go subtests in /internal 2025-10-02 14:50:02 +02:00
photos.go Upload: Update album YAML backups when photos have been added 2025-11-20 14:39:06 +01:00
photos_search.go Logs: Add package pkg/log/status to provide generic outcome constants 2025-10-21 14:42:05 +02:00
photos_search_geo.go Logs: Add package pkg/log/status to provide generic outcome constants 2025-10-21 14:42:05 +02:00
photos_search_geo_test.go
photos_search_test.go Auth: Refactor cluster configuration and provisioning API endpoints #98 2025-09-24 08:28:38 +02:00
photos_test.go Auth: Refactor cluster configuration and provisioning API endpoints #98 2025-09-24 08:28:38 +02:00
places_reverse.go Places: Add config option to specify location details locale #465 #883 2025-07-03 12:58:20 +02:00
places_search.go Places: Add config option to specify location details locale #465 #883 2025-07-03 12:58:20 +02:00
places_test.go Tests: Add unit tests #465 2025-07-09 14:57:32 +02:00
reactions.go Auth: Add "node" and "portal" roles, refactor session entity #98 2025-09-18 13:33:18 +02:00
README.md Cluster: Improve API endpoint and CLI command logs 2025-10-21 16:51:24 +02:00
server.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
services.go API: Update endpoints to return HTTP 201 when a new resource was created 2025-10-20 16:46:59 +02:00
services_search.go API: Improve logging of bad request errors across all endpoints #271 2025-07-10 09:38:36 +02:00
services_search_test.go
services_test.go API: Update endpoints to return HTTP 201 when a new resource was created 2025-10-20 16:46:59 +02:00
services_upload.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
services_upload_test.go Test: Use PascalCase names for all Go subtests in /internal 2025-10-02 14:50:02 +02:00
session.go
session_create.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
session_delete.go Logs: Add package pkg/log/status to provide generic outcome constants 2025-10-21 14:42:05 +02:00
session_get.go Pkg: Move /service/http/... to /http/... and add package /http/dns 2025-10-19 21:08:48 +02:00
session_ratelimit_test.go Backend: Add security-focused tests, harden WebDAV and use safe.Download 2025-09-22 10:42:53 +02:00
session_response.go Auth: Add "node" and "portal" roles, refactor session entity #98 2025-09-18 13:33:18 +02:00
session_test.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
share.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
share_preview.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
share_preview_test.go
share_test.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
status.go API: Update swagger endpoint documentation #5133 2025-08-28 11:20:00 +02:00
status_test.go
subjects.go API: Improve logging of bad request errors across all endpoints #271 2025-07-10 09:38:36 +02:00
subjects_search.go API: Improve logging of bad request errors across all endpoints #271 2025-07-10 09:38:36 +02:00
subjects_search_test.go
subjects_test.go UX: New Action Menu for Faces in People Editing Tab #4151 #797 #5249 2025-10-10 13:02:31 +02:00
svg.go API: Add missing Swagger annotations and update swagger.json 2025-10-30 11:00:16 +01:00
svg_test.go Test: Use PascalCase names for all Go subtests in /internal 2025-10-02 14:50:02 +02:00
swagger.json Server: Upgrade github.com/gin-contrib/gzip from v1.2.3 to v1.2.5 2025-12-12 11:31:03 +01:00
thumbnails.go API: Add missing Swagger endpoint annotations and update swagger.json 2025-09-22 04:12:02 +02:00
thumbnails_test.go
users_avatar.go Logs: Replace status string literals with generic constants 2025-10-21 15:08:10 +02:00
users_avatar_test.go Test: Use PascalCase names for all Go subtests in /internal 2025-10-02 14:50:02 +02:00
users_passcode.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
users_passcode_test.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
users_password.go API: Add missing Swagger endpoint annotations and update swagger.json 2025-09-22 04:12:02 +02:00
users_password_test.go Auth: Refactor cluster configuration and provisioning API endpoints #98 2025-09-24 08:28:38 +02:00
users_sessions.go API: Add missing Swagger endpoint annotations and update swagger.json 2025-09-22 04:12:02 +02:00
users_sessions_test.go
users_update.go API: Add missing Swagger endpoint annotations and update swagger.json 2025-09-22 04:12:02 +02:00
users_update_test.go Auth: Refactor cluster configuration and provisioning API endpoints #98 2025-09-24 08:28:38 +02:00
users_upload.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
users_upload_multipart_test.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
users_upload_test.go Backend: Add security-focused tests, harden WebDAV and use safe.Download 2025-09-22 10:42:53 +02:00
video.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
video_test.go Pkg: Move /service/http/... to /http/... and add package /http/dns 2025-10-19 21:08:48 +02:00
vision_caption.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
vision_face.go Pkg: Move /service/http/... to /http/... and add package /http/dns 2025-10-19 21:08:48 +02:00
vision_face_test.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
vision_labels.go Pkg: Move /service/http/... to /http/... and add package /http/dns 2025-10-19 21:08:48 +02:00
vision_labels_test.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
vision_nsfw.go Pkg: Move /service/http/... to /http/... and add package /http/dns 2025-10-19 21:08:48 +02:00
vision_nsfw_test.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
websocket.go
websocket_create.go API: Add missing Swagger annotations and update swagger.json 2025-10-30 11:00:16 +01:00
websocket_reader.go Auth: Add "node" and "portal" roles, refactor session entity #98 2025-09-18 13:33:18 +02:00
websocket_test.go Auth: Refactor cluster configuration and provisioning API endpoints #98 2025-09-24 08:28:38 +02:00
websocket_topics_test.go Portal: Add cluster admin UI #98 2025-10-16 16:21:56 +02:00
websocket_writer.go Portal: Add cluster admin UI #98 2025-10-16 16:21:56 +02:00
zip.go API: Apply "golangci-lint" recommendations #5330 2025-11-22 09:25:01 +01:00
zip_test.go

API Package Guide

Overview

The API package exposes PhotoPrisms HTTP endpoints via Gin handlers. Each file under internal/api contains the handlers, request/response DTOs, and Swagger annotations for a specific feature area. Handlers remain thin: they validate input, enforce security or ACL checks, and delegate domain work to services in internal/photoprism, internal/service, or other internal packages. Keep exported types aligned with the REST schema and avoid embedding business logic directly in handlers.

Routing & Wiring

  • Register handlers in internal/server/routes.go by attaching them to the proper router group (for example, APIv1 := router.Group(conf.BaseUri("/api/v1"), Api(conf))).
  • Group endpoints by resource to match existing patterns: sessions, cluster, photos, labels, files, downloads, metadata, and technical routes.
  • Apply middleware stacks (Api, AuthRequired, limiter.Auth, etc.) at the router level to keep handlers focused on request handling.
  • Use conf.BaseUri() when constructing route prefixes so configuration overrides propagate consistently.
  • When new endpoints require feature toggles, gate them in the router rather than inside the handler so disabled routes remain undiscoverable.

Handler Implementation Patterns

  • Accept and return JSON using the shared response helpers. Set header.ContentTypeJSON and ensure responses include proper cache headers (no-store for sensitive payloads).
  • Parse parameters with Gin binding and validate inputs before delegating work. For complex payloads, define dedicated request structs with validation tags.
  • Use the shared download helpers (safe.Download, avatar.SafeDownload) when calling outward HTTP APIs to inherit timeout, size, and SSRF protections.
  • Query and persist data through the corresponding services or repositories; avoid ad-hoc SQL or GORM usage in handlers when dedicated functions exist elsewhere.
  • Surface pagination consistently with count, offset, and limit following the defaults (100 max 1000). Validate offset >= 0 and clamp count to the allowed range.
  • When responses need role-specific fields, build DTOs that redact sensitive data for non-admin roles so the handler stays deterministic.

Security & Middleware

  • Authenticate requests using the standard middleware (AuthRequired) and check roles via helpers in internal/auth/acl (acl.ParseRole, acl.ScopePermits, acl.ScopeAttrPermits).
  • Never log secrets or tokens. Prefer structured logging through event.Log and redact sensitive values before logging.
  • Enforce rate limiting with the shared limiters (limiter.Auth, limiter.Login) and respond with limiter.AbortJSON to maintain consistent 429 JSON payloads.
  • Derive client IPs through api.ClientIP and extract bearer tokens with header.BearerToken or the helper setters. Use constant-time comparison for tokens and secrets.
  • For downloads or proxy endpoints, validate URLs against allowed schemes (http, https) and reject private or loopback addresses unless explicitly required.

Audit Logging

  • Emit security events via event.Audit* (AuditInfo, AuditWarn, AuditErr, AuditDebug) and always build the slice as Who → What → Outcome.
    • Who: ClientIP(c) followed by the most specific actor context ("session %s", "client %s", "user %s").
    • What: Resource constant plus action segments (for example, string(acl.ResourceCluster), "node", "%s"). Place extra context such as counts or error placeholders in separate segments before the outcome.
    • Outcome: End with a single token such as status.Succeeded, status.Failed, status.Denied, or status.Error(err) when the sanitized error message should be the outcome; nothing comes after it.
  • Prefer existing helpers (ClientIP, clean.Log, clean.LogQuote, clean.Error) instead of formatting values manually, and avoid inline = expressions.
  • Example patterns:
    event.AuditInfo([]string{
        ClientIP(c),
        "session %s",
        string(acl.ResourceCluster),
        "node", "%s",
        status.Deleted,
    }, s.RefID, uuid)
    
    event.AuditErr([]string{
        clientIp,
        "session %s",
        string(acl.ResourceCluster),
        "download theme",
        status.Error(err),
    }, refID)
    
  • See specs/common/audit-logs.md for the full conventions and additional examples that agents should follow.

Swagger Documentation

  • Annotate handlers with Swagger comments that include full /api/v1/... paths, request/response schemas, and security definitions. Only annotate routes that are externally accessible.
  • Regenerate docs after adding or updating handlers: make fmt-go swag-fmt swag. This formats Go files, normalizes annotations, and updates internal/api/swagger.json. Do not edit the generated JSON manually.
  • When adding new DTOs, keep field names aligned with the JSON schema and update client documentation if serialized names change.
  • Use enum annotations sparingly and ensure they reflect actual runtime constraints to avoid misleading generated clients.

Testing Strategy

  • Build tests around the API harness (NewApiTest) to obtain a configured Gin router, config, and dependencies. This isolates filesystem paths and avoids polluting global state.
  • Wrap requests with helper functions (for example, PerformRequestJSON, PerformAuthenticatedRequest) to capture status codes, headers, and payloads. Assert headers using constants from pkg/http/header.
  • When handlers interact with the database, initialize fixtures through config helpers such as config.NewTestConfig("api") or config.NewMinimalTestConfigWithDb("api", t.TempDir()) depending on fixture needs.
  • Stub external dependencies (httptest.Server) for remote calls and set AllowPrivate=true explicitly when the test server binds to loopback addresses.
  • Structure tests with table-driven subtests (t.Run("CaseName", ...)) and use PascalCase names. Provide cleanup functions (t.Cleanup) to remove temporary files or databases created during tests.

Focused Test Runs

  • Fast iteration: go test ./internal/api -run '<Package|HandlerName>' -count=1
  • Cluster endpoints: go test ./internal/api -run 'Cluster' -count=1
  • Downloads and zip streaming: go test ./internal/api -run 'Download|Archive' -count=1
  • Combined CLI and API validation: pair go test ./internal/commands -run 'Cluster' -count=1 with the matching API suite to ensure DTOs remain compatible.

Preflight Checklist

  • Format and regenerate documentation: make fmt-go swag-fmt swag
  • Compile backend: go build ./...
  • Execute targeted API suites: go test ./internal/api -run '<Name>' -count=1
  • Run integration-heavy checks before release: go test ./internal/service/cluster/registry -count=1 alongside relevant API routes to confirm cluster DTOs stay aligned.
  • Verify that photoprism show commands --json reflects any new API-driven flags or outputs when CLI exposure changes.