Documentation ¶
Overview ¶
Package restapi provides a set of helpers to implement REST API following Acronis REST API Guidelines.
Index ¶
- Constants
- Variables
- func DecodeRequestJSON(r *http.Request, dst interface{}) error
- func DecodeRequestJSONStrict(r *http.Request, dst interface{}, disallowUnknownFields bool) error
- func DisableWrappingErrorInResponse()
- func DoRequest(client *http.Client, req *http.Request, logger log.FieldLogger) (*http.Response, error)
- func DoRequestAndUnmarshalJSON(client *http.Client, req *http.Request, result interface{}, ...) error
- func MustInitAndRegisterMetrics(namespace string)
- func NewJSONRequest(method, url string, data interface{}) (*http.Request, error)
- func NormalizeURLPath(urlPath string) string
- func RespondCodeAndJSON(rw http.ResponseWriter, statusCode int, respData interface{}, ...)
- func RespondError(rw http.ResponseWriter, httpStatusCode int, err *Error, logger log.FieldLogger)
- func RespondInternalError(rw http.ResponseWriter, domain string, logger log.FieldLogger)
- func RespondJSON(rw http.ResponseWriter, respData interface{}, logger log.FieldLogger)
- func RespondMalformedRequestError(rw http.ResponseWriter, domain string, reqErr *MalformedRequestError, ...)
- func RespondMalformedRequestOrInternalError(rw http.ResponseWriter, domain string, err error, logger log.FieldLogger)
- func RespondNoWrappedError(rw http.ResponseWriter, httpStatusCode int, err *Error, logger log.FieldLogger)
- func RespondWrappedError(rw http.ResponseWriter, httpStatusCode int, err *Error, logger log.FieldLogger)
- func SetRequestMaxBodySize(w http.ResponseWriter, r *http.Request, maxSizeBytes uint64)
- func UnregisterMetrics()
- type ClientError
- type Error
- type ErrorResponseData
- type KBLinkInfo
- type MalformedRequestError
- type RequestBodyTooLargeError
- type Route
- type RouteConfig
- type RoutePath
- type RoutesManager
Examples ¶
Constants ¶
const ContentTypeAppJSON = "application/json"
ContentTypeAppJSON represents MIME media type for JSON.
const ContentTypeAppSCIMJSON = "application/scim+json"
ContentTypeAppSCIMJSON represents MIME media type for SCIM JSON.
Variables ¶
var ( ErrCodeInternal = "internalError" ErrCodeNotFound = "notFound" ErrCodeMethodNotAllowed = "methodNotAllowed" )
Error codes. We are using "var" here because some services may want to use different error codes.
var ( ErrMessageInternal = "Internal error." ErrMessageNotFound = "Not found." ErrMessageMethodNotAllowed = "Method not allowed." )
Error messages. We are using "var" here because some services may want to use different error messages.
Functions ¶
func DecodeRequestJSON ¶
DecodeRequestJSON tries to read request body and decode it as JSON.
Example ¶
type User struct { Name string `json:"name"` Age int `json:"age"` } const domain = "MyService" http.HandleFunc("/endpoint", func(w http.ResponseWriter, r *http.Request) { var user User if err := DecodeRequestJSON(r, &user); err != nil { logger := log.NewDisabledLogger() var reqErr *MalformedRequestError if errors.As(err, &reqErr) { RespondMalformedRequestError(w, domain, reqErr, logger) return } RespondError(w, http.StatusInternalServerError, NewInternalError(domain), logger) return } })
Output:
func DecodeRequestJSONStrict ¶
DecodeRequestJSONStrict tries to read and validate request fields in body and decode it as JSON.
func DisableWrappingErrorInResponse ¶
func DisableWrappingErrorInResponse()
DisableWrappingErrorInResponse disables wrapping error ({"error": {"domain": "{domain}", ...} -> {"domain": "{domain}", ...}) in response body.
func DoRequest ¶
func DoRequest(client *http.Client, req *http.Request, logger log.FieldLogger) (*http.Response, error)
DoRequest allows to do HTTP requests and log some its details
func DoRequestAndUnmarshalJSON ¶
func DoRequestAndUnmarshalJSON(client *http.Client, req *http.Request, result interface{}, logger log.FieldLogger) error
DoRequestAndUnmarshalJSON allows doing HTTP requests, log some its details and unmarshal response
func MustInitAndRegisterMetrics ¶
func MustInitAndRegisterMetrics(namespace string)
MustInitAndRegisterMetrics initializes and registers restapi global metrics. Panic will be raised in case of error.
func NewJSONRequest ¶
NewJSONRequest performs JSON marshaling of the passed data and creates a new http.Request
func NormalizeURLPath ¶
NormalizeURLPath normalizes URL path (i.e. for example, it convert /foo///bar/.. to /foo).
func RespondCodeAndJSON ¶
func RespondCodeAndJSON(rw http.ResponseWriter, statusCode int, respData interface{}, logger log.FieldLogger)
RespondCodeAndJSON sends a response with the passed status code and sets the "Content-Type" to "application/json" if it's not already set. It performs JSON marshaling of the data and writes the result to the response's body.
func RespondError ¶
func RespondError(rw http.ResponseWriter, httpStatusCode int, err *Error, logger log.FieldLogger)
RespondError sets HTTP status code in response and writes error in body in JSON format. Also, it logs info (code and message) about error.
Example ¶
http.HandleFunc("/endpoint", func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { apiErr := NewError("MyService", "methodNotAllowed", "Only GET HTTP method is allowed.") RespondError(w, http.StatusMethodNotAllowed, apiErr, log.NewDisabledLogger()) return } })
Output:
func RespondInternalError ¶
func RespondInternalError(rw http.ResponseWriter, domain string, logger log.FieldLogger)
RespondInternalError sends response with 500 HTTP status code and internal error in body in JSON format.
func RespondJSON ¶
func RespondJSON(rw http.ResponseWriter, respData interface{}, logger log.FieldLogger)
RespondJSON sends response with 200 HTTP status code, does JSON marshaling of data and writes result in response's body.
Example ¶
http.HandleFunc("/endpoint", func(w http.ResponseWriter, r *http.Request) { type User struct { Name string `json:"name"` Age int `json:"age"` } RespondJSON(w, &User{Name: "Bob", Age: 12}, log.NewDisabledLogger()) })
Output:
func RespondMalformedRequestError ¶
func RespondMalformedRequestError(rw http.ResponseWriter, domain string, reqErr *MalformedRequestError, logger log.FieldLogger)
RespondMalformedRequestError creates Error from passed MalformedRequestError and then call RespondError.
func RespondMalformedRequestOrInternalError ¶
func RespondMalformedRequestOrInternalError(rw http.ResponseWriter, domain string, err error, logger log.FieldLogger)
RespondMalformedRequestOrInternalError calls RespondMalformedRequestError (if passed error is *MalformedRequestError) or RespondInternalError (in other cases).
func RespondNoWrappedError ¶
func RespondNoWrappedError(rw http.ResponseWriter, httpStatusCode int, err *Error, logger log.FieldLogger)
RespondNoWrappedError sets HTTP status code in response and writes non-wrapped error in body in JSON format. Also, it logs info (code and message) about error.
func RespondWrappedError ¶
func RespondWrappedError(rw http.ResponseWriter, httpStatusCode int, err *Error, logger log.FieldLogger)
RespondWrappedError sets HTTP status code in response and writes wrapped error in body in JSON format. Also, it logs info (code and message) about error.
func SetRequestMaxBodySize ¶
func SetRequestMaxBodySize(w http.ResponseWriter, r *http.Request, maxSizeBytes uint64)
SetRequestMaxBodySize wraps request body with a reader which limit the number of bytes to read. RequestBodyTooLargeError will be returned when maxSizeBytes is exceeded.
func UnregisterMetrics ¶
func UnregisterMetrics()
UnregisterMetrics unregisters restapi global metrics.
Types ¶
type ClientError ¶
ClientError - error that can be returned in request to client
func (*ClientError) Is ¶
func (e *ClientError) Is(target error) bool
Is - allow check it with errors.Is
func (*ClientError) Unwrap ¶
func (e *ClientError) Unwrap() error
Unwrap - allow check it with errors.As
type Error ¶
type Error struct { Domain string `json:"domain"` Code string `json:"code"` Message string `json:"message,omitempty"` Context map[string]interface{} `json:"context,omitempty"` KbLink *KBLinkInfo `json:"kbLink,omitempty"` Debug map[string]interface{} `json:"debug,omitempty"` }
Error represents an error details.
func NewInternalError ¶
NewInternalError creates a new internal error with specified domain.
func (*Error) AddContext ¶
AddContext adds value to error context.
type ErrorResponseData ¶
type ErrorResponseData struct {
Err *Error `json:"error"`
}
ErrorResponseData is used for answer on requests with error
func (*ErrorResponseData) Error ¶
func (e *ErrorResponseData) Error() string
type KBLinkInfo ¶
type KBLinkInfo struct { LineTag string `json:"lineTag,omitempty"` SerCode string `json:"serCode,omitempty"` Version string `json:"version,omitempty"` Build string `json:"build,omitempty"` Product string `json:"product,omitempty"` Os string `json:"os,omitempty"` }
KBLinkInfo represents an info about item in Acronis Knowledge Base.
type MalformedRequestError ¶
MalformedRequestError is an error that occurs in case of incorrect request.
func NewTooLargeMalformedRequestError ¶
func NewTooLargeMalformedRequestError(maxSizeBytes uint64) *MalformedRequestError
NewTooLargeMalformedRequestError creates a new MalformedRequestError for case when request body is too large.
func (*MalformedRequestError) Error ¶
func (e *MalformedRequestError) Error() string
Error returns a string representation of MalformedRequestError.
type RequestBodyTooLargeError ¶
RequestBodyTooLargeError represents an error that occurs when read number of bytes (HTTP request body) exceeds the specified limit.
func (*RequestBodyTooLargeError) Error ¶
func (e *RequestBodyTooLargeError) Error() string
Error returns a string representation of RequestBodyTooLargeError.
type Route ¶
type Route struct { Path RoutePath Methods []string Handler http.Handler Middlewares []func(http.Handler) http.Handler Excluded bool // Set to true for routes that are matched to be excluded. }
Route represents route for handling.
func NewExcludedRoute ¶
func NewExcludedRoute(cfg RouteConfig) Route
NewExcludedRoute returns a new route that will be used as exclusion in matching.
type RouteConfig ¶
type RouteConfig struct { // Path is a struct that contains info about route path. // ParseRoutePath function should be used for constructing it from the string representation. Path RoutePath `mapstructure:"path"` // Methods is a list of case-insensitive HTTP verbs/methods. Methods []string `mapstructure:"methods"` }
RouteConfig represents route's configuration.
func (*RouteConfig) MethodsInUpperCase ¶
func (r *RouteConfig) MethodsInUpperCase() []string
MethodsInUpperCase returns list of route's methods in upper-case.
func (*RouteConfig) Validate ¶
func (r *RouteConfig) Validate() error
Validate validates RouteConfig
type RoutePath ¶
type RoutePath struct { Raw string NormalizedPath string RegExpPath *regexp.Regexp ExactMatch bool ForwardMatch bool }
RoutePath represents route's path.
func ParseRoutePath ¶
ParseRoutePath parses string representation of route's path. Syntax: [ = | ~ | ^~ ] urlPath Semantic for modifier is used the same as in Nginx (https://nginx.org/en/docs/http/ngx_http_core_module.html#location).
func (*RoutePath) UnmarshalText ¶
UnmarshalText implements the encoding.TextUnmarshaler interface.
type RoutesManager ¶
type RoutesManager struct {
// contains filtered or unexported fields
}
RoutesManager contains routes for handling and allows to search among them.
func NewRoutesManager ¶
func NewRoutesManager(routes []Route) *RoutesManager
NewRoutesManager create new RoutesManager.
func (*RoutesManager) SearchMatchedRouteForRequest ¶
func (r *RoutesManager) SearchMatchedRouteForRequest(req *http.Request) (Route, bool)
SearchMatchedRouteForRequest searches Route that matches the passing http.Request. Algorithm is the same as used in Nginx for locations matching (https://nginx.org/en/docs/http/ngx_http_core_module.html#location). Excluded routes has priority.
func (*RoutesManager) SearchRoute ¶
func (r *RoutesManager) SearchRoute(normalizedPath string, method string, excluded bool) (Route, bool)
SearchRoute searches Route by passed path and method. Path should be normalized (see NormalizeURLPath for this). If the excluded arg is true, search will be done only among excluded routes. If false - only among included routes. nolint:gocyclo