http

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Jun 24, 2026 License: MIT Imports: 28 Imported by: 0

Documentation

Overview

Package http provides an HTTP server built on gorilla/mux.

The server adds configurable CORS, request/response tracing and graceful shutdown. BaseController offers helpers for parsing request variables, decoding JSON bodies, pagination and writing JSON or error responses (AppError is translated to the right HTTP status).

Index

Examples

Constants

View Source
const (
	ErrCodeHttpTest                          = "HTTP-000"
	ErrCodeHttpSrvListen                     = "HTTP-001"
	ErrCodeDecodeRequest                     = "HTTP-002"
	ErrCodeHttpUrlVar                        = "HTTP-003"
	ErrCodeHttpCurrentUser                   = "HTTP-004"
	ErrCodeHttpUrlVarEmpty                   = "HTTP-005"
	ErrCodeHttpUrlFormVarEmpty               = "HTTP-006"
	ErrCodeHttpUrlFormVarNotInt              = "HTTP-007"
	ErrCodeHttpUrlFormVarNotTime             = "HTTP-008"
	ErrCodeHttpMultipartParseForm            = "HTTP-009"
	ErrCodeHttpMultipartEmptyContent         = "HTTP-010"
	ErrCodeHttpMultipartNotMultipart         = "HTTP-011"
	ErrCodeHttpMultipartParseMediaType       = "HTTP-012"
	ErrCodeHttpMultipartWrongMediaType       = "HTTP-013"
	ErrCodeHttpMultipartMissingBoundary      = "HTTP-014"
	ErrCodeHttpMultipartEofReached           = "HTTP-015"
	ErrCodeHttpMultipartNext                 = "HTTP-016"
	ErrCodeHttpMultipartFormNameFileExpected = "HTTP-017"
	ErrCodeHttpMultipartFilename             = "HTTP-018"
	ErrCodeHttpCurrentClient                 = "HTTP-019"
	ErrCodeHttpUrlFormVarNotFloat            = "HTTP-020"
	ErrCodeHttpUrlFormVarNotBool             = "HTTP-021"
	ErrCodeHttpUrlWrongSortFormat            = "HTTP-022"
	ErrCodeHttpUrlVarInvalidUUID             = "HTTP-023"
	ErrCodeHttpUrlMaxPageSizeExceeded        = "HTTP-024"
	ErrCodeHttpCurrentPartner                = "HTTP-025"
	ErrCodeHttpFileHeaderEmpty               = "HTTP-026"
	ErrCodeHttpFileHeaderInvalidJson         = "HTTP-027"
	ErrCodeHttpFileHeaderInvalidUUID         = "HTTP-028"
	ErrCodeHttpProxyFileNewRequest           = "HTTP-029"
	ErrCodeHttpProxyFileInvalidContext       = "HTTP-030"
	ErrCodeHttpProxyFileClientDo             = "HTTP-031"
	ErrCodeHttpProxyFileCreatePart           = "HTTP-032"
	ErrCodeHttpProxyFileCopyFile             = "HTTP-033"
	ErrCodeHttpProxyFileWriteField           = "HTTP-034"
	ErrCodeHttpProxyFileReadResponse         = "HTTP-035"
	ErrCodeHttpProxyFileJsonUnmarshal        = "HTTP-036"
	ErrCodeHttpRequestEmptyUrl               = "HTTP-037"
	ErrCodeHttpRequestEmptyMethod            = "HTTP-038"
	ErrCodeHttpRequestEmptyClient            = "HTTP-039"
	ErrCodeHttpRequestEmptyResponseFunc      = "HTTP-040"
	ErrCodeHttpRequestInvalidUrl             = "HTTP-041"
	ErrCodeHttpRequestInvalidStatusCode      = "HTTP-042"
	ErrCodeHttpRequestReadAll                = "HTTP-043"
	ErrCodeHttpRequestResponseFuncFailed     = "HTTP-044"
	ErrCodeHttpRequestJsonMarshal            = "HTTP-045"
	ErrCodeHttpRequestJsonUnmarshal          = "HTTP-046"
	ErrCodeHttpRequestWriterWriteField       = "HTTP-047"
	ErrCodeHttpRequestWriterCreate           = "HTTP-048"
	ErrCodeHttpRequestWriterCopy             = "HTTP-049"
	ErrCodeHttpRequestWriterClose            = "HTTP-050"
	ErrCodeHttpRequestEmptyFileData          = "HTTP-051"
	ErrCodeHttpRequestNew                    = "HTTP-052"
	ErrCodeHttpRequestDo                     = "HTTP-053"
	ErrCodeHttpUrlInvalidPagingSortSet       = "HTTP-054"
	ErrCodeHttpCalculateLengthCopy           = "HTTP-055"
)
View Source
const (
	RequestMetricsLatencyMsGaugeName = "request_metrics_latency_ms_gauge"
	RequestMetricsErrorCounterName   = "request_metrics_error_counter"

	RequestMetricsLabelUrl             = "url"
	RequestMetricsLabelIntegrationName = "name"
	RequestMetricsLabelErrorCodeName   = "code"
)
View Source
const (
	R = "r" // R read
	W = "w" // W write
	X = "x" // X execute
	D = "d" // D delete
)
View Source
const (
	Authorization = "Authorization"
	ContentType   = "Content-Type"
)
View Source
const (
	Me = "me" // Me can be used in URL whenever userId is expected. When encountered, userId from the session context is used
)

Variables

View Source
var (
	ErrHttpTest = func() error {
		return jet.NewAppErrBuilder(ErrCodeHttpTest, "").Business().Err()
	}
	ErrHttpSrvListen = func(cause error) error {
		return jet.NewAppErrBuilder(ErrCodeHttpSrvListen, "").Wrap(cause).Err()
	}
	ErrHttpDecodeRequest = func(cause error, ctx context.Context) error {
		return jet.NewAppErrBuilder(ErrCodeDecodeRequest, "invalid request").Wrap(cause).Business().C(ctx).HttpSt(http.StatusBadRequest).Err()
	}
	ErrHttpUrlVar = func(ctx context.Context, v string) error {
		return jet.NewAppErrBuilder(ErrCodeHttpUrlVar, "invalid or empty URL parameter").F(jet.KV{"var": v}).Business().C(ctx).HttpSt(http.StatusBadRequest).Err()
	}
	ErrHttpCurrentUser = func(ctx context.Context) error {
		return jet.NewAppErrBuilder(ErrCodeHttpCurrentUser, `cannot obtain current user`).Business().C(ctx).HttpSt(http.StatusBadRequest).Err()
	}
	ErrHttpUrlVarEmpty = func(ctx context.Context, v string) error {
		return jet.NewAppErrBuilder(ErrCodeHttpUrlVarEmpty, `URL parameter is empty`).Business().F(jet.KV{"var": v}).C(ctx).HttpSt(http.StatusBadRequest).Err()
	}
	ErrHttpUrlVarInvalidUUID = func(ctx context.Context, v string) error {
		return jet.NewAppErrBuilder(ErrCodeHttpUrlVarInvalidUUID, `invalid UUID`).Business().F(jet.KV{"var": v}).C(ctx).HttpSt(http.StatusBadRequest).Err()
	}
	ErrHttpUrlFormVarEmpty = func(ctx context.Context, v string) error {
		return jet.NewAppErrBuilder(ErrCodeHttpUrlFormVarEmpty, `URL form value is empty`).Business().F(jet.KV{"var": v}).C(ctx).HttpSt(http.StatusBadRequest).Err()
	}
	ErrHttpUrlFormVarNotInt = func(cause error, ctx context.Context, v string) error {
		return jet.NewAppErrBuilder(ErrCodeHttpUrlFormVarNotInt, "form value must be of int type").Wrap(cause).Business().C(ctx).HttpSt(http.StatusBadRequest).Err()
	}
	ErrHttpUrlFormVarNotFloat = func(cause error, ctx context.Context, v string) error {
		return jet.NewAppErrBuilder(ErrCodeHttpUrlFormVarNotFloat, "form value must be of float type").Wrap(cause).Business().C(ctx).HttpSt(http.StatusBadRequest).Err()
	}
	ErrHttpUrlFormVarNotBool = func(cause error, ctx context.Context, v string) error {
		return jet.NewAppErrBuilder(ErrCodeHttpUrlFormVarNotBool, "form value must be of bool type").Wrap(cause).Business().C(ctx).HttpSt(http.StatusBadRequest).Err()
	}
	ErrHttpUrlFormVarNotTime = func(cause error, ctx context.Context, v string) error {
		return jet.NewAppErrBuilder(ErrCodeHttpUrlFormVarNotTime, "form value must be of time type in RFC-3339 format").Wrap(cause).Business().C(ctx).HttpSt(http.StatusBadRequest).Err()
	}
	ErrHttpFileHeaderEmpty = func(ctx context.Context, v string) error {
		return jet.NewAppErrBuilder(ErrCodeHttpFileHeaderEmpty, `file header is empty`).Business().F(jet.KV{"var": v}).C(ctx).HttpSt(http.StatusBadRequest).Err()
	}
	ErrHttpFileHeaderInvalidUUID = func(ctx context.Context, v string) error {
		return jet.NewAppErrBuilder(ErrCodeHttpFileHeaderInvalidUUID, `invalid UUID`).Business().F(jet.KV{"var": v}).C(ctx).HttpSt(http.StatusBadRequest).Err()
	}
	ErrHttpFileHeaderInvalidJson = func(ctx context.Context, v string) error {
		return jet.NewAppErrBuilder(ErrCodeHttpFileHeaderInvalidJson, `file header json is invalid`).Business().F(jet.KV{"var": v}).C(ctx).HttpSt(http.StatusBadRequest).Err()
	}
	ErrHttpMultipartParseForm = func(cause error, ctx context.Context) error {
		return jet.NewAppErrBuilder(ErrCodeHttpMultipartParseForm, "parse multipart form").Wrap(cause).Business().C(ctx).HttpSt(http.StatusBadRequest).Err()
	}
	ErrHttpMultipartEmptyContent = func(ctx context.Context) error {
		return jet.NewAppErrBuilder(ErrCodeHttpMultipartEmptyContent, `content is empty`).Business().C(ctx).HttpSt(http.StatusBadRequest).Err()
	}
	ErrHttpMultipartNotMultipart = func(ctx context.Context) error {
		return jet.NewAppErrBuilder(ErrCodeHttpMultipartNotMultipart, `content isn't multipart`).Business().C(ctx).HttpSt(http.StatusBadRequest).Err()
	}
	ErrHttpMultipartParseMediaType = func(cause error, ctx context.Context) error {
		return jet.NewAppErrBuilder(ErrCodeHttpMultipartParseMediaType, "parse media type").Wrap(cause).Business().C(ctx).HttpSt(http.StatusBadRequest).Err()
	}
	ErrHttpMultipartWrongMediaType = func(ctx context.Context, mt string) error {
		return jet.NewAppErrBuilder(ErrCodeHttpMultipartWrongMediaType, `wrong media type %s`, mt).Business().C(ctx).HttpSt(http.StatusBadRequest).Err()
	}
	ErrHttpMultipartMissingBoundary = func(ctx context.Context) error {
		return jet.NewAppErrBuilder(ErrCodeHttpMultipartMissingBoundary, `missing boundary`).Business().C(ctx).HttpSt(http.StatusBadRequest).Err()
	}
	ErrHttpMultipartEofReached = func(ctx context.Context) error {
		return jet.NewAppErrBuilder(ErrCodeHttpMultipartEofReached, `no parts found`).Business().C(ctx).HttpSt(http.StatusBadRequest).Err()
	}
	ErrHttpMultipartNext = func(cause error, ctx context.Context) error {
		return jet.NewAppErrBuilder(ErrCodeHttpMultipartNext, "reading part").Wrap(cause).Business().C(ctx).HttpSt(http.StatusBadRequest).Err()
	}
	ErrHttpMultipartFormNameFileExpected = func(ctx context.Context) error {
		return jet.NewAppErrBuilder(ErrCodeHttpMultipartFormNameFileExpected, `correct part must have name="file" param`).Business().C(ctx).HttpSt(http.StatusBadRequest).Err()
	}
	ErrHttpMultipartFilename = func(ctx context.Context) error {
		return jet.NewAppErrBuilder(ErrCodeHttpMultipartFilename, `filename is empty`).Business().C(ctx).HttpSt(http.StatusBadRequest).Err()
	}
	ErrHttpCurrentClient = func(ctx context.Context) error {
		return jet.NewAppErrBuilder(ErrCodeHttpCurrentClient, `cannot obtain current client`).Business().C(ctx).HttpSt(http.StatusBadRequest).Err()
	}
	ErrHttpCurrentPartner = func(ctx context.Context) error {
		return jet.NewAppErrBuilder(ErrCodeHttpCurrentPartner, `cannot obtain current partner`).Business().C(ctx).HttpSt(http.StatusBadRequest).Err()
	}
	ErrHttpUrlWrongSortFormat = func(ctx context.Context, v string) error {
		return jet.NewAppErrBuilder(ErrCodeHttpUrlWrongSortFormat, "wrong sort format").Business().F(jet.KV{"var": v}).C(ctx).HttpSt(http.StatusBadRequest).Err()
	}
	ErrHttpUrlMaxPageSizeExceeded = func(ctx context.Context, maxPageSize int) error {
		return jet.NewAppErrBuilder(ErrCodeHttpUrlMaxPageSizeExceeded, "max page size (%d) exceeded", maxPageSize).Business().C(ctx).HttpSt(http.StatusBadRequest).Err()
	}
	ErrHttpUrlInvalidPagingSortSet = func(ctx context.Context) error {
		return jet.NewAppErrBuilder(ErrCodeHttpUrlInvalidPagingSortSet, "invalid sort set").Business().C(ctx).HttpSt(http.StatusBadRequest).Err()
	}
	ErrHttpProxyFileNewRequest = func(ctx context.Context, cause error) error {
		return jet.NewAppErrBuilder(ErrCodeHttpProxyFileNewRequest, "new request").Wrap(cause).C(ctx).Err()
	}
	ErrHttpProxyFileInvalidContext = func(ctx context.Context, cause error) error {
		return jet.NewAppErrBuilder(ErrCodeHttpProxyFileInvalidContext, "invalid context").Wrap(cause).C(ctx).Err()
	}
	ErrHttpProxyFileClientDo = func(ctx context.Context, cause error) error {
		return jet.NewAppErrBuilder(ErrCodeHttpProxyFileClientDo, "client do failed").Wrap(cause).C(ctx).Err()
	}
	ErrHttpProxyFileCreatePart = func(cause error) error {
		return jet.NewAppErrBuilder(ErrCodeHttpProxyFileCreatePart, "create part failed").Wrap(cause).Err()
	}
	ErrHttpProxyFileCopyFile = func(cause error) error {
		return jet.NewAppErrBuilder(ErrCodeHttpProxyFileCopyFile, "copy failed").Wrap(cause).Err()
	}
	ErrHttpProxyFileWriteField = func(cause error) error {
		return jet.NewAppErrBuilder(ErrCodeHttpProxyFileWriteField, "write field failed").Wrap(cause).Err()
	}
	ErrHttpProxyFileReadResponse = func(ctx context.Context, cause error) error {
		return jet.NewAppErrBuilder(ErrCodeHttpProxyFileReadResponse, "read response failed").Wrap(cause).C(ctx).Err()
	}
	ErrHttpProxyFileJsonUnmarshal = func(ctx context.Context, cause error) error {
		return jet.NewAppErrBuilder(ErrCodeHttpProxyFileJsonUnmarshal, "unmarshall failed").Wrap(cause).C(ctx).Err()
	}
	ErrHttpRequestEmptyUrl = func(ctx context.Context) error {
		return jet.NewAppErrBuilder(ErrCodeHttpRequestEmptyUrl, "request: empty url").C(ctx).Err()
	}
	ErrHttpRequestEmptyMethod = func(ctx context.Context) error {
		return jet.NewAppErrBuilder(ErrCodeHttpRequestEmptyMethod, "request: empty method").C(ctx).Err()
	}
	ErrHttpRequestEmptyClient = func(ctx context.Context) error {
		return jet.NewAppErrBuilder(ErrCodeHttpRequestEmptyClient, "request: empty client").C(ctx).Err()
	}
	ErrHttpRequestEmptyResponseFunc = func(ctx context.Context) error {
		return jet.NewAppErrBuilder(ErrCodeHttpRequestEmptyResponseFunc, "request: empty response function").C(ctx).Err()
	}
	ErrHttpRequestInvalidUrl = func(ctx context.Context, cause error) error {
		return jet.NewAppErrBuilder(ErrCodeHttpRequestInvalidUrl, "request: invalid url").Wrap(cause).C(ctx).Err()
	}
	ErrHttpRequestInvalidStatusCode = func(ctx context.Context, code int, detail string) error {
		return jet.NewAppErrBuilder(ErrCodeHttpRequestInvalidStatusCode, "invalid status code").F(jet.KV{"code": code, "detail": detail}).C(ctx).Err()
	}
	ErrHttpRequestReadAll = func(ctx context.Context, cause error) error {
		return jet.NewAppErrBuilder(ErrCodeHttpRequestReadAll, "io: read all failed").Wrap(cause).C(ctx).Err()
	}
	ErrHttpRequestNew = func(ctx context.Context, cause error) error {
		return jet.NewAppErrBuilder(ErrCodeHttpRequestNew, "request create failed").Wrap(cause).C(ctx).Err()
	}
	ErrHttpRequestDo = func(ctx context.Context, cause error) error {
		return jet.NewAppErrBuilder(ErrCodeHttpRequestDo, "request execution failed").Wrap(cause).C(ctx).Err()
	}
	ErrHttpRequestJsonMarshal = func(ctx context.Context, cause error) error {
		return jet.NewAppErrBuilder(ErrCodeHttpRequestJsonMarshal, "json: marshal failed").Wrap(cause).C(ctx).Err()
	}
	ErrHttpCalculateLengthCopy = func(ctx context.Context, cause error) error {
		return jet.NewAppErrBuilder(ErrCodeHttpCalculateLengthCopy, "io: copy failed").Wrap(cause).C(ctx).Err()
	}
	ErrHttpRequestJsonUnmarshal = func(ctx context.Context, cause error) error {
		return jet.NewAppErrBuilder(ErrCodeHttpRequestJsonUnmarshal, "json: unmarshal failed").Wrap(cause).C(ctx).Err()
	}
	ErrHttpRequestWriterWriteField = func(ctx context.Context, cause error) error {
		return jet.NewAppErrBuilder(ErrCodeHttpRequestWriterWriteField, "writer: write failed").Wrap(cause).C(ctx).Err()
	}
	ErrHttpRequestWriterCreate = func(ctx context.Context, cause error) error {
		return jet.NewAppErrBuilder(ErrCodeHttpRequestWriterCreate, "writer: create failed").Wrap(cause).C(ctx).Err()
	}
	ErrHttpRequestWriterCopy = func(ctx context.Context, cause error) error {
		return jet.NewAppErrBuilder(ErrCodeHttpRequestWriterCopy, "writer: copy failed").Wrap(cause).C(ctx).Err()
	}
	ErrHttpRequestWriterClose = func(ctx context.Context, cause error) error {
		return jet.NewAppErrBuilder(ErrCodeHttpRequestWriterClose, "writer: close failed").Wrap(cause).C(ctx).Err()
	}
	ErrHttpRequestEmptyFileData = func(ctx context.Context) error {
		return jet.NewAppErrBuilder(ErrCodeHttpRequestEmptyFileData, "empty file data").Business().C(ctx).Err()
	}
	ErrHttpRequestResponseFuncFailed = func(ctx context.Context, cause error) error {
		return jet.NewAppErrBuilder(ErrCodeHttpRequestResponseFuncFailed, "response fn failed").Wrap(cause).C(ctx).Err()
	}
)
View Source
var EmptyOkResponse = struct {
	Status string `json:"status"`
}{
	Status: "OK",
}
View Source
var MediaContentTypes = [...]string{
	"image/jpeg",
	"image/png",
	"image/bmp",
	"image/gif",
	"image/tiff",
	"video/avi",
	"video/mpeg",
	"video/mp4",
	"audio/mpeg",
	"audio/wav",
}

Functions

func CalculateLength

func CalculateLength(ctx context.Context, reader io.Reader) (io.Reader, int64, error)

func CreateJsonReader

func CreateJsonReader[T any](ctx context.Context, metadata T) (io.Reader, error)

func DecodeRequest

func DecodeRequest[T any](ctx context.Context, r *http.Request) (*T, error)

DecodeRequest is a generic func allowing to unmarshal request

func ParseSortBy

func ParseSortBy(ctx context.Context, sortString string) ([]*jet.SortRequest, error)

ParseSortBy Converts string like "field1 asc first,field2 desc last,field3 desc,field4" to array of SortRequest

Types

type AuthorizationResource

type AuthorizationResource struct {
	Resource    string   `json:"res,omitempty"`   // Resource code
	Permissions []string `json:"perms,omitempty"` // Permissions requested (R, W, X, D)
}

type BaseController

type BaseController struct {
	Logger jet.CLoggerFunc
}

BaseController is a base controller implementation

func (*BaseController) CurrentUser

func (c *BaseController) CurrentUser(ctx context.Context) (uid string, un string, err error)

func (*BaseController) DecodeRequest

func (c *BaseController) DecodeRequest(ctx context.Context, r *http.Request, body interface{}) error

func (*BaseController) FileHeader

func (c *BaseController) FileHeader(ctx context.Context, h *multipart.FileHeader, name string, allowEmpty bool) (string, error)

func (*BaseController) FileHeaderJson

func (c *BaseController) FileHeaderJson(ctx context.Context, h *multipart.FileHeader, name string, allowEmpty bool, data interface{}) error

func (*BaseController) FileHeaderMetadata

func (c *BaseController) FileHeaderMetadata(ctx context.Context, h *multipart.FileHeader, name string, allowEmpty bool) (map[string]string, error)

func (*BaseController) FileHeaderUUID

func (c *BaseController) FileHeaderUUID(ctx context.Context, h *multipart.FileHeader, name string, allowEmpty bool) (string, error)

func (*BaseController) FormPaging

func (c *BaseController) FormPaging(ctx context.Context, r *http.Request, maxPageSize *int) (size *int, index *int, err error)

FormPaging parses URL form value for paging params. Allows specifying max page size

func (*BaseController) FormSort

func (c *BaseController) FormSort(ctx context.Context, r *http.Request) ([]*jet.SortRequest, error)

FormSort parses URL form sorting value for paging params

func (*BaseController) FormVal

func (c *BaseController) FormVal(ctx context.Context, r *http.Request, name string, allowEmpty bool) (string, error)

func (*BaseController) FormValBool

func (c *BaseController) FormValBool(ctx context.Context, r *http.Request, name string, allowEmpty bool) (*bool, error)

func (*BaseController) FormValFloat

func (c *BaseController) FormValFloat(ctx context.Context, r *http.Request, name string, allowEmpty bool) (*float64, error)

func (*BaseController) FormValInt

func (c *BaseController) FormValInt(ctx context.Context, r *http.Request, name string, allowEmpty bool) (*int, error)

func (*BaseController) FormValJson

func (c *BaseController) FormValJson(ctx context.Context, r *http.Request, name string, allowEmpty bool, data interface{}) error

func (*BaseController) FormValList

func (c *BaseController) FormValList(ctx context.Context, r *http.Request, name string, allowEmpty bool) ([]string, error)

func (*BaseController) FormValMetadata

func (c *BaseController) FormValMetadata(ctx context.Context, r *http.Request, name string, allowEmpty bool) (map[string]string, error)

func (*BaseController) FormValTime

func (c *BaseController) FormValTime(ctx context.Context, r *http.Request, name string, allowEmpty bool) (*time.Time, error)

FormValTime parses URL form value and checks for time in RFC3339 format(UTC)

func (*BaseController) FormValUUID

func (c *BaseController) FormValUUID(ctx context.Context, r *http.Request, name string, allowEmpty bool) (string, error)

func (*BaseController) GetUploadFileMultipartContent

func (c *BaseController) GetUploadFileMultipartContent(ctx context.Context, r *http.Request) (io.Reader, string, error)

GetUploadFileMultipartContent it parse body for multipart content disposition it expects the only one part with the following structure: -----------------------------4562559108110960722260982980 Content-Disposition: form-data; name="files"; filename="my-file.jpg" Content-Type: image/jpeg .... .....

func (*BaseController) HasRoles

func (c *BaseController) HasRoles(roles ...string) func(ctx context.Context, r *http.Request) (bool, error)

HasRoles returns true if a current user has the requested roles

func (*BaseController) MyUser

func (c *BaseController) MyUser(ctx context.Context, r *http.Request) (bool, error)

MyUser returns true if current user requests his own data

func (*BaseController) RespondContent

func (c *BaseController) RespondContent(w http.ResponseWriter, r *http.Request, opts ResponseContentOpts, file []byte)

func (*BaseController) RespondCreated

func (c *BaseController) RespondCreated(w http.ResponseWriter, payload interface{})

func (*BaseController) RespondError

func (c *BaseController) RespondError(w http.ResponseWriter, err error)

func (*BaseController) RespondJson

func (c *BaseController) RespondJson(w http.ResponseWriter, httpStatus int, payload interface{})

func (*BaseController) RespondOK

func (c *BaseController) RespondOK(w http.ResponseWriter, payload interface{})

func (*BaseController) RespondWithStatus

func (c *BaseController) RespondWithStatus(w http.ResponseWriter, status int, payload interface{})

func (*BaseController) UserIdVar

func (c *BaseController) UserIdVar(ctx context.Context, r *http.Request, varName string) (string, error)

func (*BaseController) UserNameVar

func (c *BaseController) UserNameVar(ctx context.Context, r *http.Request, varName string) (string, error)

func (*BaseController) Var

func (c *BaseController) Var(ctx context.Context, r *http.Request, varName string, allowEmpty bool) (string, error)

func (*BaseController) VarUUID

func (c *BaseController) VarUUID(ctx context.Context, r *http.Request, varName string, allowEmpty bool) (string, error)

type ConditionFn

type ConditionFn func(context.Context, *http.Request) (bool, error)

type Config

type Config struct {
	Port                 string
	Cors                 *Cors
	Trace                bool
	TraceDetails         *TraceDetails `mapstructure:"trace_details"`
	WriteTimeoutSec      int           `mapstructure:"write_timeout_sec"`
	ReadTimeoutSec       int           `mapstructure:"read_timeout_sec"`
	ReadBufferSizeBytes  int           `mapstructure:"read_buffer_size_bytes"`
	WriteBufferSizeBytes int           `mapstructure:"write_buffer_size_bytes"`
}

type Controller

type Controller interface {
	// MyUser returns true if current user requests his own data
	MyUser(ctx context.Context, r *http.Request) (bool, error)
	// HasRoles returns function which checks if current login has list of roles
	HasRoles(roles ...string) func(ctx context.Context, r *http.Request) (bool, error)
}

Controller is a base controller interface

type Cors

type Cors struct {
	Enabled        bool
	AllowedHeaders []string
	AllowedOrigins []string
	AllowedMethods []string
	Debug          bool
}

type Error

type Error struct {
	Code    string                 `json:"code,omitempty"`    // Code is error code provided by error producer
	Type    string                 `json:"type,omitempty"`    // Type is error type (panic, system, business)
	Message string                 `json:"message"`           // Message is error description
	Details map[string]interface{} `json:"details,omitempty"` // Details is additional info provided by error producer
}

Error is HTTP error object returning to clients in case of error

func (*Error) Error

func (e *Error) Error() string

type File

type File struct {
	Name string    // Name file name
	Data io.Reader // Data file data
}

type HttpClient

type HttpClient interface {
	Do(req *http.Request) (*http.Response, error)
}

type MetricsProvider

type MetricsProvider interface {
	GetCollector() monitoring.MetricsCollector
	RequestErrorInc(ctx context.Context, metric *RequestError)
	RequestLatencySet(ctx context.Context, metric *RequestLatency)
}

func NewRequestMetrics

func NewRequestMetrics(config *monitoring.Config) MetricsProvider

type MultipartRequest

type MultipartRequest struct {
	Body        *bytes.Buffer
	ContentType string
}

func CreateMultipartRequest

func CreateMultipartRequest[T comparable](ctx context.Context, metadata T, files []*File) (rs *MultipartRequest, err error)

func CreateMultipartRequestOnlyFiles

func CreateMultipartRequestOnlyFiles(ctx context.Context, files []*File) (rs *MultipartRequest, err error)

type Proxy

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

Proxy represents HTTP proxy

func NewProxy

func NewProxy(cfg *ProxyConfig) *Proxy

func (*Proxy) AddField

func (p *Proxy) AddField(key, value string) *Proxy

func (*Proxy) AddFile

func (p *Proxy) AddFile(name, fileName string, file io.Reader) *Proxy

func (*Proxy) AddMetadataField

func (p *Proxy) AddMetadataField(key string, value map[string]string) *Proxy

func (*Proxy) Error

func (p *Proxy) Error() error

func (*Proxy) NewRequest

func (p *Proxy) NewRequest() *Proxy

func (*Proxy) POST

func (p *Proxy) POST(ctx context.Context, path string, res any) error

func (*Proxy) PUT

func (p *Proxy) PUT(ctx context.Context, path string, res any) error

type ProxyConfig

type ProxyConfig struct {
	Url string
}

ProxyConfig is proxy http configuration

type Request

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

func NewRq

func NewRq() *Request

func (*Request) AuthBasic

func (r *Request) AuthBasic(user, pass string) *Request

func (*Request) AuthBearer

func (r *Request) AuthBearer(token string) *Request

func (*Request) Cl

func (r *Request) Cl(cl HttpClient) *Request

func (*Request) Connect

func (r *Request) Connect() *Request

func (*Request) ContType

func (r *Request) ContType(content string) *Request

func (*Request) ContentLength

func (r *Request) ContentLength(length int64) *Request

func (*Request) Delete

func (r *Request) Delete() *Request

func (*Request) Do

func (r *Request) Do(ctx context.Context) error

func (*Request) ErrCodeFn

func (r *Request) ErrCodeFn(fn func(ctx context.Context, code int, data []byte) error) *Request

func (*Request) ExtendedLog

func (r *Request) ExtendedLog() *Request

func (*Request) Fn

func (r *Request) Fn(fn func(data []byte) error) *Request

Fn empty fn is default

func (*Request) FnJson

func (r *Request) FnJson(out any) *Request

FnJson sets json function as out parses

func (*Request) Get

func (r *Request) Get() *Request

Get this is default by preset

func (*Request) H

func (r *Request) H(name, value string) *Request

func (*Request) Head

func (r *Request) Head() *Request

func (*Request) Metrics

func (r *Request) Metrics(provider MetricsProvider) *Request

func (*Request) Mth

func (r *Request) Mth(method string) *Request

func (*Request) Name

func (r *Request) Name(name string) *Request

func (*Request) Options

func (r *Request) Options() *Request

func (*Request) Patch

func (r *Request) Patch() *Request

func (*Request) Payload

func (r *Request) Payload(payload io.Reader) *Request

func (*Request) Post

func (r *Request) Post() *Request

func (*Request) Put

func (r *Request) Put() *Request

func (*Request) Stream

func (r *Request) Stream(ctx context.Context) (*StreamReadCloser, error)

func (*Request) Trace

func (r *Request) Trace() *Request

func (*Request) Url

func (r *Request) Url(url fmt.Stringer) *Request

func (*Request) WithLogger

func (r *Request) WithLogger(logger jet.CLogger) *Request

type RequestError

type RequestError struct {
	Url             string
	IntegrationName string
	ErrorCode       int
}

type RequestLatency

type RequestLatency struct {
	Url             string
	IntegrationName string
	LatencyMs       int64
}

type ResourcePolicy

type ResourcePolicy interface {
	// Resolve determines needed authorization resources for the given request
	Resolve(ctx context.Context, r *http.Request) (*AuthorizationResource, error)
}

type ResourcePolicyBuilder

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

func Resource

func Resource(resource string, permissions string) *ResourcePolicyBuilder

func (*ResourcePolicyBuilder) B

func (*ResourcePolicyBuilder) Resolve

func (*ResourcePolicyBuilder) When

func (*ResourcePolicyBuilder) WhenNot

type ResourcePolicyManager

type ResourcePolicyManager interface {
	// RegisterResourceMapping maps routeId and resource policies
	RegisterResourceMapping(routeId string, policies ...ResourcePolicy)
	// GetRequestedResources resolves policies and retrieves accumulated resources requested to be authorized
	GetRequestedResources(ctx context.Context, routeId string, r *http.Request) ([]*AuthorizationResource, error)
}

ResourcePolicyManager accumulates mapping between URLs and requested resources and then convert it to Authorization request

func NewResourcePolicyManager

func NewResourcePolicyManager() ResourcePolicyManager

type ResponseContentOpts

type ResponseContentOpts struct {
	Filename     string
	ContentType  string
	ContentSize  int
	Download     bool
	ModifiedTime time.Time
}

type RouteSetter

type RouteSetter interface {
	Set() error
}

type Server

type Server struct {
	Srv        *http.Server        // Srv - internal server
	RootRouter *mux.Router         // RootRouter - root router
	WsUpgrader *websocket.Upgrader // WsUpgrader - websocket upgrader
	// contains filtered or unexported fields
}

Server represents HTTP server

func NewHttpServer

func NewHttpServer(cfg *Config, logger jet.CLoggerFunc) *Server
Example
package main

import (
	"github.com/zloevil/jet"
	"github.com/zloevil/jet/http"
)

func main() {
	logFn := func() jet.CLogger { return jet.L(jet.InitLogger(&jet.LogConfig{Level: jet.InfoLevel})) }

	srv := http.NewHttpServer(&http.Config{Port: "8080"}, logFn)
	srv.Listen()
	defer srv.Close()

	// register routes on srv.RootRouter
	_ = srv.RootRouter
}

func (*Server) Close

func (s *Server) Close()

func (*Server) Listen

func (s *Server) Listen()

func (*Server) SetWsUpgrader

func (s *Server) SetWsUpgrader(upgradeSetter WsUpgrader)

type StreamReadCloser

type StreamReadCloser struct {
	Content       io.ReadCloser // Content should be closed by the client's method externally
	ContentLength int64         // ContentLength records the length of the associated content.
}

func (*StreamReadCloser) Close

func (s *StreamReadCloser) Close() error

type TestRequest

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

TestRequest simplifies testing of controller methods it provides fluent API to prepare and make mock request

func NewTestRequest

func NewTestRequest(ts *testing.T, ctx context.Context) *TestRequest

NewTestRequest creates a new test HTTP request

func (*TestRequest) AssertAppError

func (t *TestRequest) AssertAppError(code string) *TestRequest

AssertAppError assert application error with given code

func (*TestRequest) AssertCode

func (t *TestRequest) AssertCode(code int) *TestRequest

AssertCode asserts given http code

func (*TestRequest) AssertOk

func (t *TestRequest) AssertOk() *TestRequest

AssertOk asserts HTTP code is OK

func (*TestRequest) DELETE

func (t *TestRequest) DELETE() *TestRequest

func (*TestRequest) GET

func (t *TestRequest) GET() *TestRequest

func (*TestRequest) Header

func (t *TestRequest) Header(key, value string) *TestRequest

Header allows define Header parameter

func (*TestRequest) Make

func (t *TestRequest) Make(controllerFn func(w http.ResponseWriter, r *http.Request))

Make makes a request with all specified params It returns 1: http code 2: response body

func (*TestRequest) POST

func (t *TestRequest) POST() *TestRequest

func (*TestRequest) PUT

func (t *TestRequest) PUT() *TestRequest

func (*TestRequest) RqBody

func (t *TestRequest) RqBody(rq interface{}) *TestRequest

RqBody allows defining request body if any

func (*TestRequest) RsBody

func (t *TestRequest) RsBody(rs interface{}) *TestRequest

RsBody allows pass a variable of expected response type, so that response body is unmarshalled to this variable

func (*TestRequest) Url

func (t *TestRequest) Url(url string) *TestRequest

func (*TestRequest) Var

func (t *TestRequest) Var(key, value string) *TestRequest

Var allows define URL parameters

type TraceDetails

type TraceDetails struct {
	RequestBody  bool `mapstructure:"request_body"` // RequestBody if true, to trace full request with body. Otherwise, body isn't traced
	Response     bool // Response if true, to trace response (can have significant impact on logging volume and performance)
	ResponseBody bool `mapstructure:"response_body"` // ResponseBody if true, to trace full response with body. Otherwise, body isn't traced
}

type Url

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

func NewUrl

func NewUrl() *Url

func (*Url) Params

func (u *Url) Params(params map[string]string) *Url

func (*Url) Path

func (u *Url) Path(path string) *Url

func (*Url) Pathf

func (u *Url) Pathf(path string, a ...any) *Url

func (*Url) String

func (u *Url) String() string

func (*Url) Url

func (u *Url) Url(url string) *Url

type WsUpgrader

type WsUpgrader interface {
	Set(router *mux.Router, upgrader *websocket.Upgrader)
}

Jump to

Keyboard shortcuts

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