vhttp

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Aug 12, 2022 License: MIT Imports: 11 Imported by: 0

README

vhttp

Go Test Go Reference GitHub go.mod Go version

created by Austin Poor

A library for validating HTTP requests and responses from the net/http package.

Quick Example

The following is a quick example testing that req (of type *http.Request)...

  1. Is a "GET" request
  2. Calling json.Valid() on the body returns true
  3. Has the header "Content-Type" and it's equal to "application/json"
  4. The header "Authorization" matches the regular expression ^Bearer .+$
  5. Has the URL path "/users/all"
err := vhttp.ValidateRequest(req, 
    vhttp.MethodIsGet(),                      // #1
    vhttp.BodyIsValidJSON(),                  // #2
    vhttp.HeaderContentTypeJSON(),            // #3
    vhttp.HeaderAuthorizationMatchesBearer(), // #4
    vhttp.URLPathIs("/users/all"),            // #5
)

Read more and find more examples in the go docs!

License

vhttp is released under an MIT license.

Contributing

Contributions are welcome!

Please feel free to submit an issue or a PR. Or you can reach out to me on twitter.

To-Do

  • Add more tests!
  • Add more examples!
  • Form validators
  • Check for nil pointers? (eg *url.URL)

Documentation

Overview

Package vhttp contains helper functions for testing aspects of http.Request or http.Response objects from the net/http package.

The core functions used are ValidateRequest and ValidateResponse whose arguments (in addition to the http.Request or http.Response) implement the RequestValidator ResponseValidator interfaces, respectively.

This package also includes helper types for validating specific aspects of the requests or responses, such as the MethodValidator, HeaderValidator, or the BodyValidator.

Some helper functions exist for creating validator functions but others can be created manually.

Index

Examples

Constants

View Source
const (
	HeaderContentType   = "Content-Type"
	HeaderAccept        = "Accept"
	HeaderHost          = "Host"
	HeaderAuthorization = "Authorization"
	HeaderConnection    = "Connection"
)

Common headers, used for convenience

View Source
const (
	MimePlain          = "text/plain"
	MimeHTML           = "text/html"
	MimeCSS            = "text/css"
	MimeTextJavascript = "text/javascript"

	MimeJSON = "application/json"
	MimeXML  = "application/xml"

	MimeImageAPNG   = "image/apng"
	MimeImageAVIF   = "image/avif"
	MimeImageGIF    = "image/gif"
	MimeImageJPEG   = "image/jpeg"
	MimeImagePNG    = "image/png"
	MimeImageSVGXML = "image/svg+xml"
	MimeImageWEBP   = "image/webp"
)

Common Content-Type / MIME type values

Variables

View Source
var (
	BasicAuthMatch  = regexp.MustCompile(`^Basic .+$`)
	BearerAuthMatch = regexp.MustCompile(`^Bearer .+$`)
)

Regular expressions for matching against (simplified) Authentication HTTP headers.

View Source
var CanonicalHeaderKey func(string) string = http.CanonicalHeaderKey

CanonicallHeaderKey converts the given string to a canonical form.

This function is used in Header validation function, on the keys of the HeaderValidators parameter. By copying the function from the net/http package, this can be replaced with a custom implementation, if that functionality needs to be changed.

Functions

func InternalErr

func InternalErr(err error) error

InternalErr creates a new InternalError

func ValidateRequest

func ValidateRequest(req *http.Request, vs ...RequestValidator) error

ValidateRequest validates the request against the given validators.

Example
package main

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
	"net/url"

	"github.com/a-poor/vhttp"
)

func asReadCloser(b []byte) io.ReadCloser {
	return io.NopCloser(bytes.NewReader(b))
}

func main() {
	// Create a sample request...
	u, _ := url.Parse("https://example.com/api/v1/users")
	req := &http.Request{
		Method: http.MethodPost,
		Header: http.Header{
			"Content-Type":  []string{"application/json"},
			"Authorization": []string{"Basic abcde12345"},
		},
		Body: asReadCloser([]byte(`{{{{`)),
		URL:  u,
	}

	// Validate the request...
	err := vhttp.ValidateRequest(req,
		// Is a "GET" request
		vhttp.MethodIsGet(),

		// Calling json.Valid() on the body returns true
		vhttp.BodyIsValidJSON(),

		// Has the header "Content-Type" and it's equal to "application/json"
		vhttp.HeaderContentTypeJSON(),

		// The header "Authorization" matches the regular expression ^Bearer .+$
		vhttp.HeaderAuthorizationMatchesBearer(),

		// Has the URL path "/api/v2/posts"
		vhttp.URLPathIs("/api/v2/posts"),
	)

	// Print the output...
	fmt.Println(err)
}
Output:

4 errors occurred:
	* expected method "GET", found "POST"
	* body is not valid JSON
	* expected header "Authorization" to match "^Bearer .+$"
	* expected URL path "/api/v2/posts", found "/api/v1/users"

func ValidateResponse

func ValidateResponse(res *http.Response, vs ...ResponseValidator) error

ValidateResponse validates the response against the given validators.

Types

type BodyValidator

type BodyValidator func(b []byte) error

BodyValidator is a validator that validates an http.Request's body.

Note that this expects the body to be fully read as a byte slice. If more than one BodyValidator is being used, you should use a CachedBodyValidator instead – which will read the body once and pass the resulting byte slice to all of the BodyValidators.

func BodyDetectedTypeIs

func BodyDetectedTypeIs(t string) BodyValidator

BodyDetectedTypeIs uses the http.DetectContentType function to guess the content type of the body and returns an error if it does not match the expected type t.

func BodyIs

func BodyIs(b []byte) BodyValidator

BodyIs validates that the body is equal to the given byte slice.

func BodyIsNil

func BodyIsNil() BodyValidator

BodyIsNil validates that the body is nil.

func BodyIsString

func BodyIsString(s string) BodyValidator

BodyIsString validates that the body is equal to the given string.

func BodyIsValidJSON

func BodyIsValidJSON() BodyValidator

BodyIsValidJSON uses the json.Valid function (from the encoding/json) to test if the body is valid JSON.

func BodyJSONUnmarshalsAs

func BodyJSONUnmarshalsAs(v any) BodyValidator

BodyJSONUnmarshalsAs attmepts to uses the json.Unmarshal function to unmarshal the body. If it fails, an error is returned.

func BodyLengthIs

func BodyLengthIs(n int) BodyValidator

BodyLengthIs validates that the body has the given length n.

func BodyXMLUnmarshalsAs

func BodyXMLUnmarshalsAs(v any) BodyValidator

BodyXMLUnmarshalsAs attmepts to uses the xml.Unmarshal function to unmarshal the body. If it fails, an error is returned.

func (BodyValidator) ValidateRequest

func (v BodyValidator) ValidateRequest(req *http.Request) error

func (BodyValidator) ValidateResponse

func (v BodyValidator) ValidateResponse(res *http.Response) error

type CachedBodyValidator

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

CachedBodyValidator is a RequestValidator/ResponseValidator that reads the Request or Response body once and passes the byte slice to each of it's BodyValidators (rather than calling their ValidateRequest or ValidateResponse methods each time).

This helps avoid duplicated reads of the body and prevents issues with attemps to read the body after it has been closed.

func CacheBody

func CacheBody(vs ...BodyValidator) CachedBodyValidator

CacheBody creates a new CachedBodyValidator

func (CachedBodyValidator) ValidateRequest

func (v CachedBodyValidator) ValidateRequest(req *http.Request) error

func (CachedBodyValidator) ValidateResponse

func (v CachedBodyValidator) ValidateResponse(res *http.Response) error

type HeaderValidator

type HeaderValidator func(http.Header) error

HeaderValidator is a validator that validates an http.Request or http.Response object's headers.

func HasHeader

func HasHeader(h string) HeaderValidator

HasHeader creates a request validator that checks that the header h is present in the request object.

Note that this function will convert the header key to canonical form using the vhttp.CanonicalHeaderKey function. If this behavior needs to be changed, either create a custom validator or change the value of the function.

func HasHeaderAccept

func HasHeaderAccept() HeaderValidator

HasHeaderAccept creates a request validator that checks that the header "Accept" is present in the request object.

func HasHeaderAuthorization

func HasHeaderAuthorization() HeaderValidator

HasHeaderAuthorization creates a request validator that checks that the "Authorization" header is present in the request object.

func HasHeaderContentType

func HasHeaderContentType(ct string) HeaderValidator

HasHeaderContentType creates a request validator that checks that the "Content-Type" header is present in the request object.

func HeaderAuthorizationIs

func HeaderAuthorizationIs(t string) HeaderValidator

HeaderAuthorizationIs creates a request validator that checks that at least one of the "Authorization" header values are equal to t.

func HeaderAuthorizationMatchesBasic

func HeaderAuthorizationMatchesBasic() HeaderValidator

HeaderAuthorizationMatchesBasic creates a request validator that checks that the request header value for the Authorization header matches the regular expression for a basic authentication header.

The regular expression is defined in the variable vhttp.BasicAuthMatch as `^Basic .+`.

func HeaderAuthorizationMatchesBearer

func HeaderAuthorizationMatchesBearer() HeaderValidator

HeaderAuthorizationMatchesBearer creates a request validator that checks that the request header value for the Authorization header matches the regular expression for a bearer authentication token.

The regular expression is defined in the variable vhttp.BearerAuthMatch as `^Bearer .+`.

func HeaderContentTypeIs

func HeaderContentTypeIs(ct string) HeaderValidator

HeaderContentTypeIs creates a request validator that checks that at least one of the "Content-Type" header values are equal to t.

func HeaderContentTypeJSON

func HeaderContentTypeJSON() HeaderValidator

HeaderContentTypeJSON creates a request validator that checks that at least one of the "Content-Type" header values are equal to "application/json".

func HeaderContentTypeXML

func HeaderContentTypeXML() HeaderValidator

HeaderContentTypeXML creates a request validator that checks that at least one of the "Content-Type" header values are equal to "application/xml".

func HeaderIs

func HeaderIs(h, v string) HeaderValidator

HeaderIs creates a request validator that checks that at least one of the values for header h is equal to v.

Note that this function will convert the header key to canonical form using the vhttp.CanonicalHeaderKey function. If this behavior needs to be changed, either create a custom validator or change the value of the function.

func HeaderMatches

func HeaderMatches(h string, re *regexp.Regexp) HeaderValidator

HeaderMatches creates a request validator that checks that at least one of the request header values matche the given regular expression.

Note that this function will convert the header key to canonical form using the vhttp.CanonicalHeaderKey function. If this behavior needs to be changed, either create a custom validator or change the value of the function.

func (HeaderValidator) ValidateRequest

func (v HeaderValidator) ValidateRequest(req *http.Request) error

func (HeaderValidator) ValidateResponse

func (v HeaderValidator) ValidateResponse(res *http.Response) error

type InternalError

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

InternalError is used to signal that an error returned from a validator is not a validation error but an internal error.

An InternalError is meant to wrap a real error returned in the process of validating a request or response.

func (InternalError) Error

func (e InternalError) Error() string

func (InternalError) Unwrap

func (e InternalError) Unwrap() error

func (InternalError) Wrap

func (e InternalError) Wrap(msg string) error

Wrap returns a new InternalError where the underlying error is the result of wrapping e's underlying error (using fmt.Errorf) with the message msg prepended to the error message chain.

Equivalent to:

err := vhttp.InternalErr(fmt.Errorf("%s: %w", msg, ierr.Unwrap()))

type MethodValidator

type MethodValidator func(string) error

MethodValidator is a validator that validates an http.Request's method.

func MethodIs

func MethodIs(s string) MethodValidator

MethodIs creates a request validator that checks that the request method is equal to the given method m.

func MethodIsDelete

func MethodIsDelete() MethodValidator

MethodIsDelete creates a request validator that checks that the request is a DELETE request.

func MethodIsGet

func MethodIsGet() MethodValidator

MethodIsGet creates a request validator that checks that the request is a GET request.

func MethodIsNot

func MethodIsNot(s string) MethodValidator

MethodIs creates a request validator that checks that the request method is NOT equal to the given method m.

func MethodIsOptions

func MethodIsOptions() MethodValidator

MethodIsOptions creates a request validator that checks that the request is a OPTIONS request.

func MethodIsPatch

func MethodIsPatch() MethodValidator

MethodIsPatch creates a request validator that checks that the request is a PATCH request.

func MethodIsPost

func MethodIsPost() MethodValidator

MethodIsPost creates a request validator that checks that the request is a POST request.

func MethodIsPut

func MethodIsPut() MethodValidator

MethodIsPut creates a request validator that checks that the request is a PUT request.

func (MethodValidator) ValidateRequest

func (v MethodValidator) ValidateRequest(req *http.Request) error

type ProtoValidator

type ProtoValidator func(string) error

ProtoValidator is a validator that validates an http.Request or http.Response's Proto field.

func (ProtoValidator) ValidateRequest

func (v ProtoValidator) ValidateRequest(req *http.Request) error

func (ProtoValidator) ValidateResponse

func (v ProtoValidator) ValidateResponse(res *http.Response) error

type RequestFunc

type RequestFunc func(req *http.Request) error

RequestFunc is a function that validates an http.Request and can act as a RequestValidator.

func (RequestFunc) ValidateRequest

func (v RequestFunc) ValidateRequest(req *http.Request) error

type RequestValidator

type RequestValidator interface {
	ValidateRequest(req *http.Request) error
}

RequestValidator is a validator that validates an http.Request.

type ResponseFunc

type ResponseFunc func(res *http.Response) error

ResponseFunc is a function that validates an http.Response and can act as a ResponseValidator.

func (ResponseFunc) ValidateResponse

func (v ResponseFunc) ValidateResponse(res *http.Response) error

type ResponseValidator

type ResponseValidator interface {
	ValidateResponse(res *http.Response) error
}

ResponseValidator is a validator that validates an http.Response.

type StatusCodeValidator

type StatusCodeValidator func(int) error

StatusCodeValidator is a function that validates an http.Response's status code.

func StatusInRange

func StatusInRange(min, max int) StatusCodeValidator

StatusInRange checks that the status code is in the given range: [min, max).

func StatusIs

func StatusIs(code int) StatusCodeValidator

StatusIs checks that the status code is equal to the given code.

func StatusIs1XX

func StatusIs1XX() StatusCodeValidator

StatusIs1XX checks that the status code is in the range [100, 200).

func StatusIs2XX

func StatusIs2XX() StatusCodeValidator

StatusIs2XX checks that the status code is in the range [200, 300).

func StatusIs3XX

func StatusIs3XX() StatusCodeValidator

StatusIs3XX checks that the status code is in the range [300, 400).

func StatusIs4XX

func StatusIs4XX() StatusCodeValidator

StatusIs4XX checks that the status code is in the range [400, 500).

func StatusIs5XX

func StatusIs5XX() StatusCodeValidator

StatusIs5XX checks that the status code is in the range [500, 600).

func StatusIsNot

func StatusIsNot(code int) StatusCodeValidator

StatusIsNot checks that the status code is not equal to the given code.

func StatusIsOK

func StatusIsOK() StatusCodeValidator

StatusIsOK checks that the status code is 200.

func StatusNotError

func StatusNotError() StatusCodeValidator

StatusIsError checks that the status code is not in the range [400, 600).

func StatusNotInRange

func StatusNotInRange(min, max int) StatusCodeValidator

StatusNotInRange checks that the status code is not in the given range: [min, max).

func (StatusCodeValidator) ValidateResponse

func (v StatusCodeValidator) ValidateResponse(res *http.Response) error

type TLSValidator

type TLSValidator func(*tls.ConnectionState) error

TLSValidator is a validator that validates an http.Request or http.Response object's TLS connection.

func TLSIsNil

func TLSIsNil() TLSValidator

func TLSIsNotNil

func TLSIsNotNil() TLSValidator

func TLSVersionIs

func TLSVersionIs(v uint16) TLSValidator

func (TLSValidator) ValidateRequest

func (v TLSValidator) ValidateRequest(req *http.Request) error

func (TLSValidator) ValidateResponse

func (v TLSValidator) ValidateResponse(res *http.Response) error

type URLValidator

type URLValidator func(*url.URL) error

URLValidator is a validator function that validates an http.Request's URL field.

func URLHostIs

func URLHostIs(h string) URLValidator

URLHostIs creates a URL validator that checks that the URL's Host field matches h.

func URLIs

func URLIs(s string) URLValidator

URLIs creates a url validator that checks that the URL exactly matches the given string s.

func URLPathGlob

func URLPathGlob(p string) URLValidator

URLPathGlob creates a URL validator that checks that the URL's path matches the given glob pattern p.

Uses path.Match to match the glob pattern.

func URLPathIs

func URLPathIs(p string) URLValidator

URLPathIs creates a URLValidator that checks that the request URL's path is equal to the given path p.

func URLQueryHas

func URLQueryHas(k string) URLValidator

URLQueryHas creates a URLValidator that checks that the request URL's query parameters contain the given key k.

func URLQueryIs

func URLQueryIs(k, v string) URLValidator

URLQueryIs creates a URLValidator that checks that the request URL's query parameters contain the given key k with the value v.

func URLQueryValueValidator

func URLQueryValueValidator(k string, vfn func(string) error) URLValidator

URLQueryValueValidator creates a URLValidator that applies the validator function vfn to the first value for the given key in the request URL's query.

func URLSchemeIs

func URLSchemeIs(s string) URLValidator

URLSchemeIs creates a URLValidator that checks that the request URL's scheme matches the given scheme s.

func URLSchemeIsHTTP

func URLSchemeIsHTTP() URLValidator

URLSchemeIsHTTP creates a URLValidator that checks that the request URL's scheme is "http".

func URLSchemeIsHTTPS

func URLSchemeIsHTTPS() URLValidator

URLSchemeIsHTTPS creates a URLValidator that checks that the request URL's scheme is "https".

func URLUserinfoIs

func URLUserinfoIs(ui string) URLValidator

URLUserinfoIs creates a url validator that checks that the URL's userinfo matches the given userinfo ui.

The user info will be in the form of "username[:password]".

func (URLValidator) ValidateRequest

func (v URLValidator) ValidateRequest(req *http.Request) error

Jump to

Keyboard shortcuts

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