webutil

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 1, 2022 License: MIT Imports: 14 Imported by: 30

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

Constants

This section is empty.

Variables

This section is empty.

Functions

func BaseAddress

func BaseAddress(r *http.Request) string

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

func BasePath(path string) string

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 ErrFieldExists

func ErrFieldExists(field string) error

func ErrFieldRequired

func ErrFieldRequired(field string) error

func FlashFormWithErrors

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

func FormFields(sess *sessions.Session) map[string]string

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

func UnmarshalForm(f Form, r *http.Request) error

UnmarshalForm unmarshals the given request into the given form. This will return any unmarshalling errors for individual fields in a ValidationErrors type.

func UnmarshalFormWithFile

func UnmarshalFormWithFile(f Form, file *File, r *http.Request) error

UnmarshalFormWithFile will unmarshal a file from the given request, then it it will unmarshal the rest of the request data into the given form. If the file is sent as the request body itself, then the URL query parameters will be used to unmarshal the rest of the form data from.

func Validate

func Validate(v Validator) error

Validate will call Validate on the given Validator. If the given Validator fails, then the returned error will be of type ValidationErrors, otherwise it will be nil.

Types

type File

type File struct {
	multipart.File // The underlying file that was uploaded.

	// 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

	// Field is the form field to unmarshal the file from, if the file is being
	// uploaded as part of a "multipart/form-data" request.
	Field string
}

File is used for unmarshalling files from requests.

func (*File) Remove

func (f *File) Remove() error

Remove will remove the underlying file if it was written to disk during the upload. This will typically only be done if the file was too large to store in memory.

func (*File) UnmarshalRequest

func (f *File) UnmarshalRequest(r *http.Request) error

UnmarshalRequest will unmarshal a file from the given request. If the file was sent as the request body, then the header of the file will only be partially populated with the size of the file, and nothing else.

type FileValidator

type FileValidator struct {
	*File // The uploaded file.

	// Size is the maximum size of a file. Set to 0 for no limit.
	Size int64

	// Mimes is a list of MIME types to allow/disallow during uploading.
	Mimes []string

	// MimesAllowed delineates whether or not the above slice of MIME types
	// should be allowed/disallowed. Set to false to disallow, set to true to
	// allow.
	MimesAllowed bool
}

FileValidator is a Validator implementation for validating file uploads.

func (*FileValidator) HasFile

func (v *FileValidator) HasFile() bool

HasFile will check to see if a file has been uploaded.

func (*FileValidator) Validate

func (v *FileValidator) Validate(errs ValidationErrors)

Validate will check if a file has been validated, along with whether or not it is within the size limit, and of the allowed MIME types.

type Form

type Form interface {
	// Fields returns a map of all the form's underlying values.
	Fields() map[string]string
}

type FormUnmarshaler

type FormUnmarshaler struct {
	Form    Form            // The Form to decode the values to, must be a pointer.
	Decoder *schema.Decoder // The decoder to use for decoding form data.
}

FormUnmarshaler is used for unmarshalling forms from requests.

func (FormUnmarshaler) UnmarshalRequest

func (f FormUnmarshaler) UnmarshalRequest(r *http.Request) error

UnmarshalRequest will unmarshal the given request to the underlying form. If the request has the Content-Type header set to "application/json" then the request body is decoded as JSON.

type UnmarshalError

type UnmarshalError struct {
	Field string
	Err   error
}

func (UnmarshalError) Error

func (e UnmarshalError) Error() string

type ValidationErrors

type ValidationErrors map[string][]string

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 NewValidationErrors

func NewValidationErrors() ValidationErrors

NewValidationErrors returns an empty ValidationErrors.

func (ValidationErrors) Add

func (e ValidationErrors) Add(key string, err error)

Add adds the given error for the given key.

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(key string) string

First returns the first error for the given key if any.

func (ValidationErrors) Merge

func (e ValidationErrors) Merge(verrs ValidationErrors)

Merge merges the given set of errors into the current one.

type Validator

type Validator interface {
	// Validate performs validation on a set of data. Each error that occurs
	// should be added to the given set of errors.
	Validate(errs ValidationErrors)
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL