API: Add const, func, and struct comments for easier troubleshooting

Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
Michael Mayer
2025-09-30 22:02:43 +02:00
parent bbf6580512
commit 983cbb50ff
6 changed files with 23 additions and 6 deletions

View File

@@ -1,7 +1,7 @@
package api package api
import ( import (
_ "embed" _ "embed" // required for go:embed video placeholder
"net/http" "net/http"
"strings" "strings"
@@ -18,6 +18,7 @@ import (
//go:embed embed/video.mp4 //go:embed embed/video.mp4
var brokenVideo []byte var brokenVideo []byte
// Abort writes a localized error response and stops further handler processing.
func Abort(c *gin.Context, code int, id i18n.Message, params ...interface{}) { func Abort(c *gin.Context, code int, id i18n.Message, params ...interface{}) {
resp := i18n.NewResponse(code, id, params...) resp := i18n.NewResponse(code, id, params...)
@@ -30,6 +31,7 @@ func Abort(c *gin.Context, code int, id i18n.Message, params ...interface{}) {
c.AbortWithStatusJSON(code, resp) c.AbortWithStatusJSON(code, resp)
} }
// Error aborts the request while attaching error details to the response payload.
func Error(c *gin.Context, code int, err error, id i18n.Message, params ...interface{}) { func Error(c *gin.Context, code int, err error, id i18n.Message, params ...interface{}) {
resp := i18n.NewResponse(code, id, params...) resp := i18n.NewResponse(code, id, params...)
@@ -95,22 +97,27 @@ func AbortAlbumNotFound(c *gin.Context) {
Abort(c, http.StatusNotFound, i18n.ErrAlbumNotFound) Abort(c, http.StatusNotFound, i18n.ErrAlbumNotFound)
} }
// AbortSaveFailed aborts with a generic 500 "save failed" error.
func AbortSaveFailed(c *gin.Context) { func AbortSaveFailed(c *gin.Context) {
Abort(c, http.StatusInternalServerError, i18n.ErrSaveFailed) Abort(c, http.StatusInternalServerError, i18n.ErrSaveFailed)
} }
// AbortDeleteFailed aborts with a generic 500 "delete failed" error.
func AbortDeleteFailed(c *gin.Context) { func AbortDeleteFailed(c *gin.Context) {
Abort(c, http.StatusInternalServerError, i18n.ErrDeleteFailed) Abort(c, http.StatusInternalServerError, i18n.ErrDeleteFailed)
} }
// AbortNotImplemented aborts with status 501 when a feature is unavailable.
func AbortNotImplemented(c *gin.Context) { func AbortNotImplemented(c *gin.Context) {
Abort(c, http.StatusNotImplemented, i18n.ErrUnsupported) Abort(c, http.StatusNotImplemented, i18n.ErrUnsupported)
} }
// AbortUnexpectedError aborts with a generic 500 error.
func AbortUnexpectedError(c *gin.Context) { func AbortUnexpectedError(c *gin.Context) {
Abort(c, http.StatusInternalServerError, i18n.ErrUnexpected) Abort(c, http.StatusInternalServerError, i18n.ErrUnexpected)
} }
// AbortBadRequest attaches validation details and responds with status 400.
func AbortBadRequest(c *gin.Context, errs ...error) { func AbortBadRequest(c *gin.Context, errs ...error) {
// Log and attach validation errors to the context. // Log and attach validation errors to the context.
for _, err := range errs { for _, err := range errs {
@@ -127,34 +134,41 @@ func AbortBadRequest(c *gin.Context, errs ...error) {
Abort(c, http.StatusBadRequest, i18n.ErrBadRequest) Abort(c, http.StatusBadRequest, i18n.ErrBadRequest)
} }
// AbortFeatureDisabled aborts with a forbidden response when a feature is disabled.
func AbortFeatureDisabled(c *gin.Context) { func AbortFeatureDisabled(c *gin.Context) {
Abort(c, http.StatusForbidden, i18n.ErrFeatureDisabled) Abort(c, http.StatusForbidden, i18n.ErrFeatureDisabled)
} }
// AbortQuotaExceeded aborts with a forbidden response when quotas are exhausted.
func AbortQuotaExceeded(c *gin.Context) { func AbortQuotaExceeded(c *gin.Context) {
Abort(c, http.StatusForbidden, i18n.ErrQuotaExceeded) Abort(c, http.StatusForbidden, i18n.ErrQuotaExceeded)
} }
// AbortBusy responds with HTTP 429 to signal temporary overload.
func AbortBusy(c *gin.Context) { func AbortBusy(c *gin.Context) {
Abort(c, http.StatusTooManyRequests, i18n.ErrBusy) Abort(c, http.StatusTooManyRequests, i18n.ErrBusy)
} }
// AbortInvalidName aborts with HTTP 400 when a name fails validation.
func AbortInvalidName(c *gin.Context) { func AbortInvalidName(c *gin.Context) {
Abort(c, http.StatusBadRequest, i18n.ErrInvalidName) Abort(c, http.StatusBadRequest, i18n.ErrInvalidName)
} }
// AbortInvalidCredentials responds with HTTP 401 for failed authentication attempts.
func AbortInvalidCredentials(c *gin.Context) { func AbortInvalidCredentials(c *gin.Context) {
if c != nil { if c != nil {
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": authn.ErrInvalidCredentials.Error(), "code": i18n.ErrInvalidCredentials, "message": i18n.Msg(i18n.ErrInvalidCredentials)}) c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": authn.ErrInvalidCredentials.Error(), "code": i18n.ErrInvalidCredentials, "message": i18n.Msg(i18n.ErrInvalidCredentials)})
} }
} }
// AbortVideo writes a placeholder MP4 response for video errors.
func AbortVideo(c *gin.Context) { func AbortVideo(c *gin.Context) {
if c != nil { if c != nil {
AbortVideoWithStatus(c, http.StatusOK) AbortVideoWithStatus(c, http.StatusOK)
} }
} }
// AbortVideoWithStatus writes the placeholder MP4 response using the provided status code.
func AbortVideoWithStatus(c *gin.Context, code int) { func AbortVideoWithStatus(c *gin.Context, code int) {
if c != nil { if c != nil {
c.Data(code, header.ContentTypeMp4AvcMain, brokenVideo) c.Data(code, header.ContentTypeMp4AvcMain, brokenVideo)

View File

@@ -11,6 +11,7 @@ import (
// Event represents an api event type. // Event represents an api event type.
type Event string type Event string
// Canonical event payload status strings used by the API layer.
const ( const (
StatusCreated Event = "created" StatusCreated Event = "created"
StatusUpdated Event = "updated" StatusUpdated Event = "updated"

View File

@@ -16,11 +16,13 @@ import (
"github.com/photoprism/photoprism/pkg/service/http/header" "github.com/photoprism/photoprism/pkg/service/http/header"
) )
// ThumbCache describes files persisted on disk for cached thumbnails and share images.
type ThumbCache struct { type ThumbCache struct {
FileName string FileName string
ShareName string ShareName string
} }
// ByteCache wraps in-memory cached byte slices for fast responses.
type ByteCache struct { type ByteCache struct {
Data []byte Data []byte
} }

View File

@@ -2,11 +2,9 @@ package api
import "time" import "time"
// Schema Overrides for Swagger generation. // SwaggerTimeDuration overrides the generated schema for time.Duration to avoid unstable enums
// from the standard library constants (Nanosecond, Minute, etc.). Using a simple integer schema is
// Override the generated schema for time.Duration to avoid unstable enums // accurate (nanoseconds) and deterministic.
// from the standard library constants (Nanosecond, Minute, etc.). Using
// a simple integer schema is accurate (nanoseconds) and deterministic.
// //
// @name time.Duration // @name time.Duration
// @description Duration in nanoseconds (int64). Examples: 1000000000 (1s), 60000000000 (1m). // @description Duration in nanoseconds (int64). Examples: 1000000000 (1s), 60000000000 (1m).

View File

@@ -7,6 +7,7 @@ import (
"github.com/photoprism/photoprism/pkg/fs" "github.com/photoprism/photoprism/pkg/fs"
) )
// AllowedPaths lists absolute directories from which downloads may be registered.
var AllowedPaths []string var AllowedPaths []string
// Deny checks if the filename may not be registered for download. // Deny checks if the filename may not be registered for download.

View File

@@ -24,6 +24,7 @@ import (
"github.com/photoprism/photoprism/pkg/txt" "github.com/photoprism/photoprism/pkg/txt"
) )
// UploadPath is the root directory underneath which user uploads are staged.
const ( const (
UploadPath = "/upload" UploadPath = "/upload"
) )