crud

package module
v1.5.0 Latest Latest
Warning

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

Go to latest
Published: Feb 7, 2024 License: Apache-2.0 Imports: 13 Imported by: 8

README

crud

GoDoc Go

An OpenAPI v2 builder and validation library for building HTTP/REST APIs.

No additional dependencies besides the router you choose.

Status

Version 1.0 is stable, version 2 will support OpenAPI v3.

Why

OpenAPI is great, but up until now your options to use it are:

  1. Write YAML by hand and then make your server match your spec.
  2. Write YAML by hand and generate your server.
  3. Generate YAML from comments in your code.

None of these options seems like a great idea.

This project takes another approach: make a specification in Go code using type-safe builders where possible. The OpenAPI spec is generated from this and validation is done before your handler gets called.

This reduces boilerplate that you have to write and gives you nice documentation too!

Examples

Getting started

Check the example directory under the adapters for a simple example.

Start by getting the package go get github.com/jakecoffman/crud

Then in your main.go:

  1. Create a router with NewRouter, use an adapter from the adapters sub-package or write you own.
  2. Add routes with Add.
  3. Then call Serve.

Routes are specifications that look like this:

crud.Spec{
	Method:      "PATCH",
	Path:        "/widgets/{id}",
	PreHandlers: Auth,
	Handler:     CreateHandler,
	Description: "Adds a widget",
	Tags:        []string{"Widgets"},
	Validate: crud.Validate{
		Path: crud.Object(map[string]crud.Field{
			"id": crud.Number().Required().Description("ID of the widget"),
		}),
		Body: crud.Object(map[string]crud.Field{
			"owner": crud.String().Required().Example("Bob").Description("Widget owner's name"),
			"quantity": crud.Integer().Min(1).Default(1).Description("The amount requested")
		}),
	},
}

This will add a route /widgets/:id that responds to the PATCH method. It generates swagger and serves it at the root of the web application. It validates that the ID in the path is a number, so you don't have to. It also validates that the body is an object and has an "owner" property that is a string, again so you won't have to.

It mounts the swagger-ui at / and loads up the generated swagger.json:

screenshot

The PreHandlers run before validation, and the Handler runs after validation is successful.

Documentation

Index

Constants

View Source
const (
	KindNumber  = "number"
	KindString  = "string"
	KindBoolean = "boolean"
	KindObject  = "object"
	KindArray   = "array"
	KindFile    = "file"
	KindInteger = "integer"
)

These kinds correlate to swagger and json types.

View Source
const (
	FormatDate     = "date"
	FormatDateTime = "dateTime"
)

Variables

View Source
var SwaggerPathPattern = regexp.MustCompile("\\{([^}]+)\\}")

SwaggerPathPattern regex captures swagger path params.

View Source
var SwaggerUiTemplate []byte

SwaggerUiTemplate contains the html for swagger UI.

Functions

This section is empty.

Types

type Adapter

type Adapter interface {
	Install(router *Router, spec *Spec) error
	Serve(swagger *Swagger, addr string) error
}

type Field

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

Field allows specification of swagger or json schema types using the builder pattern.

func Array

func Array() Field

Array creates a field with array type

func Boolean

func Boolean() Field

Boolean creates a field with boolean type

func Date added in v1.2.0

func Date() Field

Date creates a field with date type

func DateTime added in v1.2.0

func DateTime() Field

DateTime creates a field with dateTime type

func File

func File() Field

File creates a field with file type

func Integer

func Integer() Field

Integer creates a field with integer type

func Number

func Number() Field

Number creates a field with floating point type

func Object

func Object(obj map[string]Field) Field

Object creates a field with object type

func String

func String() Field

String creates a field with string type

func (Field) Allow

func (f Field) Allow(values ...interface{}) Field

Allow lets you break rules For example, String().Required() excludes "", unless you Allow("")

func (Field) Default

func (f Field) Default(value interface{}) Field

Default specifies a default value to use if the field is nil. Can't be used with Required.

func (Field) Description

func (f Field) Description(description string) Field

Description specifies a human-readable explanation of the field

func (Field) Enum

func (f Field) Enum(values ...interface{}) Field

Enum restricts the field's values to the set of values specified

func (Field) Example

func (f Field) Example(ex interface{}) Field

Example specifies an example value for the swagger to display

func (Field) Format added in v1.2.0

func (f Field) Format(format string) Field

Format is used to set custom format types. Note that formats with special validation in this library also have their own constructor. See DateTime for example.

func (Field) Initialized

func (f Field) Initialized() bool

Initialized returns true if the field has been initialized with Number, String, etc. When the Swagger is being built, often an uninitialized field will be ignored.

func (Field) Items

func (f Field) Items(item Field) Field

Items specifies the type of elements in an array

func (Field) Kind

func (f Field) Kind() string

Kind returns the kind of the field.

func (Field) Max

func (f Field) Max(max float64) Field

Max specifies a maximum value for this field

func (Field) Min

func (f Field) Min(min float64) Field

Min specifies a minimum value for this field

func (Field) Pattern added in v1.3.0

func (f Field) Pattern(pattern string) Field

Pattern specifies a regex pattern value for this field

func (Field) Required

func (f Field) Required() Field

Required specifies the field must be provided. Can't be used with Default.

func (Field) String

func (f Field) String() string

func (Field) Strip

func (f Field) Strip(strip bool) Field

Strip overrides the global "strip unknown" setting just for this field, and all children of this field

func (*Field) ToJsonSchema

func (f *Field) ToJsonSchema() JsonSchema

ToJsonSchema transforms a field into a Swagger Schema. TODO this is an extension of JsonSchema, rename in v2 ToSchema() Schema

func (*Field) ToSwaggerParameters

func (f *Field) ToSwaggerParameters(in string) (parameters []Parameter)

ToSwaggerParameters transforms a field into a slice of Parameter.

func (Field) Unknown

func (f Field) Unknown(allow bool) Field

Unknown overrides the global "allow unknown" setting just for this field, and all children of this field

func (*Field) Validate

func (f *Field) Validate(value interface{}) error

Validate is used in the validation middleware to tell if the value passed into the controller meets the restrictions set on the field.

type Info

type Info struct {
	Title   string `json:"title"`
	Version string `json:"version"`
}

type JsonSchema

type JsonSchema struct {
	Type        string                `json:"type,omitempty"`
	Format      string                `json:"format,omitempty"`
	Properties  map[string]JsonSchema `json:"properties,omitempty"`
	Items       *JsonSchema           `json:"items,omitempty"`
	Required    []string              `json:"required,omitempty"`
	Example     interface{}           `json:"example,omitempty"`
	Description string                `json:"description,omitempty"`
	Minimum     float64               `json:"minimum,omitempty"`
	Maximum     float64               `json:"maximum,omitempty"`
	Enum        []interface{}         `json:"enum,omitempty"`
	Default     interface{}           `json:"default,omitempty"`
	Pattern     string                `json:"pattern,omitempty"`
}

type MiddlewareFunc added in v1.5.0

type MiddlewareFunc func(http.Handler) http.Handler

type Operation

type Operation struct {
	Tags        []string            `json:"tags,omitempty"`
	Parameters  []Parameter         `json:"parameters,omitempty"`
	Responses   map[string]Response `json:"responses"`
	Description string              `json:"description"`
	Summary     string              `json:"summary"`
}

type Parameter

type Parameter struct {
	In   string `json:"in"`
	Name string `json:"name"`

	// one of path, query, header, body, or form
	Type   string `json:"type,omitempty"`
	Schema *Ref   `json:"schema,omitempty"`

	Required         *bool         `json:"required,omitempty"`
	Description      string        `json:"description,omitempty"`
	Minimum          *float64      `json:"minimum,omitempty"`
	Maximum          *float64      `json:"maximum,omitempty"`
	Enum             []interface{} `json:"enum,omitempty"`
	Pattern          string        `json:"pattern,omitempty"`
	Default          interface{}   `json:"default,omitempty"`
	Items            *JsonSchema   `json:"items,omitempty"`
	CollectionFormat string        `json:"collectionFormat,omitempty"`
}

type Path

type Path struct {
	Get     *Operation `json:"get,omitempty"`
	Post    *Operation `json:"post,omitempty"`
	Put     *Operation `json:"put,omitempty"`
	Delete  *Operation `json:"delete,omitempty"`
	Patch   *Operation `json:"patch,omitempty"`
	Options *Operation `json:"options,omitempty"`
}

type Ref

type Ref struct {
	Ref string `json:"$ref,omitempty"`
}

type Response

type Response struct {
	Schema      JsonSchema `json:"schema"`
	Description string     `json:"description"`

	Example interface{}       `json:"interface,omitempty"`
	Ref     *Ref              `json:"$ref,omitempty"`
	Headers map[string]string `json:"headers,omitempty"`
}

type Router

type Router struct {
	// Swagger is exposed so the user can edit additional optional fields.
	Swagger Swagger
	// contains filtered or unexported fields
}

Router is the main object that is used to generate swagger and holds the underlying router.

func NewRouter

func NewRouter(title, version string, adapter Adapter, options ...option.Option) *Router

NewRouter initializes a router.

func (*Router) Add

func (r *Router) Add(specs ...Spec) error

Add routes to the swagger spec and installs a handler with built-in validation. Some validation of the route itself occurs on Add so this is the kind of error that can be returned.

func (*Router) Serve

func (r *Router) Serve(addr string) error

Serve installs the swagger and the swagger-ui and runs the server.

func (*Router) Validate

func (r *Router) Validate(val Validate, query url.Values, body interface{}, path map[string]string) error

Validate checks the spec against the inputs and returns an error if it finds one.

type ServeMuxAdapter added in v1.5.0

type ServeMuxAdapter struct {
	Engine *http.ServeMux
}

func NewServeMuxAdapter added in v1.5.0

func NewServeMuxAdapter() *ServeMuxAdapter

func (*ServeMuxAdapter) Install added in v1.5.0

func (a *ServeMuxAdapter) Install(r *Router, spec *Spec) error

func (*ServeMuxAdapter) Serve added in v1.5.0

func (a *ServeMuxAdapter) Serve(swagger *Swagger, addr string) error

type Spec

type Spec struct {
	// Method is the http method of the route, e.g. GET, POST
	Method string
	// Path is the URL path of the routes, w.g. /widgets/{id}
	Path string
	// PreHandlers run before validation. Good for authorization
	PreHandlers interface{}
	// Handler runs after validation. This is where you take over
	Handler interface{}
	// Description is the longer text that will appear in the Swagger under the endpoint
	Description string
	// Tags are how the Swagger groups paths together, e.g. []string{"Widgets"}
	Tags []string
	// Summary is a short description of what an endpoint does in the Swagger
	Summary string
	// Validate is used to automatically validate the various inputs to the endpoint
	Validate Validate
	// Responses specifies the responses in Swagger. If none provided a default is used.
	Responses map[string]Response
}

Spec is used to generate swagger paths and automatic handler validation

func (Spec) Valid

func (s Spec) Valid() error

Valid returns errors if the spec itself isn't valid. This helps finds bugs early.

type Swagger

type Swagger struct {
	Swagger  string `json:"swagger"`
	Info     Info   `json:"info"`
	BasePath string `json:"basePath,omitempty"`

	Paths       map[string]*Path      `json:"paths"`
	Definitions map[string]JsonSchema `json:"definitions"`
}

type Validate

type Validate struct {
	Query    Field
	Body     Field
	Path     Field
	FormData Field
	Header   Field
}

Validate are optional fields that will be used during validation. Leave unneeded properties nil and they will be ignored.

Jump to

Keyboard shortcuts

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