Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
109 lines
2.8 KiB
Go
109 lines
2.8 KiB
Go
package httpapi
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
const (
|
|
defaultPageLimit = 50
|
|
maxPageLimit = 200
|
|
maxTreePageLimit = 2000
|
|
)
|
|
|
|
// QuerySearch returns the list/search text from query params.
|
|
// Accepts both `q` (canonical) and `search` (UI/legacy alias).
|
|
func QuerySearch(r *http.Request) string {
|
|
q := strings.TrimSpace(r.URL.Query().Get("q"))
|
|
if q != "" {
|
|
return q
|
|
}
|
|
return strings.TrimSpace(r.URL.Query().Get("search"))
|
|
}
|
|
|
|
// QueryTruthy reports whether a query param is an explicit truthy flag
|
|
// (1/true/yes/on). Empty or unrecognized values are false.
|
|
func QueryTruthy(r *http.Request, key string) bool {
|
|
v := strings.ToLower(strings.TrimSpace(r.URL.Query().Get(key)))
|
|
switch v {
|
|
case "1", "true", "yes", "on":
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
// QueryDetailed is true when the client opts into full product list fields
|
|
// (JSONB attributes, descriptions, quality scoring inputs) via detailed=1.
|
|
func QueryDetailed(r *http.Request) bool {
|
|
return QueryTruthy(r, "detailed")
|
|
}
|
|
|
|
// ParseLimitOffset reads limit/offset query params with safe defaults and caps.
|
|
// Oversized limits are clamped to maxPageLimit.
|
|
func ParseLimitOffset(r *http.Request) (limit, offset int) {
|
|
return ParseLimitOffsetMax(r, maxPageLimit)
|
|
}
|
|
|
|
// ParseLimitOffsetMax allows a higher per-endpoint cap and clamps to max
|
|
// (used for category tree loads).
|
|
func ParseLimitOffsetMax(r *http.Request, max int) (limit, offset int) {
|
|
if max <= 0 {
|
|
max = maxPageLimit
|
|
}
|
|
limit, _ = strconv.Atoi(r.URL.Query().Get("limit"))
|
|
offset, _ = strconv.Atoi(r.URL.Query().Get("offset"))
|
|
if limit <= 0 {
|
|
limit = defaultPageLimit
|
|
}
|
|
if limit > max {
|
|
limit = max
|
|
}
|
|
if offset < 0 {
|
|
offset = 0
|
|
}
|
|
return limit, offset
|
|
}
|
|
|
|
// ParsePageLimitOffset supports legacy page/limit and v2 limit/offset.
|
|
// When page is set, offset = (page-1)*limit with legacy defaults (limit=25, max 100).
|
|
// When only offset/limit are set (no page), uses ParseLimitOffset defaults (limit=50, max 200).
|
|
func ParsePageLimitOffset(r *http.Request) (page, limit, offset int) {
|
|
pageRaw := strings.TrimSpace(r.URL.Query().Get("page"))
|
|
if pageRaw == "" {
|
|
limit, offset = ParseLimitOffset(r)
|
|
page = 1
|
|
if limit > 0 {
|
|
page = offset/limit + 1
|
|
}
|
|
return page, limit, offset
|
|
}
|
|
page, _ = strconv.Atoi(pageRaw)
|
|
if page < 1 {
|
|
page = 1
|
|
}
|
|
limit, _ = strconv.Atoi(r.URL.Query().Get("limit"))
|
|
if limit <= 0 {
|
|
limit = 25
|
|
}
|
|
if limit > 100 {
|
|
limit = 100
|
|
}
|
|
offset = (page - 1) * limit
|
|
return page, limit, offset
|
|
}
|
|
|
|
// pageSlice returns a bounded page of items and the original total length.
|
|
func pageSlice[T any](items []T, limit, offset int) (page []T, total int) {
|
|
total = len(items)
|
|
if offset >= total {
|
|
return []T{}, total
|
|
}
|
|
end := offset + limit
|
|
if end > total {
|
|
end = total
|
|
}
|
|
return items[offset:end], total
|
|
}
|