Files
wehub-resource-sync f99010fae1
Desktop Artifacts / Desktop Build (Linux) (push) Waiting to run
Desktop Artifacts / Desktop Build (Windows) (push) Waiting to run
Desktop Artifacts / Desktop Build (Linux (arm64)) (push) Waiting to run
Desktop Artifacts (macOS) / Desktop Build (macOS (aarch64)) (push) Waiting to run
Desktop Artifacts (macOS) / Desktop Build (macOS (x86_64)) (push) Waiting to run
CI / lint (push) Failing after 1s
CI / frontend (push) Failing after 1s
CI / scripts (push) Failing after 1s
CI / Go Test (ubuntu-latest) (push) Failing after 0s
CI / frontend-node-25 (push) Failing after 1s
CI / docs (push) Failing after 0s
CI / coverage (push) Failing after 0s
CI / e2e (push) Failing after 0s
Docker / build-and-push (push) Failing after 1s
CI / integration (push) Failing after 4m43s
CI / Go Test (windows-latest) (push) Has been cancelled
CI / Desktop Unit Tests (Windows) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:30:36 +08:00

89 lines
2.6 KiB
Go

package server
import (
"fmt"
"net/http"
"strconv"
)
// parseIntParam reads an integer query parameter from r.
// Returns (value, true) on success, or writes a 400 error and
// returns (0, false) if the parameter is present but not a valid
// integer. When the parameter is absent, returns (0, true).
func parseIntParam(
w http.ResponseWriter, r *http.Request, name string,
) (int, bool) {
raw := r.URL.Query().Get(name)
if raw == "" {
return 0, true
}
v, err := strconv.Atoi(raw)
if err != nil {
writeError(w, http.StatusBadRequest,
fmt.Sprintf("invalid %s parameter", name))
return 0, false
}
return v, true
}
// parseBoolParam reads a boolean query parameter from r. Returns
// (false, true) when the parameter is absent, and writes a 400 unless
// the parameter is exactly "true" or "false".
func parseBoolParam(
w http.ResponseWriter, r *http.Request, name string,
) (bool, bool) {
raw := r.URL.Query().Get(name)
if raw == "" {
return false, true
}
switch raw {
case "true":
return true, true
case "false":
return false, true
default:
writeError(w, http.StatusBadRequest,
fmt.Sprintf("invalid %s parameter", name))
return false, false
}
}
// parseNonNegativeIntParam reads an integer query parameter that must
// be non-negative (e.g. cursor / OFFSET values). Returns (value, true)
// on success, writes a 400 and returns (0, false) on a non-integer or
// negative value. Negative values flow through to SQL OFFSET on
// PostgreSQL as an error (SQLite tolerates them); rejecting at the
// handler turns the silent 500 into a clean 400.
func parseNonNegativeIntParam(
w http.ResponseWriter, r *http.Request, name string,
) (int, bool) {
v, ok := parseIntParam(w, r, name)
if !ok {
return 0, false
}
if v < 0 {
writeError(w, http.StatusBadRequest,
fmt.Sprintf("%s must not be negative", name))
return 0, false
}
return v, true
}
// validateDateFilters validates the shared date query params: date, date_from,
// and date_to must be YYYY-MM-DD; date_from must not be after date_to; and
// active_since must be an RFC3339 timestamp. On the first invalid value it
// writes a 400 and returns false, so callers must return when it returns false.
// Pass "" for any param an endpoint does not accept. Centralizing this keeps
// malformed dates out of the query layer, where they would otherwise reach the
// DB and surface as a 500 (e.g. PostgreSQL casting to date/timestamptz).
// clampLimit applies a default and upper bound to a limit value.
func clampLimit(limit, defaultLimit, maxLimit int) int {
if limit <= 0 {
return defaultLimit
}
if limit > maxLimit {
return maxLimit
}
return limit
}