httpserver

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 20, 2026 License: MPL-2.0 Imports: 21 Imported by: 0

Documentation

Overview

Package httpserver is the Gin HTTP layer: routes, JSON/error envelopes, API-key auth on mutating endpoints, and wiring to executor.Executor (business logic). List/read routes are public; POST/PUT/DELETE require Bearer API key.

Index

Constants

View Source
const (
	DefaultListLimit = 100
	MinListLimit     = 1
	MaxListLimit     = 100
)

API list limits (public contract). Store enforces a higher ceiling separately.

Variables

This section is empty.

Functions

func APIKeyAuth

func APIKeyAuth(secret string, log *zap.Logger) gin.HandlerFunc

APIKeyAuth requires Authorization: Bearer <secret> for mutating routes. Compares the full header value in constant time to reduce timing leakage of the API key length/prefix.

func NormalizeListLimit

func NormalizeListLimit(n int) int

NormalizeListLimit clamps n to [MinListLimit, MaxListLimit]; zero or negative uses DefaultListLimit.

func ParseListLimitQuery

func ParseListLimitQuery(s string) (int, error)

ParseListLimitQuery parses the `limit` query parameter. Empty uses DefaultListLimit. Non-empty values must be decimal integers; the result is normalized to API bounds.

func RegisterRoutes

func RegisterRoutes(r *gin.Engine, h *Handler, cfg *config.Config, log *zap.Logger)

RegisterRoutes attaches all HTTP routes to the Gin engine. POST and document PUT/PATCH use SignatureOrAPIKeyAuth (API key or signatures in body); DELETE and registry PUT use APIKeyAuth only.

func SetAuthMode added in v0.2.0

func SetAuthMode(c *gin.Context, mode AuthMode)

SetAuthMode stores the authentication mode in the Gin context for executor access.

func SignatureOrAPIKeyAuth added in v0.2.0

func SignatureOrAPIKeyAuth(secret string, log *zap.Logger) gin.HandlerFunc

SignatureOrAPIKeyAuth accepts either API key (ops path) or valid signatures in request body (user path). Used for POST (create) and PUT/PATCH (replace/update) on playlists, playlist-groups, and channels: requests with a non-empty signatures[] array may omit the API key; the executor verifies signatures.

Authentication flow:

  • Path A (Ops): Has Authorization: Bearer header → validate API key → set AuthModeAPIKey
  • Path B (User): No Authorization header but has signatures[] in body → set AuthModeSignature
  • Reject: No Authorization header and no signatures in body

func ZapLogger

func ZapLogger(log *zap.Logger) gin.HandlerFunc

ZapLogger emits basic request logs (method, path, status, latency).

Types

type AuthMode added in v0.2.0

type AuthMode int

AuthMode distinguishes API key (ops) vs signature-based (user) authentication paths.

const (
	// AuthModeAPIKey indicates request used API key authentication (ops path).
	AuthModeAPIKey AuthMode = iota
	// AuthModeSignature indicates request used cryptographic signature authentication (user path).
	AuthModeSignature
)

func GetAuthMode added in v0.2.0

func GetAuthMode(c *gin.Context) AuthMode

GetAuthMode retrieves the authentication mode from the Gin context; defaults to AuthModeAPIKey if not set.

type ErrorResponse

type ErrorResponse struct {
	Error   string `json:"error"`
	Message string `json:"message"`
}

ErrorResponse matches the feed OpenAPI error shape.

type Handler

type Handler struct {
	Exec    executor.Executor
	Log     *zap.Logger
	Version string
}

Handler carries the executor, logger, and build version for health/metadata responses.

func (*Handler) APIInfo

func (h *Handler) APIInfo(c *gin.Context)

APIInfo serves GET /api/v1.

func (*Handler) CreateChannel

func (h *Handler) CreateChannel(c *gin.Context)

CreateChannel POST /api/v1/channels.

func (*Handler) CreatePlaylist

func (h *Handler) CreatePlaylist(c *gin.Context)

CreatePlaylist POST /api/v1/playlists.

func (*Handler) CreatePlaylistGroup

func (h *Handler) CreatePlaylistGroup(c *gin.Context)

CreatePlaylistGroup POST /api/v1/playlist-groups.

func (*Handler) DeleteChannel

func (h *Handler) DeleteChannel(c *gin.Context)

DeleteChannel DELETE /api/v1/channels/:id.

func (*Handler) DeletePlaylist

func (h *Handler) DeletePlaylist(c *gin.Context)

DeletePlaylist DELETE /api/v1/playlists/:id.

func (*Handler) DeletePlaylistGroup

func (h *Handler) DeletePlaylistGroup(c *gin.Context)

DeletePlaylistGroup DELETE /api/v1/playlist-groups/:id.

func (*Handler) GetChannel

func (h *Handler) GetChannel(c *gin.Context)

GetChannel GET /api/v1/channels/:id.

func (*Handler) GetChannelRegistry

func (h *Handler) GetChannelRegistry(c *gin.Context)

GetChannelRegistry GET /api/v1/registry/channels.

func (*Handler) GetPlaylist

func (h *Handler) GetPlaylist(c *gin.Context)

GetPlaylist GET /api/v1/playlists/:id.

func (*Handler) GetPlaylistGroup

func (h *Handler) GetPlaylistGroup(c *gin.Context)

GetPlaylistGroup GET /api/v1/playlist-groups/:id.

func (*Handler) GetPlaylistItem

func (h *Handler) GetPlaylistItem(c *gin.Context)

GetPlaylistItem GET /api/v1/playlist-items/:id.

func (*Handler) Health

func (h *Handler) Health(c *gin.Context)

Health is a liveness endpoint (no version prefix in plan; we expose both /health and /api/v1/health).

func (*Handler) HealthAPI

func (h *Handler) HealthAPI(c *gin.Context)

HealthAPI matches OpenAPI /api/v1/health.

func (*Handler) ListChannels

func (h *Handler) ListChannels(c *gin.Context)

ListChannels GET /api/v1/channels.

func (*Handler) ListPlaylistGroups

func (h *Handler) ListPlaylistGroups(c *gin.Context)

ListPlaylistGroups GET /api/v1/playlist-groups.

func (*Handler) ListPlaylistItems

func (h *Handler) ListPlaylistItems(c *gin.Context)

ListPlaylistItems GET /api/v1/playlist-items.

func (*Handler) ListPlaylists

func (h *Handler) ListPlaylists(c *gin.Context)

ListPlaylists GET /api/v1/playlists.

func (*Handler) ReplaceChannel

func (h *Handler) ReplaceChannel(c *gin.Context)

ReplaceChannel PUT /api/v1/channels/:id.

func (*Handler) ReplaceChannelRegistry

func (h *Handler) ReplaceChannelRegistry(c *gin.Context)

ReplaceChannelRegistry PUT /api/v1/registry/channels.

func (*Handler) ReplacePlaylist

func (h *Handler) ReplacePlaylist(c *gin.Context)

ReplacePlaylist PUT /api/v1/playlists/:id.

func (*Handler) ReplacePlaylistGroup

func (h *Handler) ReplacePlaylistGroup(c *gin.Context)

ReplacePlaylistGroup PUT /api/v1/playlist-groups/:id.

func (*Handler) UpdateChannel

func (h *Handler) UpdateChannel(c *gin.Context)

UpdateChannel PATCH /api/v1/channels/:id.

func (*Handler) UpdatePlaylist

func (h *Handler) UpdatePlaylist(c *gin.Context)

UpdatePlaylist PATCH /api/v1/playlists/:id.

func (*Handler) UpdatePlaylistGroup

func (h *Handler) UpdatePlaylistGroup(c *gin.Context)

UpdatePlaylistGroup PATCH /api/v1/playlist-groups/:id.

type ListResponse

type ListResponse[T any] struct {
	Items   []T    `json:"items"`
	Cursor  string `json:"cursor,omitempty"`
	HasMore bool   `json:"hasMore"`
}

ListResponse is the JSON envelope for GET list endpoints: items, optional cursor, hasMore.

func NewListResponse

func NewListResponse[T any](items []T, nextCursor string) ListResponse[T]

NewListResponse sets HasMore from nextCursor (non-empty means another page exists).

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server wraps stdlib http.Server with the Gin engine built in New.

func New

func New(cfg *config.Config, log *zap.Logger, exec executor.Executor, version string) *Server

New builds a Gin engine: recovery, optional Sentry, Zap request logging, RegisterRoutes, and http.Server timeouts from cfg.

func (*Server) ListenAndServe

func (s *Server) ListenAndServe() error

ListenAndServe starts the HTTP server (blocking).

func (*Server) Shutdown

func (s *Server) Shutdown(ctx context.Context) error

Shutdown gracefully stops the server (caller may use a deadline; this also applies an internal 15s cap).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL