README

Forms

GoDoc

Forms is a lightweight, but incredibly useful go library for parsing form data from an http.Request. It supports multipart forms, url-encoded forms, json data, and url query parameters. It also provides helper methods for converting data into other types and a Validator object which can be used to validate the data. Forms is framework-agnostic and works directly with the http package.

Version 0.3.2

Development Status

Forms is being actively developed and is well-tested. However, since it is still a young library, it is not recommended for use in mission-critical production applications at this time. It is probably fine to use for low-traffic hobby sites, and in fact we encourage its use in those settings to help polish the API and find missing features and hidden bugs. Pull requests and issue reports are much appreciated :)

Forms follows semantic versioning but offers no guarantees of backwards compatibility until version 1.0. Keep in mind that breaking changes might occur. We will do our best to make the community aware of any non-trivial breaking changes beforehand. We recommend using a dependency vendoring tool such as godep to ensure that breaking changes will not break your application.

Installation

Install like you would any other package:

go get github.com/albrow/forms

Then include the package in your import statements:

import "github.com/albrow/forms"

Example Usage

Meant to be used inside the body of an http.HandlerFunc or any function that has access to an http.Request.

func CreateUserHandler(res http.ResponseWriter, req *http.Request) {
	// Parse request data.
	userData, err := forms.Parse(req)
	if err != nil {
		// Handle err
		// ...
	}

	// Validate
	val := userData.Validator()
	val.Require("username")
	val.LengthRange("username", 4, 16)
	val.Require("email")
	val.MatchEmail("email")
	val.Require("password")
	val.MinLength("password", 8)
	val.Require("confirmPassword")
	val.Equal("password", "confirmPassword")
	val.RequireFile("profileImage")
	val.AcceptFileExts("profileImage", "jpg", "png", "gif")
	if val.HasErrors() {
		// Write the errors to the response
		// Maybe this means formatting the errors as json
		// or re-rendering the form with an error message
		// ...
	}

	// Use data to create a user object
	user := &models.User {
		Username: userData.Get("username"),
		Email: userData.Get("email"),
		HashedPassword: hash(userData.Get("password")),
	}

	// Continue by saving the user to the database and writing
	// to the response
	// ...


	// Get the contents of the profileImage file
	imageBytes, err := userData.GetFileBytes("profileImage")
	if err != nil {
	  // Handle err
	}
	// Now you can either copy the file over to your server using io.Copy,
	// upload the file to something like amazon S3, or do whatever you want
	// with it.
}

Contributing

See CONTRIBUTING.md

License

Forms is licensed under the MIT License. See the LICENSE file for more information.

Expand ▾ Collapse ▴

Documentation

Overview

    package forms is a lightweight, but incredibly useful library for parsing form data from an http.Request. It supports multipart forms, url-encoded forms, json data, and url query parameters. It also provides helper methods for converting data into other types and a Validator object which can be used to validate the data. Forms is framework-agnostic and works directly with the http package.

    For the full source code, example usage, and more, visit https://github.com/albrow/forms.

    Version 0.3.2

    Index

    Examples

    Constants

    This section is empty.

    Variables

    This section is empty.

    Functions

    This section is empty.

    Types

    type Data

    type Data struct {
    	// Values holds any basic key-value string data
    	// This includes all fields from a json body or
    	// urlencoded form, and the form fields only (not
    	// files) from a multipart form
    	Values url.Values
    	// Files holds files from a multipart form only.
    	// For any other type of request, it will always
    	// be empty. Files only supports one file per key,
    	// since this is by far the most common use. If you
    	// need to have more than one file per key, parse the
    	// files manually using req.MultipartForm.File.
    	Files map[string]*multipart.FileHeader
    	// contains filtered or unexported fields
    }

      Data holds data obtained from the request body and url query parameters. Because Data is built from multiple sources, sometimes there will be more than one value for a given key. You can use Get, Set, Add, and Del to access the first element for a given key or access the Values and Files properties directly to access additional elements for a given key. You can also use helper methods to convert the first value for a given key to a different type (e.g. bool or int).

      func CreateFromMap

      func CreateFromMap(m map[string]string) *Data

        CreateFromMap returns a Data object with keys and values matching the map.

        func Parse

        func Parse(req *http.Request) (*Data, error)

          Parse parses the request body and url query parameters into Data. The content in the body of the request has a higher priority, will be added to Data first, and will be the result of any operation which gets the first element for a given key (e.g. Get, GetInt, or GetBool).

          Example
          Output:
          
          Bob is 25 years old and not yet retired.
          

          func (*Data) Add

          func (d *Data) Add(key string, value string)

            Add adds the value to key. It appends to any existing values associated with key.

            func (*Data) AddFile

            func (d *Data) AddFile(key string, file *multipart.FileHeader)

              AddFile adds the multipart form file to data with the given key.

              func (Data) BindJSON

              func (d Data) BindJSON(v interface{}) error

                BindJSON binds v to the json data in the request body. It calls json.Unmarshal and sets the value of v.

                func (*Data) Del

                func (d *Data) Del(key string)

                  Del deletes the values associated with key.

                  func (*Data) DelFile

                  func (d *Data) DelFile(key string)

                    DelFile deletes the file associated with key (if any). If there is no file associated with key, it does nothing.

                    func (*Data) Encode

                    func (d *Data) Encode() string

                      Encode encodes the values into “URL encoded” form ("bar=baz&foo=quux") sorted by key. Any files in d will be ignored because there is no direct way to convert a file to a URL encoded value.

                      func (Data) FileExists

                      func (d Data) FileExists(key string) bool

                        FileExists returns true iff data.Files[key] exists. When parsing a request body, the key is considered to be in existence if it was provided in the request body, even if the file is empty.

                        func (Data) Get

                        func (d Data) Get(key string) string

                          Get gets the first value associated with the given key. If there are no values associated with the key, Get returns the empty string. To access multiple values, use the map directly.

                          func (Data) GetAndUnmarshalJSON

                          func (d Data) GetAndUnmarshalJSON(key string, v interface{}) error

                            GetAndUnmarshalJSON assumes that the first element in data[key] is a json string and attempts to unmarshal it into v. If unmarshaling was not successful, returns an error. v should be a pointer to some data structure.

                            func (Data) GetBool

                            func (d Data) GetBool(key string) bool

                              GetBool returns the first element in data[key] converted to a bool.

                              func (Data) GetBytes

                              func (d Data) GetBytes(key string) []byte

                                GetBytes returns the first element in data[key] converted to a slice of bytes.

                                func (Data) GetFile

                                func (d Data) GetFile(key string) *multipart.FileHeader

                                  GetFile returns the multipart form file associated with key, if any, as a *multipart.FileHeader. If there is no file associated with key, it returns nil. If you just want the body of the file, use GetFileBytes.

                                  func (Data) GetFileBytes

                                  func (d Data) GetFileBytes(key string) ([]byte, error)

                                    GetFileBytes returns the body of the file associated with key. If there is no file associated with key, it returns nil (not an error). It may return an error if there was a problem reading the file. If you need to know whether or not the file exists (i.e. whether it was provided in the request), use the FileExists method.

                                    func (Data) GetFloat

                                    func (d Data) GetFloat(key string) float64

                                      GetFloat returns the first element in data[key] converted to a float.

                                      func (Data) GetInt

                                      func (d Data) GetInt(key string) int

                                        GetInt returns the first element in data[key] converted to an int.

                                        func (Data) GetMapFromJSON

                                        func (d Data) GetMapFromJSON(key string) (map[string]interface{}, error)

                                          GetMapFromJSON assumes that the first element in data[key] is a json string, attempts to unmarshal it into a map[string]interface{}, and if successful, returns the result. If unmarshaling was not successful, returns an error.

                                          func (Data) GetSliceFromJSON

                                          func (d Data) GetSliceFromJSON(key string) ([]interface{}, error)

                                            GetSliceFromJSON assumes that the first element in data[key] is a json string, attempts to unmarshal it into a []interface{}, and if successful, returns the result. If unmarshaling was not successful, returns an error.

                                            func (Data) GetStringsSplit

                                            func (d Data) GetStringsSplit(key string, delim string) []string

                                              GetStringsSplit returns the first element in data[key] split into a slice delimited by delim.

                                              func (Data) KeyExists

                                              func (d Data) KeyExists(key string) bool

                                                KeyExists returns true iff data.Values[key] exists. When parsing a request body, the key is considered to be in existence if it was provided in the request body, even if its value is empty.

                                                func (*Data) Set

                                                func (d *Data) Set(key string, value string)

                                                  Set sets the key to value. It replaces any existing values.

                                                  func (*Data) Validator

                                                  func (d *Data) Validator() *Validator

                                                    Validator returns a Validator which can be used to easily validate data.

                                                    type ValidationResult

                                                    type ValidationResult struct {
                                                    	Ok bool
                                                    	// contains filtered or unexported fields
                                                    }

                                                      ValidationResult is returned from every validation method and can be used to override the default field name or error message. If you want to use the default fields and messages, simply discard the ValidationResult.

                                                      func (*ValidationResult) Field

                                                      func (vr *ValidationResult) Field(field string) *ValidationResult

                                                        Field changes the field name associated with the validation result.

                                                        func (*ValidationResult) Message

                                                        func (vr *ValidationResult) Message(msg string) *ValidationResult

                                                          Message changes the error message associated with the validation result. msg should typically be a user-readable sentence, such as "username is required."

                                                          type Validator

                                                          type Validator struct {
                                                          	// contains filtered or unexported fields
                                                          }

                                                            Validator has methods for validating its underlying Data. A Validator stores any errors that occurred during validation, and they can be accessed directly. In a typical workflow, you will create a Validator from some Data, call some methods on that validator (e.g. Require), check if the validator has errors, then do something with the errors if it does.

                                                            Example
                                                            Output:
                                                            
                                                            []string{"name must be at least 4 characters long.", "Must specify whether or not person is retired."}
                                                            

                                                            func (*Validator) AcceptFileExts

                                                            func (v *Validator) AcceptFileExts(field string, exts ...string) *ValidationResult

                                                              AcceptFileExts will add an error to the Validator if the extension of the file identified by field is not in exts. exts should be one ore more allowed file extensions, not including the preceding ".". If the file does not exist, it does not add an error to the Validator.

                                                              func (*Validator) AddError

                                                              func (v *Validator) AddError(field string, msg string) *ValidationResult

                                                                AddError adds an error associated with field to the validator. msg should typically be a user-readable sentence, such as "username is required."

                                                                func (*Validator) Equal

                                                                func (v *Validator) Equal(field1 string, field2 string) *ValidationResult

                                                                  Equal will add an error to the Validator if data[field1] is not equal to data[field2].

                                                                  func (*Validator) ErrorMap

                                                                  func (v *Validator) ErrorMap() map[string][]string

                                                                    ErrorMap reutrns all the fields and error messages for the validator in the form of a map. The keys of the map are field names, and the values are any error messages associated with that field name.

                                                                    func (*Validator) Fields

                                                                    func (v *Validator) Fields() []string

                                                                      Fields returns the fields for all validation results for the Validator, in order.

                                                                      func (*Validator) Greater

                                                                      func (v *Validator) Greater(field string, value float64) *ValidationResult

                                                                        Greater will add an error to the Validator if the first element of data.Values[field] is not greater than value or if the first element of data.Values[field] cannot be converted to a number.

                                                                        func (*Validator) GreaterOrEqual

                                                                        func (v *Validator) GreaterOrEqual(field string, value float64) *ValidationResult

                                                                          GreaterOrEqual will add an error to the Validator if the first element of data.Values[field] is not greater than or equal to value or if the first element of data.Values[field] cannot be converted to a number.

                                                                          func (*Validator) HasErrors

                                                                          func (v *Validator) HasErrors() bool

                                                                            HasErrors returns true iff the Validator has errors, i.e. if any validation methods called on the Validator failed.

                                                                            func (*Validator) LengthRange

                                                                            func (v *Validator) LengthRange(field string, min int, max int) *ValidationResult

                                                                              LengthRange will add an error to the Validator if data.Values[field] is shorter than min (if data.Values[field] has less than min characters) or if data.Values[field] is longer than max (if data.Values[field] has more than max characters), not counting leading or trailing whitespace.

                                                                              func (*Validator) Less

                                                                              func (v *Validator) Less(field string, value float64) *ValidationResult

                                                                                Less will add an error to the Validator if the first element of data.Values[field] is not less than value or if the first element of data.Values[field] cannot be converted to a number.

                                                                                func (*Validator) LessOrEqual

                                                                                func (v *Validator) LessOrEqual(field string, value float64) *ValidationResult

                                                                                  LessOrEqual will add an error to the Validator if the first element of data.Values[field] is not less than or equal to value or if the first element of data.Values[field] cannot be converted to a number.

                                                                                  func (*Validator) Match

                                                                                  func (v *Validator) Match(field string, regex *regexp.Regexp) *ValidationResult

                                                                                    Match will add an error to the Validator if data.Values[field] does not match the regular expression regex.

                                                                                    func (*Validator) MatchEmail

                                                                                    func (v *Validator) MatchEmail(field string) *ValidationResult

                                                                                      MatchEmail will add an error to the Validator if data.Values[field] does not match the formatting expected of an email.

                                                                                      func (*Validator) MaxLength

                                                                                      func (v *Validator) MaxLength(field string, length int) *ValidationResult

                                                                                        MaxLength will add an error to the Validator if data.Values[field] is longer than length (if data.Values[field] has more than length characters), not counting leading or trailing whitespace.

                                                                                        func (*Validator) Messages

                                                                                        func (v *Validator) Messages() []string

                                                                                          Messages returns the messages for all validation results for the Validator, in order.

                                                                                          func (*Validator) MinLength

                                                                                          func (v *Validator) MinLength(field string, length int) *ValidationResult

                                                                                            MinLength will add an error to the Validator if data.Values[field] is shorter than length (if data.Values[field] has less than length characters), not counting leading or trailing whitespace.

                                                                                            func (*Validator) Require

                                                                                            func (v *Validator) Require(field string) *ValidationResult

                                                                                              Require will add an error to the Validator if data.Values[field] does not exist, is an empty string, or consists of only whitespace.

                                                                                              func (*Validator) RequireFile

                                                                                              func (v *Validator) RequireFile(field string) *ValidationResult

                                                                                                RequireFile will add an error to the Validator if data.Files[field] does not exist or is an empty file

                                                                                                func (*Validator) TypeBool

                                                                                                func (v *Validator) TypeBool(field string) *ValidationResult

                                                                                                  TypeBool will add an error to the Validator if the first element of data.Values[field] cannot be converted to a bool.

                                                                                                  func (*Validator) TypeFloat

                                                                                                  func (v *Validator) TypeFloat(field string) *ValidationResult

                                                                                                    TypeFloat will add an error to the Validator if the first element of data.Values[field] cannot be converted to an float64.

                                                                                                    func (*Validator) TypeInt

                                                                                                    func (v *Validator) TypeInt(field string) *ValidationResult

                                                                                                      TypeInt will add an error to the Validator if the first element of data.Values[field] cannot be converted to an int.