Popularity
7.3
Stable
Activity
0.0
Stable
791
32
82

Programming language: Go
License: MIT License
Tags: Forms    
Latest version: v0.3.0

binding alternatives and similar packages

Based on the "Forms" category.
Alternatively, view binding alternatives based on common mentions on social networks and blogs.

  • nosurf

    CSRF protection middleware for Go.
  • gorilla/csrf

    DISCONTINUED. gorilla/csrf provides Cross Site Request Forgery (CSRF) prevention middleware for Go web applications & services 🔒
  • Get real-time insights from all types of time series data with InfluxDB. Ingest, query, and analyze billions of data points in real-time with unbounded cardinality.
    Promo www.influxdata.com
    InfluxDB Logo
  • form

    :steam_locomotive: Decodes url.Values into Go value(s) and Encodes Go value(s) into url.Values. Dual Array and Full map support.
  • conform

    Trims, sanitizes & scrubs data based on struct tags (go, golang)
  • httpin

    🍡 HTTP Input for Go - HTTP Request from/to Go Struct (Data Binding between Go Struct and http.Request)
  • formam

    a package for decode form's values into struct in Go
  • forms

    A lightweight go library for parsing form data or json from an http.Request.
  • qs

    Go module for encoding structs into URL query parameters
  • bind

    Bind form data to any Go values
  • queryparam

    Go package to easily convert a URL's query parameters/values into usable struct values of the correct types.
  • checker

    Checker is a Go library for validating user input through checker rules provided in struct tags.
  • gbind

    Bind data to any Go value. Can use built-in and custom expression binding capabilities; supports data validation logic for Go values. // 将数据绑定到任何 Go 值。可使用内置和自定义表达式绑定能力;支持对Go值的数据校验逻辑.

Do you think we are missing an alternative of binding or a related project?

Add another 'Forms' Package

README

GoDoc

binding

Reflectionless data binding for Go's net/http

Features

  • HTTP request data binding
  • Data validation (custom and built-in)
  • Error handling

Benefits

  • Moves data binding, validation, and error handling out of your application's handler
  • Reads Content-Type to deserialize form, multipart form, and JSON data from requests
  • No middleware: just a function call
  • Usable in any setting where net/http is present (Negroni, gocraft/web, std lib, etc.)
  • No reflection

Usage example

package main

import (
    "fmt"
    "net/http"

    "github.com/mholt/binding"
)

// First define a type to hold the data
// (If the data comes from JSON, see: http://mholt.github.io/json-to-go)
type ContactForm struct {
    User struct {
        ID int
    }
    Email   string
    Message string
}

// Then provide a field mapping (pointer receiver is vital)
func (cf *ContactForm) FieldMap(req *http.Request) binding.FieldMap {
    return binding.FieldMap{
        &cf.User.ID: "user_id",
        &cf.Email:   "email",
        &cf.Message: binding.Field{
            Form:     "message",
            Required: true,
        },
    }
}

// Now your handlers can stay clean and simple
func handler(resp http.ResponseWriter, req *http.Request) {
    contactForm := new(ContactForm)
    if errs := binding.Bind(req, contactForm); errs != nil {
        http.Error(resp, errs.Error(), http.StatusBadRequest)
        return
    }
    fmt.Fprintf(resp, "From:    %d\n", contactForm.User.ID)
    fmt.Fprintf(resp, "Message: %s\n", contactForm.Message)
}

func main() {
    http.HandleFunc("/contact", handler)
    http.ListenAndServe(":3000", nil)
}

Multipart/form-data usage example

package main

import (
    "bytes"
    "fmt"
    "github.com/mholt/binding"
    "io"
    "log"
    "mime/multipart"
    "net/http"
)

// We expect a multipart/form-data upload with
// a file field named 'data'
type MultipartForm struct {
    Data *multipart.FileHeader `json:"data"`
}

func (f *MultipartForm) FieldMap(req *http.Request) binding.FieldMap {
    return binding.FieldMap{
        &f.Data: "data",
    }
}

// Handlers are still clean and simple
func handler(resp http.ResponseWriter, req *http.Request) {
    multipartForm := new(MultipartForm)
    if errs := binding.Bind(req, multipartForm); errs != nil {
        http.Error(resp, errs.Error(), http.StatusBadRequest)
        return
    }

    // To access the file data you need to Open the file
    // handler and read the bytes out.
    var fh io.ReadCloser
    var err error
    if fh, err = multipartForm.Data.Open(); err != nil {
        http.Error(resp,
            fmt.Sprint("Error opening Mime::Data %v", err),
            http.StatusInternalServerError)
        return
    }
    defer fh.Close()
    dataBytes := bytes.Buffer{}
    var size int64
    if size, err = dataBytes.ReadFrom(fh); err != nil {
        http.Error(resp,
            fmt.Sprint("Error reading Mime::Data %v", err),
            http.StatusInternalServerError)
        return
    }
    // Now you have the attachment in databytes.
    // Maximum size is default is 10MB.
    log.Printf("Read %v bytes with filename %s",
        size, multipartForm.Data.Filename)
}

func main() {
    http.HandleFunc("/upload", handler)
    http.ListenAndServe(":3000", nil)
}

You can test from CLI using the excellent httpie client

http -f POST localhost:3000/upload data@myupload

Custom data validation

You may optionally have your type implement the binding.Validator interface to perform your own data validation. The .Validate() method is called after the struct is populated.

func (cf ContactForm) Validate(req *http.Request) error {
    if cf.Message == "Go needs generics" {
        return binding.Errors{
            binding.NewError([]string{"message"}, "ComplaintError", "Go has generics. They're called interfaces.")
        }
    }
    return nil
}

Binding custom types

For types you've defined, you can bind form data to it by implementing the Binder interface. Here's a contrived example:

type MyBinder map[string]string

func (t MyBinder) Bind(fieldName string, strVals []string) error {
    t["formData"] = strVals[0]
    return nil
}

If you can't add a method to the type, you can still specify a Binder func in the field spec. Here's a contrived example that binds an integer (not necessary, but you get the idea):

func (t *MyType) FieldMap(req *http.Request) binding.FieldMap {
    return binding.FieldMap{
        "a-key": binding.Field{
            Form: "number",
            Binder: func(fieldName string, formVals []string) error {
                val, err := strconv.Atoi(formVals[0])
                if err != nil {
                    return binding.Errors{binding.NewError([]string{fieldName}, binding.DeserializationError, err.Error())}
                }
                t.SomeNumber = val
                return nil
            },
        },
    }
}

The Errors type has a convenience method, Add, which you can use to append to the slice if you prefer.

Supported types (forms)

The following types are supported in form deserialization by default. (JSON requests are delegated to encoding/json.)

  • uint, *uint, []uint, uint8, *uint8, []uint8, uint16, *uint16, []uint16, uint32, *uint32, []uint32, uint64, *uint64, []uint64
  • int, *int, []int, int8, *int8, []int8, int16, *int16, []int16, int32, *int32, []int32, int64, *int64, []int64
  • float32, *float32, []float32, float64, *float64, []float64
  • bool, *bool, []bool
  • string, *string, []string
  • time.Time, *time.Time, []time.Time
  • *multipart.FileHeader, []*multipart.FileHeader