README ¶
webutil
webutil is a collection of utility functions to aid in the development of web applications in Go. this builds on top of some packages provided by the Gorilla web toolkit such as gorilla/schema and gorilla/sessions.
This package provides the ability to easily handle form validation, file uploads, serving different content types, and flashing of form data between requests.
Examples
Form Validation
Form validations is achieved via the webutil.Form
and webutil.Validator
interfaces. The webutil.Form
interface wraps the Fields
method that returns
a map of the underlying fields in the form. The webutil.Validator
interface
wraps the Validate
method for validating data. Below is an example of these
interfaces being implemented for form validation,
type LoginForm struct {
Email string
Password string
}
func (f LoginForm) Fields() map[string]string {
return map[string]string{
"email": f.Email,
}
}
type LoginValidator struct {
Form Login
}
func (v LoginValidator) Validate(errs webutil.ValidationErrors) error {
if f.Email == "" {
errs.Add("email", webutil.ErrFieldRequired("email"))
}
if f.Password == "" {
errs.Add("password", webutil.ErrFieldRequired("password"))
}
}
with the above implementation we can then use webutil.UnmarshalForm
and
webutil.Validate
to unmarshal and validate the form data,
func Login(w http.ResponseWriter, r *http.Request) {
var f LoginForm
if err := webutil.UnmarshalForm(&f, r); err != nil {
io.WriteString(w, err.Error())
return
}
v := LoginValidator{
Form: f,
}
if err := webutil.Validate(v); err != nil {
io.WriteString(w, err.Error())
return
}
}
webutil.Validate
will always return the webutil.ValidationErrors
error
type. Under the hood the gorilla/schema package is used to handle the
unmarshalling of request data into a form.
File Uploads
File uploads can be handled via the webutil.File
type. This can be used along
the webutil.FileValidator
to handle the uploading and validating of files,
type UploadForm struct {
File *webutil.File
Name string
}
func Upload(w http.ResponseWriter, r *http.Request) {
f := UploadForm{
File: &webutil.File{
Field: "avatar",
},
}
if err := webutil.UnmarshalFormWithFile(&f, f.File, r); err != nil {
io.WriteString(w, err.Error())
return
}
defer f.File.Remove()
v := &webutil.FileValidator{
File: f.File,
Size: 5 * (1 << 20),
}
if err := webutil.Validate(v); err != nil {
io.WriteString(w, err.Error())
return
}
dir, _ := os.Getwd()
dst, _ := os.CreateTemp(dir, "")
io.Copy(dst, f.File)
w.WriteHeader(http.StatusNoContent)
}
with the above example, we call the webutil.UnmarshalFormWithFile
function to
handle the unmarshalling of the file from the request. This will also handle
requests where the file is sent as the request body itself, when this is done
the URL query parameters are used as the typical form values. Validation of the
file is then handled with the webutil.FileValidator
.
Response Types
HTML, Text, and JSON response types can be sent using the respective functions
provided by this package. These functions will set the appropriate
Content-Type
header, and Content-Length
too.
func HTMLHandler(w http.ResponseWriter, r *http.Request) {
webutil.HTML(w, "<h1>HTML response</h1>", http.StatusOK)
}
func TextHandler(w http.ResponseWriter, r *http.Request) {
webutil.Text(w, "Text response", http.StatusOK)
}
func JSONHandler(w http.ResponseWriter, r *http.Request) {
data := map[string]string{
"message": "JSON response",
}
webutil.JSON(w, data, http.StatusOK)
}
Documentation ¶
Index ¶
- Variables
- func BaseAddress(r *http.Request) string
- func BasePath(path string) string
- func FieldRequired(ctx context.Context, val any) error
- func FlashFormWithErrors(sess *sessions.Session, f Form, errs ValidationErrors)
- func FormFields(sess *sessions.Session) map[string]string
- func HTML(w http.ResponseWriter, content string, status int)
- func JSON(w http.ResponseWriter, data interface{}, status int)
- func Text(w http.ResponseWriter, content string, status int)
- func UnmarshalForm(f Form, r *http.Request) error
- func UnmarshalFormAndValidate(f Form, r *http.Request) error
- func WrapFieldError(name string, err error) error
- type FieldError
- type File
- func UnmarshalFile(field string, r *http.Request) (*File, bool, error)
- func UnmarshalFiles(field string, r *http.Request) ([]*File, bool, error)
- func UnmarshalFormWithFile(f Form, field string, r *http.Request) (*File, bool, error)
- func UnmarshalFormWithFiles(f Form, field string, r *http.Request) ([]*File, bool, error)
- type Form
- type MatchError
- type ValidationErrors
- type Validator
- type ValidatorFunc
- type WrapErrorFunc
Constants ¶
This section is empty.
Variables ¶
var ( ErrFieldRequired = errors.New("field required") ErrFieldExists = errors.New("already exists") )
Functions ¶
func BaseAddress ¶
BaseAddress will return the HTTP address for the given Request. This will return the Scheme of the current Request (http, or https), concatenated with the host. If the X-Forwarded-Proto, and X-Forwarded-Host headers are present in the Request, then they will be used for the Scheme and Host respectively.
func BasePath ¶
BasePath returns the last element of the given path. This will split the path using the "/" spearator. If the path is empty BasePath returns "/".
func FieldRequired ¶ added in v2.2.0
FieldRequired checks to see if the given val was actually given. This only checks if val is a string, or has the String method on it, otherwise nil is returned.
func FlashFormWithErrors ¶ added in v2.1.0
func FlashFormWithErrors(sess *sessions.Session, f Form, errs ValidationErrors)
FlashFormWithErrors flashes the given Form and Errors to the given session under the "form_fields" and "form_errors" keys respectively.
func FormFields ¶
FormField returns the map of form fields that has been flashed to the given session under the "form_fields" key. If the key does not exist, then an empty map is returned instead.
func HTML ¶
func HTML(w http.ResponseWriter, content string, status int)
HTML sets the Content-Type of the given ResponseWriter to text/html, and writes the given content with the given status code to the writer. This will also set the Content-Length header to the len of content.
func JSON ¶
func JSON(w http.ResponseWriter, data interface{}, status int)
JSON sets the Content-Type of the given ResponseWriter to application/json, and encodes the given interface to JSON to the given writer, with the given status code. This will also set the Content-Length header to the len of the JSON encoded data.
func Text ¶
func Text(w http.ResponseWriter, content string, status int)
Text sets the Content-Type of the given ResponseWriter to text/plain, and writes the given content with the given status code to the writer. This will also se the Content-Length header to the len of content.
func UnmarshalForm ¶
UnmarshalForm parses the request into the given Form. If any errors occur during unmarshalling, then these will be returned via the ValidationErrors type.
func UnmarshalFormAndValidate ¶
UnmarshalFormAndValidate parses the request into the given Form. If unmmarshalling succeeds, then the Form is validated via the Validate method.
func WrapFieldError ¶ added in v2.2.0
WrapFieldError wraps the given error with the *FieldError type and returns it.
Types ¶
type FieldError ¶
FieldError captures an error and the field name that caused it.
func (*FieldError) Error ¶
func (e *FieldError) Error() string
func (*FieldError) Unwrap ¶
func (e *FieldError) Unwrap() error
Unwrap returns the underlying error.
type File ¶
type File struct { // The underlying file that was uploaded. multipart.File // Header is the header of the file being uploaded. Header *multipart.FileHeader // Type is the MIME type of the file, this is set during the unmarshalling // of the file by sniffing the first 512 bytes of the file. Type string }
File is used for unmarshalling files from requests.
func UnmarshalFile ¶
UnmarshalFile parses the request for a file sent with it. If the request has the Content-Type of multipart/form-data, then the file will be taken from the multipart form via the given field, otherwise it will be taken from the request body. A boolean is returned for whether or not a file was sent in the request.
func UnmarshalFiles ¶
UnmarshalFiles parses the request for every file sent with it. The request must have the Content-Type of multipart/form-data, otherwise an error is returned. A boolean is returned for whether or not any files were sent in the request.
func UnmarshalFormWithFile ¶
UnmarshalFormWithFile parses the request for a file sent with it. If the request has the Content-Type of multipart/form-data, then the file will be taken from the multipart form via the given field. This will then unmarshal the rest of the request data into the given Form. If file in the request was sent in the request body, then the URL query parameters are unmarshalled into the given Form. A boolean is returned for whether or not a file was a file in the request.
func UnmarshalFormWithFiles ¶
UnmarshalFormWithFiles parses the request for every file sent with it. The request must have the Content-Type of multipart/form-data, otherwise an error is returned. This will then unmarshal the rest of the request data into the given Form. A boolean is returned for whether or not any files were sent in the request.
type Form ¶
type Form interface { // Fields returns a map of all the form's underlying values. Fields() map[string]string // Validate validates the form. This should return an error type of // ValidationErrors should validation fail. Validate(ctx context.Context) error }
Form is the interface used for unmarhsalling and validating form data sent in an HTTP request.
type MatchError ¶ added in v2.2.0
func (MatchError) Error ¶ added in v2.2.0
func (e MatchError) Error() string
type ValidationErrors ¶
ValidationErrors records any validation errors that may have occurred. Each error is kept beneath the field for which the error occurred.
func FormErrors ¶
func FormErrors(sess *sessions.Session) ValidationErrors
FormErrors returns the Errors that has been flashed to the given session under the "form_errors" key. If the key does not exist, then an empty Errors is returned instead.
func (ValidationErrors) Add ¶
func (e ValidationErrors) Add(field string, err error)
Add adds the given error for the given field.
func (ValidationErrors) Err ¶
func (e ValidationErrors) Err() error
func (ValidationErrors) Error ¶
func (e ValidationErrors) Error() string
Error returns the string representation of the current set of errors. It will be formatted like so,
field: err err
func (ValidationErrors) First ¶
func (e ValidationErrors) First(field string) string
First returns the first error message for the given field if any.
type Validator ¶ added in v2.2.0
type Validator struct {
// contains filtered or unexported fields
}
Validator is the type used for validating data.
func (*Validator) Add ¶ added in v2.2.0
func (v *Validator) Add(name string, val any, fn ValidatorFunc)
Add will add a ValidatorFunc to the given Validator for the field of name and with the value of val.
func (*Validator) Validate ¶ added in v2.2.0
func (v *Validator) Validate(ctx context.Context) ValidationErrors
Validate runs the validatio functions and returns all errors via ValidationErrors. When calling this, a subsequent call to Err should be made on the returned ValidationErrors, this will either return an error or nil depending on whether or not ValidationErrors contains errors.
func (*Validator) WrapError ¶ added in v2.2.0
func (v *Validator) WrapError(wraps ...WrapErrorFunc)
WrapError sets the chain of WrapErrorFuncs to use when processing a validation error.
type ValidatorFunc ¶ added in v2.2.0
ValidatorFunc is the function type for validating a value in a form. This will return an error should validation fail.
func FieldEquals ¶ added in v2.2.0
func FieldEquals(expected any) ValidatorFunc
FieldEquals checks to see if the given val matches expected.
func FieldLen ¶ added in v2.2.0
func FieldLen(min, max int) ValidatorFunc
FieldLen checks to see if the given val is between the length of min and max.
func FieldMatches ¶ added in v2.2.0
func FieldMatches(re *regexp.Regexp) ValidatorFunc
FieldMatches checks to see if the given val matches the regular expression of re. This will return an error of type MatchError if validation fails.
func FieldMaxLen ¶ added in v2.2.0
func FieldMaxLen(max int) ValidatorFunc
FieldMaxLen checks to see if the given val is at least shorter than max.
func FieldMinLen ¶ added in v2.2.0
func FieldMinLen(min int) ValidatorFunc
FieldMinLen checks to see if the given val is at least longer than min.
type WrapErrorFunc ¶ added in v2.2.0
WrapErrorFunc is the function type for wrapping an error that is returned from a failed validation. This would be given the name of the field and the error for that failed validation. This would be used for either adding additional context to an error, or mutating it.
func IgnoreError ¶ added in v2.2.0
func IgnoreError(name string, target error) WrapErrorFunc
IgnoreError will return nil if the underlying validation error and field name match what is given as name and target. This is useful if there are benign errors you want to ignore during validation.
func MapError ¶ added in v2.2.0
func MapError(from, to error) WrapErrorFunc
MapError will map the given error from to the given error of to if the underlying error is of the type from. The underlying check is done via errors.Is.