http

package module
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Apr 4, 2023 License: MIT Imports: 15 Imported by: 0

README

Package http

This package contains http handler related to help you write handler easier and have a standardized response.

How to create custom handler

To create custom handler using this package, you need to declare the handler using this function signature:

func(w http.ResponseWriter, r *http.Request) (data interface{}, pageToken *string, err error)

This handler requires you to return the response data, page token and error if any. response data is the struct for the response data page token is the optional hashed or encoded page token for pagination. We enforce this approach for pagination since it's the most clean way to do a pagination.' This approach support infinite scroll and traditional pagination. error is the error (if any)

Example:

func HelloHandler(w http.ResponseWriter, r *http.Request) (data interface{}, pageToken *string, err error) {
    // Data we will return
	data = Person{
		FirstName: "Budi",
		LastName:  "Ariyanto",
	}

    // The token
	token := "o934ywjkhk67j78sd9af=="
    pageToken = &token
    
    // error, should be something like this
    // if err != nil {
    //    return err
    //}

	return
}

func main() {
    // Meta is metadata for the response
	meta := structs.Meta{
		Version: "v1.2.3",
		Status:  "stable",
		APIEnv:  "prod-test",
	}

	// When new context handler is created, it will inject all general error map.
	// Then you should add your necessary own error to the handler.
	handlerCtx := phttp.NewContextHandler(meta)

	// add error individualy
	var ErrCustom *structs.ErrorResponse = &structs.ErrorResponse{
		Response: structs.Response{
			ResponseCode: "00011",
			ResponseDesc: structs.ResponseDesc{
				ID: "Custom error",
				EN: "Custom error",
			},
		},
		HttpStatus: http.StatusInternalServerError,
	}
	handlerCtx.AddError(errors.New("custom error"), ErrCustom)

	// add error individualy
	var ErrCustom2 *structs.ErrorResponse = &structs.ErrorResponse{
		Response: structs.Response{
			ResponseCode: "00011",
			ResponseDesc: structs.ResponseDesc{
				ID: "Custom error",
				EN: "Custom error",
			},
		},
		HttpStatus: http.StatusInternalServerError,
	}

	// add error individualy
	var ErrCustom3 *structs.ErrorResponse = &structs.ErrorResponse{
		Response: structs.Response{
			ResponseCode: "00011",
			ResponseDesc: structs.ResponseDesc{
				ID: "Custom error",
				EN: "Custom error",
			},
		},
		HttpStatus: http.StatusInternalServerError,
	}

	// add error by setup error map at first
	customError2 := errors.New("Custom error 2")
	customError3 := errors.New("Custom error 3")
	errMap := map[error]*structs.ErrorResponse{
		customError2: ErrCustom2,
		customError3: ErrCustom3,
	}

	// add error map
	handlerCtx.AddErrorMap(errMap)

    // newHandler is a function that will create function for create new custom handler with injected handler context
    newHandler := phttp.NewHttpHandler(handlerCtx)
    
    // helloHandler is the handler
	helloHandler := newHandler(HelloHandler)

	router := chi.NewRouter()
	router.Get("/hello", helloHandler.ServeHTTP)

	http.ListenAndServe(":5678", router)
}

From the example above, you can see you only care about the data, pageToken and error, then this custom handler will construct the response itself. This response are refer to Kitabisa API response standardization.

How to use http metrics

This http metrics will send your http metrics (response time, error status, and success status) to telegraf.

Usage:

handlerCtx := phttp.NewContextHandler(pstructs.Meta{
	Version: "v1.2.3",
	Status:  "stable",
	APIEnv:  "prod-test",
})

telegrafHost := "telegraf.localhost"
telegrafPort := 8125
serviceName := "my-service" // serviceName identifies your service in the telegraf storage (e.g., Influxdb, etc)

phandler := phttp.NewHttpHandler(
	handlerCtx,
	phttp.WithMetric(telegrafHost, telegrafPort, serviceName),
)

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CreatePageToken

func CreatePageToken(arrayData interface{}, dataLimit int, fieldNameId string, fieldNameDate string) (nextToken string)

func New

func New(w io.Writer, lvl zerolog.Level, withTimestamp bool) zerolog.Logger

func NewHttpHandler

func NewHttpHandler(c HttpHandlerContext, opts ...HandlerOption) func(handler func(w http.ResponseWriter, r *http.Request) (interface{}, *string, error)) PerkakasHttpHandler

func ParsePageToken

func ParsePageToken(pageToken string) (token map[string]string)

Types

type APIResponse

type APIResponse struct {
	*BaseResponse
	Meta       Meta                      `json:"meta"`
	Next       *string                   `json:"next,omitempty"` //deprecated in v3. Will be removed
	Pagination *paginationPkg.Pagination `json:"pagination,omitempty"`
	Data       interface{}               `json:"data,omitempty"`
	*ErrResponse
	// contains filtered or unexported fields
}

type BaseResponse

type BaseResponse struct {
	ResponseCode    string        `json:"response_code,omitempty"`
	ResponseMessage string        `json:"response_message,omitempty"`
	ResponseDesc    *ResponseDesc `json:"response_desc,omitempty"` //deprecated in v3. Will be removed
}

type CustomSuccessResp

type CustomSuccessResp struct {
	ResponseCode    string
	ResponseMessage string
	StatusCode      int
	Header          map[string]string
	Pagination      *paginationPkg.Pagination
}

type CustomWriter

type CustomWriter struct {
	C HttpHandlerContext
}

func (*CustomWriter) Write

func (c *CustomWriter) Write(ctx context.Context, w http.ResponseWriter, data interface{}, nextPage *string)

func (*CustomWriter) WriteError

func (c *CustomWriter) WriteError(ctx context.Context, w http.ResponseWriter, err error)

WriteError sending error response based on err type

type ErrResD

type ErrResD struct {
	APIResponse
}

func (*ErrResD) HTTPErrorResponse

func (er *ErrResD) HTTPErrorResponse(w http.ResponseWriter, lgr zerolog.Logger, err error)

HTTPErrorResponse takes a writer, error and a logger, performs a type switch to determine if the type is an Error (which meets the Error interface as defined in this package), then sends the Error as a response to the client. If the type does not meet the Error interface as defined in this package, then a proper error is still formed and sent to the client, however, the Kind and Code will be Unexpected. Logging of error is also done using https://github.com/rs/zerolog

type ErrResponse

type ErrResponse struct {
	Error ServiceError `json:"error,omitempty"`
}

ErrResponse is used as the Response Body

type HandlerOption

type HandlerOption func(*PerkakasHttpHandler)

type HttpHandlerContext

type HttpHandlerContext struct {
	M                     Meta
	CustomSuccessResponse *CustomSuccessResp
}

func NewContextHandler

func NewContextHandler(meta Meta) HttpHandlerContext

NewContextHandler add base error response

type Meta

type Meta struct {
	Version   string `json:"version" mapstructure:"version"`
	Status    string `json:"api_status" mapstructure:"api_status"`
	APIEnv    string `json:"api_env" mapstructure:"api_env"`
	RequestId string `json:"request_id,omitempty"`
}

Meta defines meta format format for api format

type PerkakasHttpHandler

type PerkakasHttpHandler struct {
	// H is handler, with return interface{} as data object, *string for token next page, error for error type
	H func(w http.ResponseWriter, r *http.Request) (interface{}, *string, error)
	CustomWriter
	Metric      *statsd.Client
	ServiceName string
}

func (PerkakasHttpHandler) ServeHTTP

func (h PerkakasHttpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

type ResponseDesc

type ResponseDesc struct {
	ID string `json:"id,omitempty"`
	EN string `json:"en,omitempty"`
}

ResponseDesc defines details data response

type ServiceError

type ServiceError struct {
	Kind    string            `json:"kind,omitempty"`
	Code    string            `json:"code,omitempty"`
	Param   map[string]string `json:"param,omitempty"`
	Message string            `json:"message,omitempty"`
}

ServiceError has fields for Service errors. All fields with no data will be omitted

Directories

Path Synopsis
Package errs is a modified copy of the upspin.io/errors package.
Package errs is a modified copy of the upspin.io/errors package.
mocks
Package mock_random is a generated GoMock package.
Package mock_random is a generated GoMock package.
jwt

Jump to

Keyboard shortcuts

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