Skip to content

Latest commit

 

History

History
148 lines (117 loc) · 4.17 KB

File metadata and controls

148 lines (117 loc) · 4.17 KB

Request Binding

한국어: 요청 바인딩

JSON Body

Bind[T] decodes the request body into a struct and automatically runs validation.

type CreateUserDTO struct {
    Name  string `validate:"required,min=2,max=50"`
    Email string `validate:"required,email"`
    Age   int    `validate:"min=0,max=150"`
    Role  string `validate:"oneof=admin user guest"`
}

func (c *UserController) create(r *http.Request) (any, error) {
    dto, err := core.Bind[CreateUserDTO](r)
    if err \!= nil {
        return nil, err // already a 400 Bad Request
    }
    return c.svc.Create(dto), nil
}

Returns ErrBadRequest automatically if:

  • Content-Type is not application/json
  • Body is missing or malformed JSON
  • Validation fails

Body size limit (default 1 MB):

core.SetMaxBodySize(5 << 20) // 5 MB; set 0 to disable

Validation Rules

Tag Description
required Field must be present and non-zero
min=N Minimum length (string), value (number), or item count (slice/map)
max=N Maximum length (string), value (number), or item count (slice/map)
len=N Exact length (string, slice, array, map)
email Valid email format
url Valid HTTP/HTTPS URL
uuid Valid UUID format
oneof=a|b|c Value must be one of the listed options (string or int)
alpha Letters only
alphanum Letters and numbers only
numeric Digits only
lowercase Must be lowercase
uppercase Must be uppercase
contains=sub Must contain substring
startswith=pre Must start with prefix
endswith=suf Must end with suffix
regex=pattern Must match regex pattern
dive Validate each element of a slice/array

Nested structs are validated recursively with dot-separated field paths (e.g. address.city).

Path Parameters

// Supported types: string, int, int64, uint, uint64
id, err := core.Param[int64](r, "id")     // /users/{id}
name, err := core.Param[string](r, "slug") // /posts/{slug}

Returns ErrBadRequest if the parameter is missing or cannot be converted to the requested type.

Query Parameters

Single value:

page := core.BindQuery(r, "page")   // GET /users?page=2  →  "2"
q    := core.BindQuery(r, "q")      // returns "" if absent

Struct binding (with validation):

type ListQuery struct {
    Page  int      `query:"page"`
    Limit int      `query:"limit" validate:"max=100"`
    Sort  string   `query:"sort"  validate:"oneof=asc|desc"`
    Tags  []string `query:"tag"`
}

func (c *Controller) list(r *http.Request) (any, error) {
    q, err := core.BindQueryStruct[ListQuery](r)
    if err != nil {
        return nil, err
    }
    // q.Page, q.Limit, q.Sort, q.Tags are typed and validated
}

Supported types: string, int, int64, uint, uint64, float32, float64, bool, []string.

Headers

token  := core.BindHeader(r, "Authorization")
accept := core.BindHeader(r, "Accept")

File Uploads

Single File

func (c *Controller) upload(r *http.Request) (any, error) {
    f, err := core.BindFile(r, "avatar")
    if err \!= nil {
        return nil, err
    }
    // f.Filename    — sanitized base name (path components stripped)
    // f.ContentType — server-detected MIME type (not client-declared)
    // f.Size        — byte length
    // f.Content     — []byte file data
    // f.Header      — raw multipart.FileHeader for custom metadata
    return map[string]any{"name": f.Filename, "size": f.Size}, nil
}

Multiple Files

files, err := core.BindFiles(r, "images")
if err \!= nil {
    return nil, err
}
for _, f := range files {
    // process f.Content
}

Upload limits:

core.SetMaxUploadSize(64 << 20)    // total form size (default 32 MB)
core.SetMaxFileCount(10)           // max files per request (default 20)
core.SetMaxSingleFileSize(5 << 20) // max per file (default 10 MB)

Security note: Filename is sanitized server-side (path separators and null bytes removed). ContentType is detected from file content, not the client's declared value. Do not use Filename as a filesystem path without additional validation.