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 ¶
- Constants
- Variables
- func CalculateLength(ctx context.Context, reader io.Reader) (io.Reader, int64, error)
- func CreateJsonReader[T any](ctx context.Context, metadata T) (io.Reader, error)
- func DecodeRequest[T any](ctx context.Context, r *http.Request) (*T, error)
- func ParseSortBy(ctx context.Context, sortString string) ([]*jet.SortRequest, error)
- type AuthorizationResource
- type BaseController
- func (c *BaseController) CurrentUser(ctx context.Context) (uid string, un string, err error)
- func (c *BaseController) DecodeRequest(ctx context.Context, r *http.Request, body interface{}) error
- func (c *BaseController) FileHeader(ctx context.Context, h *multipart.FileHeader, name string, allowEmpty bool) (string, error)
- func (c *BaseController) FileHeaderJson(ctx context.Context, h *multipart.FileHeader, name string, allowEmpty bool, ...) error
- func (c *BaseController) FileHeaderMetadata(ctx context.Context, h *multipart.FileHeader, name string, allowEmpty bool) (map[string]string, error)
- func (c *BaseController) FileHeaderUUID(ctx context.Context, h *multipart.FileHeader, name string, allowEmpty bool) (string, error)
- func (c *BaseController) FormPaging(ctx context.Context, r *http.Request, maxPageSize *int) (size *int, index *int, err error)
- func (c *BaseController) FormSort(ctx context.Context, r *http.Request) ([]*jet.SortRequest, error)
- func (c *BaseController) FormVal(ctx context.Context, r *http.Request, name string, allowEmpty bool) (string, error)
- func (c *BaseController) FormValBool(ctx context.Context, r *http.Request, name string, allowEmpty bool) (*bool, error)
- func (c *BaseController) FormValFloat(ctx context.Context, r *http.Request, name string, allowEmpty bool) (*float64, error)
- func (c *BaseController) FormValInt(ctx context.Context, r *http.Request, name string, allowEmpty bool) (*int, error)
- func (c *BaseController) FormValJson(ctx context.Context, r *http.Request, name string, allowEmpty bool, ...) error
- func (c *BaseController) FormValList(ctx context.Context, r *http.Request, name string, allowEmpty bool) ([]string, error)
- func (c *BaseController) FormValMetadata(ctx context.Context, r *http.Request, name string, allowEmpty bool) (map[string]string, error)
- func (c *BaseController) FormValTime(ctx context.Context, r *http.Request, name string, allowEmpty bool) (*time.Time, error)
- func (c *BaseController) FormValUUID(ctx context.Context, r *http.Request, name string, allowEmpty bool) (string, error)
- func (c *BaseController) GetUploadFileMultipartContent(ctx context.Context, r *http.Request) (io.Reader, string, error)
- func (c *BaseController) HasRoles(roles ...string) func(ctx context.Context, r *http.Request) (bool, error)
- func (c *BaseController) MyUser(ctx context.Context, r *http.Request) (bool, error)
- func (c *BaseController) RespondContent(w http.ResponseWriter, r *http.Request, opts ResponseContentOpts, file []byte)
- func (c *BaseController) RespondCreated(w http.ResponseWriter, payload interface{})
- func (c *BaseController) RespondError(w http.ResponseWriter, err error)
- func (c *BaseController) RespondJson(w http.ResponseWriter, httpStatus int, payload interface{})
- func (c *BaseController) RespondOK(w http.ResponseWriter, payload interface{})
- func (c *BaseController) RespondWithStatus(w http.ResponseWriter, status int, payload interface{})
- func (c *BaseController) UserIdVar(ctx context.Context, r *http.Request, varName string) (string, error)
- func (c *BaseController) UserNameVar(ctx context.Context, r *http.Request, varName string) (string, error)
- func (c *BaseController) Var(ctx context.Context, r *http.Request, varName string, allowEmpty bool) (string, error)
- func (c *BaseController) VarUUID(ctx context.Context, r *http.Request, varName string, allowEmpty bool) (string, error)
- type ConditionFn
- type Config
- type Controller
- type Cors
- type Error
- type File
- type HttpClient
- type MetricsProvider
- type MultipartRequest
- type Proxy
- func (p *Proxy) AddField(key, value string) *Proxy
- func (p *Proxy) AddFile(name, fileName string, file io.Reader) *Proxy
- func (p *Proxy) AddMetadataField(key string, value map[string]string) *Proxy
- func (p *Proxy) Error() error
- func (p *Proxy) NewRequest() *Proxy
- func (p *Proxy) POST(ctx context.Context, path string, res any) error
- func (p *Proxy) PUT(ctx context.Context, path string, res any) error
- type ProxyConfig
- type Request
- func (r *Request) AuthBasic(user, pass string) *Request
- func (r *Request) AuthBearer(token string) *Request
- func (r *Request) Cl(cl HttpClient) *Request
- func (r *Request) Connect() *Request
- func (r *Request) ContType(content string) *Request
- func (r *Request) ContentLength(length int64) *Request
- func (r *Request) Delete() *Request
- func (r *Request) Do(ctx context.Context) error
- func (r *Request) ErrCodeFn(fn func(ctx context.Context, code int, data []byte) error) *Request
- func (r *Request) ExtendedLog() *Request
- func (r *Request) Fn(fn func(data []byte) error) *Request
- func (r *Request) FnJson(out any) *Request
- func (r *Request) Get() *Request
- func (r *Request) H(name, value string) *Request
- func (r *Request) Head() *Request
- func (r *Request) Metrics(provider MetricsProvider) *Request
- func (r *Request) Mth(method string) *Request
- func (r *Request) Name(name string) *Request
- func (r *Request) Options() *Request
- func (r *Request) Patch() *Request
- func (r *Request) Payload(payload io.Reader) *Request
- func (r *Request) Post() *Request
- func (r *Request) Put() *Request
- func (r *Request) Stream(ctx context.Context) (*StreamReadCloser, error)
- func (r *Request) Trace() *Request
- func (r *Request) Url(url fmt.Stringer) *Request
- func (r *Request) WithLogger(logger jet.CLogger) *Request
- type RequestError
- type RequestLatency
- type ResourcePolicy
- type ResourcePolicyBuilder
- func (a *ResourcePolicyBuilder) B() ResourcePolicy
- func (a *ResourcePolicyBuilder) Resolve(ctx context.Context, r *http.Request) (*AuthorizationResource, error)
- func (a *ResourcePolicyBuilder) When(f ...ConditionFn) *ResourcePolicyBuilder
- func (a *ResourcePolicyBuilder) WhenNot(f ...ConditionFn) *ResourcePolicyBuilder
- type ResourcePolicyManager
- type ResponseContentOpts
- type RouteSetter
- type Server
- type StreamReadCloser
- type TestRequest
- func (t *TestRequest) AssertAppError(code string) *TestRequest
- func (t *TestRequest) AssertCode(code int) *TestRequest
- func (t *TestRequest) AssertOk() *TestRequest
- func (t *TestRequest) DELETE() *TestRequest
- func (t *TestRequest) GET() *TestRequest
- func (t *TestRequest) Header(key, value string) *TestRequest
- func (t *TestRequest) Make(controllerFn func(w http.ResponseWriter, r *http.Request))
- func (t *TestRequest) POST() *TestRequest
- func (t *TestRequest) PUT() *TestRequest
- func (t *TestRequest) RqBody(rq interface{}) *TestRequest
- func (t *TestRequest) RsBody(rs interface{}) *TestRequest
- func (t *TestRequest) Url(url string) *TestRequest
- func (t *TestRequest) Var(key, value string) *TestRequest
- type TraceDetails
- type Url
- type WsUpgrader
Examples ¶
Constants ¶
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" )
const ( RequestMetricsLatencyMsGaugeName = "request_metrics_latency_ms_gauge" RequestMetricsErrorCounterName = "request_metrics_error_counter" RequestMetricsLabelUrl = "url" RequestMetricsLabelIntegrationName = "name" RequestMetricsLabelErrorCodeName = "code" )
const ( R = "r" // R read W = "w" // W write X = "x" // X execute D = "d" // D delete )
const ( Authorization = "Authorization" ContentType = "Content-Type" )
const (
Me = "me" // Me can be used in URL whenever userId is expected. When encountered, userId from the session context is used
)
Variables ¶
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() } )
var EmptyOkResponse = struct { Status string `json:"status"` }{ Status: "OK", }
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 CreateJsonReader ¶
func DecodeRequest ¶
DecodeRequest is a generic func allowing to unmarshal request
func ParseSortBy ¶
ParseSortBy Converts string like "field1 asc first,field2 desc last,field3 desc,field4" to array of SortRequest
Types ¶
type AuthorizationResource ¶
type BaseController ¶
type BaseController struct {
Logger jet.CLoggerFunc
}
BaseController is a base controller implementation
func (*BaseController) CurrentUser ¶
func (*BaseController) DecodeRequest ¶
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) FormValBool ¶
func (*BaseController) FormValFloat ¶
func (*BaseController) FormValInt ¶
func (*BaseController) FormValJson ¶
func (*BaseController) FormValList ¶
func (*BaseController) FormValMetadata ¶
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 (*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) 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) UserNameVar ¶
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 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
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 ¶
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) AddMetadataField ¶
func (*Proxy) NewRequest ¶
type Request ¶
type Request struct {
// contains filtered or unexported fields
}
func (*Request) AuthBearer ¶
func (*Request) Cl ¶
func (r *Request) Cl(cl HttpClient) *Request
func (*Request) ContentLength ¶
func (*Request) ExtendedLog ¶
func (*Request) Metrics ¶
func (r *Request) Metrics(provider MetricsProvider) *Request
type RequestError ¶
type RequestLatency ¶
type ResourcePolicy ¶
type ResourcePolicyBuilder ¶
type ResourcePolicyBuilder struct {
// contains filtered or unexported fields
}
func Resource ¶
func Resource(resource string, permissions string) *ResourcePolicyBuilder
func (*ResourcePolicyBuilder) B ¶
func (a *ResourcePolicyBuilder) B() ResourcePolicy
func (*ResourcePolicyBuilder) Resolve ¶
func (a *ResourcePolicyBuilder) Resolve(ctx context.Context, r *http.Request) (*AuthorizationResource, error)
func (*ResourcePolicyBuilder) When ¶
func (a *ResourcePolicyBuilder) When(f ...ConditionFn) *ResourcePolicyBuilder
func (*ResourcePolicyBuilder) WhenNot ¶
func (a *ResourcePolicyBuilder) WhenNot(f ...ConditionFn) *ResourcePolicyBuilder
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 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
}
Output:
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
}