controller

package
v0.0.5 Latest Latest
Warning

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

Go to latest
Published: Aug 30, 2023 License: MIT Imports: 10 Imported by: 1

Documentation

Overview

Package controller implements model based generic CRUD controllers (i.e. http handlers) to handle create / read / update / delete requests from http clients. Since crud use Gin web framework as http server, a controller here is actually a gin.HandlerFunc:

  • GET /models => GetListHandler[Model]: to retrieve a model list

  • GET /models/:id => GetByIDHandler[Model]: to retrieve a model by id

  • POST /models => CreateHandler[Model] : to create a new model

  • PUT /models/:id => UpdateHandler[Model] : to update an existing model

  • DELETE /models/:id => DeleteHandler[Model] : to delete an existing model

  • GET /models/:id/field => GetFieldHandler[Model] : to retrieve a field (nested model) of a model

  • POST /models/:id/field => CreateNestedHandler[Model] : to create a nested model (association)

  • DELETE /models/:id/field => DeleteNestedHandler[Model] : to delete an association record

The controller are all generic functions, which is available in Go 1.18 and later, see Go generics tutorial for help if you are not familiar with this feature. What you need to notice is that you HAVE TO pass handles the type arguments to specify the model type in the function call, because go have no way to infer them.

Notice that there is not a UpdateNestedHandler, because:

PUT /models/:id/field/:id == PUT /field/:id

Index

Constants

View Source
const (
	CodeSuccess       = http.StatusOK
	CodeNotFound      = http.StatusNotFound
	CodeBadRequest    = http.StatusBadRequest
	CodeProcessFailed = http.StatusUnprocessableEntity
)

Variables

View Source
var (
	ErrBindFailed      = errors.New("bind failed")
	ErrMissingID       = errors.New("missing id")
	ErrMissingParentID = errors.New("missing parent id")
	ErrUpdateID        = errors.New("id can not be updated")
)

Functions

func CreateHandler

func CreateHandler[T any]() gin.HandlerFunc

CreateHandler handles

POST /T

creates a new model T, responds with the created model T if successful.

Request body:

  • {...} // fields of the model T

Response:

  • 200 OK: { T: {...} }
  • 400 Bad Request: { error: "request band failed" }
  • 422 Unprocessable Entity: { error: "create process failed" }

func CreateNestedHandler

func CreateNestedHandler[P orm.Model, T orm.Model](parentIDRouteParam string, field string) gin.HandlerFunc

CreateNestedHandler handles

POST /P/:parentIDRouteParam/T

where:

  • P is the parent model, T is the child model
  • parentIDRouteParam is the route param name of the parent model P
  • field is the field name of the child model T in the parent model P

responds with the updated parent model P

Request body:

  • {...} // fields of the child model T

Response:

  • 200 OK: { P: {...} }
  • 400 Bad Request: { error: "request band failed" }
  • 422 Unprocessable Entity: { error: "create process failed" }

func DeleteHandler

func DeleteHandler[T orm.Model](idParam string) gin.HandlerFunc

DeleteHandler handles

DELETE /T/:idParam

Deletes the model T with the given id.

Request body: none

Response:

  • 200 OK: { deleted: true }
  • 400 Bad Request: { error: "missing id" }
  • 422 Unprocessable Entity: { error: "delete process failed" }

func DeleteNestedHandler

func DeleteNestedHandler[P orm.Model, T orm.Model](parentIdParam string, field string, childIdParam string) gin.HandlerFunc

DeleteNestedHandler handles

DELETE /P/:parentIdParam/T/:childIdParam

where:

  • P is the parent model, T is the child model
  • parentIdParam is the route param name of the parent model P
  • childIdParam is the route param name of the child model T in the parent model P
  • field is the field name of the child model T in the parent model P

Request body: none

Response:

  • 200 OK: { deleted: true }
  • 400 Bad Request: { error: "missing id" }
  • 422 Unprocessable Entity: { error: "delete process failed" }

func ErrorResponseBody

func ErrorResponseBody(err error) gin.H

ErrorResponseBody builds the error response body:

{ error: "error message" }

func GetByIDHandler

func GetByIDHandler[T orm.Model](idParam string) gin.HandlerFunc

GetByIDHandler handles

GET /T/:idParam

QueryOptions (See GetRequestOptions for more details): preload

Response:

  • 200 OK: { T: {...} }
  • 400 Bad Request: { error: "request band failed" }
  • 422 Unprocessable Entity: { error: "get process failed" }

func GetFieldHandler

func GetFieldHandler[T orm.Model](idParam string, field string) gin.HandlerFunc

GetFieldHandler handles

GET /T/:idParam/field

QueryOptions (See GetRequestOptions for more details):

limit, offset, order_by, desc, filter_by, filter_value, preload, total.

Notice, all GetRequestOptions will be conditions for the field, for example:

GET /user/123/order?preload=Product

Preloads User.Order.Product instead of User.Product.

Response:

  • 200 OK: { Fs: [{...}, ...] } // field models
  • 400 Bad Request: { error: "request band failed" }
  • 422 Unprocessable Entity: { error: "get process failed" }

func GetListHandler

func GetListHandler[T any]() gin.HandlerFunc

GetListHandler handles

GET /T

It returns a list of models.

QueryOptions (See GetRequestOptions for more details):

limit, offset, order_by, desc, filter_by, filter_value, preload, total.

Response:

  • 200 OK: { Ts: [{...}, ...] }
  • 400 Bad Request: { error: "request band failed" }
  • 422 Unprocessable Entity: { error: "get process failed" }

func ResponseError

func ResponseError(c *gin.Context, code int, err error)

ResponseError writes an error response to client in JSON.

func ResponseSuccess

func ResponseSuccess(c *gin.Context, model any, addition ...gin.H)

ResponseSuccess writes a success response to client in JSON.

func SuccessResponseBody

func SuccessResponseBody(model any, addition ...gin.H) gin.H

SuccessResponseBody builds the success response body:

{ `model`: { ... } }

where the `model` will be replaced by the model's type name. and addition fields can add any k-v to the response body.

func UpdateHandler

func UpdateHandler[T orm.Model](idParam string) gin.HandlerFunc

UpdateHandler handles

PUT /T/:idParam

Updates the model T with the given id.

Request body:

  • {"field": "new_value", ...} // fields to update

Response:

  • 200 OK: { updated: true }
  • 400 Bad Request: { error: "missing id or bind fields failed" }
  • 404 Not Found: { error: "record with id not found" }
  • 422 Unprocessable Entity: { error: "update process failed" }

Types

type GetRequestOptions

type GetRequestOptions struct {
	Limit       int      `form:"limit"`
	Offset      int      `form:"offset"`
	OrderBy     string   `form:"order_by"`
	Descending  bool     `form:"desc"`
	FilterBy    string   `form:"filter_by"`
	FilterValue string   `form:"filter_value"`
	Preload     []string `form:"preload"` // fields to preload
	Total       bool     `form:"total"`   // return total count ?
}

GetRequestOptions is the query options (?opt=val) for GET requests:

limit=10&offset=4&                 # pagination
order_by=id&desc=true&             # ordering
filter_by=name&filter_value=John&  # filtering
total=true&                        # return total count (all available records under the filter, ignoring pagination)
preload=Product&preload=Product.Manufacturer  # preloading: loads nested models as well

It is used in GetListHandler, GetByIDHandler and GetFieldHandler, to bind the query parameters in the GET request url.

Jump to

Keyboard shortcuts

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