ginapi

package
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 1, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package ginapi writes api envelopes, lists and objects through a gin.Context, binds list parameters from the query string, and carries the locale middleware. The envelope vocabulary itself lives in api, which depends on nothing.

Every writer here is byte-for-byte identical to the root net/http writer for the same error — gin_test.go asserts it off a real socket.

Index

Constants

View Source
const (
	// LanguageCookieName is the default cookie name for language preference
	LanguageCookieName = "lang"
	// LanguageCookieMaxAge is 1 year in seconds
	LanguageCookieMaxAge = 31536000
)

Variables

This section is empty.

Functions

func BadGateway

func BadGateway(c *gin.Context, message string)

BadGateway sends 502 api_error for an upstream failure.

func BadRequest

func BadRequest(c *gin.Context, message string)

BadRequest sends 400 invalid_request_error.

func BadRequestParam

func BadRequestParam(c *gin.Context, param, message string)

BadRequestParam sends 400 naming the offending request field.

func BadRequestWithCode

func BadRequestWithCode(c *gin.Context, code api.Code, message string)

BadRequestWithCode sends 400 with a machine-readable code.

func Bind

func Bind(c *gin.Context) api.ListParams

Bind reads limit, offset and sort (or sort_by) from the query string, unnormalized.

func BindDefault

func BindDefault(c *gin.Context) api.ListParams

BindDefault reads and normalizes against api's defaults (20, cap 100).

func BindWithDefaults

func BindWithDefaults(c *gin.Context, defaultLimit, maxLimit int) api.ListParams

BindWithDefaults reads and normalizes list parameters against the caller's default and cap.

func BuildSupportedMap

func BuildSupportedMap(languages []string) map[string]struct{}

BuildSupportedMap creates a map of supported languages for fast lookup. Useful for redirect middleware that needs to check language validity.

func Conflict

func Conflict(c *gin.Context, message string)

Conflict sends 409. The state conflict is in the code, not a transport type.

func Created

func Created(c *gin.Context, obj any)

Created sends 201 with the created resource.

func Deleted

func Deleted(c *gin.Context, objectType, id string)

Deleted sends a deletion confirmation.

func DetectPreferredLanguage

func DetectPreferredLanguage(c *gin.Context, supportedMap map[string]struct{}, defaultLang string) string

DetectPreferredLanguage determines user's preferred language. Priority: cookie → Accept-Language → default

func ExtractLanguageFromPath

func ExtractLanguageFromPath(path string) string

ExtractLanguageFromPath extracts a 2-3 character language code from URL path prefix. e.g., "/ja/galleries" -> "ja", "/galleries" -> "" Exported for use by redirect middleware.

func Fail

func Fail(c *gin.Context, err error)

Fail writes err as the canonical envelope, deriving status and shape from it. It is api.WriteError against c.Writer — the same function, not a parallel implementation, which is how byte-for-byte equivalence is guaranteed rather than tested for.

func Forbidden

func Forbidden(c *gin.Context)

Forbidden sends 403 authorization_error.

func ForbiddenWithMessage

func ForbiddenWithMessage(c *gin.Context, message string)

ForbiddenWithMessage sends 403 with a custom message.

func GetLanguage

func GetLanguage(c *gin.Context) string

GetLanguage retrieves the detected language from the gin context. Returns "en" as fallback if not set.

func HandleLanguageRedirect

func HandleLanguageRedirect(c *gin.Context, cfg LanguageRedirectConfig) bool

HandleLanguageRedirect checks if a language redirect is needed and performs it. Returns true if a redirect was performed (caller should return early). Returns false if no redirect needed (caller should continue to serve the page).

This is designed to be called from a NoRoute handler:

r.NoRoute(func(c *gin.Context) {
    if middleware.HandleLanguageRedirect(c, cfg) {
        return // redirect was performed
    }
    // serve SPA
    serveIndexHTML(c)
})

Behavior:

  • If URL has a valid language prefix (e.g., /en/videos): set cookie, return false
  • If URL has NO language prefix (e.g., /videos): redirect to prefixed URL, return true

func InternalError

func InternalError(c *gin.Context, message string)

InternalError sends 500 api_error. The message is scrubbed: 500 is the one status that means "unexpected", so its text may carry an internal cause.

func Language

func Language(cfg LanguageConfig) gin.HandlerFunc

Language returns middleware that detects user language from: 1. Query parameter (?lang=ja) - for API routes 2. URL path prefix (/ja/...) - for frontend routes 3. Cookie (user's saved preference) 4. Accept-Language header with q-value parsing 5. Default language

The detected language is stored in gin context and retrieved via GetLanguage(c). The Content-Language header is set on the response.

func ListResponse

func ListResponse[T any](c *gin.Context, data []T, total int64, limit, offset int)

ListResponse sends a list body with has_more computed.

func ModerationRejected

func ModerationRejected(c *gin.Context, reason string)

ModerationRejected sends 422 invalid_request_error with the stable code moderation_rejected: transport classification is unchanged, and the code is what tells a SPA to show the author a reason instead of retrying.

func NoContent

func NoContent(c *gin.Context)

NoContent sends 204.

func NotConfigured

func NotConfigured(c *gin.Context, message string)

NotConfigured sends 501 api_error for an optional capability the operator never wired — a deployment gap, distinguishable from a crash by its code.

func NotFound

func NotFound(c *gin.Context, entity string)

NotFound sends 404 for a named entity. The transport type stays invalid_request_error, as authkit and openrails deploy it; resource_not_found is the code a client branches on.

func NotFoundWithMessage

func NotFoundWithMessage(c *gin.Context, message string)

NotFoundWithMessage sends 404 with a custom message.

func NotImplemented

func NotImplemented(c *gin.Context, message string)

NotImplemented sends 501 api_error with the stable code not_implemented: this build lacks the capability. No new transport type — the code is the signal to hide the feature rather than retry.

func Object

func Object(c *gin.Context, obj any)

Object sends a single resource. The resource carries its own "object" field.

func ParseAcceptLanguage

func ParseAcceptLanguage(header string, supported map[string]struct{}) string

ParseAcceptLanguage parses the Accept-Language header and returns the best supported language based on q-values. Exported for use by redirect middleware.

func Send

func Send(c *gin.Context, status int, t api.Type, code api.Code, message, param string)

Send writes an explicit envelope. Code may be empty: an absent code means "no machine reason beyond the status", and the writers never invent one. param is a plain string — the wire's pointer is api's problem.

func ServiceUnavailable

func ServiceUnavailable(c *gin.Context, message string)

ServiceUnavailable sends 503 api_error.

func SetLanguageCookie

func SetLanguageCookie(c *gin.Context, lang string)

SetLanguageCookie sets the language preference cookie (1 year, SameSite=Lax).

func Success

func Success(c *gin.Context, message string)

Success sends 200 with a bare human-readable message.

func TooManyRequests

func TooManyRequests(c *gin.Context, message string)

TooManyRequests sends 429 rate_limit_error.

func Unauthorized

func Unauthorized(c *gin.Context)

Unauthorized sends 401 authentication_error.

func UnauthorizedWithMessage

func UnauthorizedWithMessage(c *gin.Context, message string)

UnauthorizedWithMessage sends 401 with a custom message.

func UnprocessableEntity

func UnprocessableEntity(c *gin.Context, message string)

UnprocessableEntity sends 422 invalid_request_error: well-formed syntax the server cannot act on. For a moderation refusal use ModerationRejected.

func UnsupportedMediaType

func UnsupportedMediaType(c *gin.Context, message string)

UnsupportedMediaType sends 415 invalid_request_error.

Types

type LanguageConfig

type LanguageConfig struct {
	// Supported languages (e.g., []string{"en", "ja", "ko", "zh"})
	Supported []string
	// Default language if none detected (defaults to "en")
	Default string
	// QueryParam to check for language override (defaults to "lang")
	QueryParam string
	// CookieName to check for language preference (defaults to "lang")
	CookieName string
}

LanguageConfig configures the language detection middleware.

type LanguageRedirectConfig

type LanguageRedirectConfig struct {
	// Supported languages (e.g., []string{"en", "ja", "ko", "zh"})
	Supported []string
	// Default language if none detected (defaults to "en")
	Default string
}

LanguageRedirectConfig configures language redirect behavior for NoRoute handlers.

Jump to

Keyboard shortcuts

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