Documentation ¶
Index ¶
- Constants
- Variables
- func AuthWall(authorizedRoles ...string) func(next http.Handler) http.Handler
- func AuthWallRegex(acceptedRolesRegex string) func(next http.Handler) http.Handler
- func AuthWallRegexp(acceptedRolesRegex *regexp.Regexp) func(next http.Handler) http.Handler
- func DefaultOpenAPIHandler(specURL string) http.Handler
- func ErrorHandler(err error) error
- func GetToken[T any](ctx context.Context) (T, error)
- func HTTPHandler[ReturnType, Body any, Contextable ctx[Body]](s *Server, controller func(c Contextable) (ReturnType, error)) http.HandlerFunc
- func InferAcceptHeaderFromType(ans any) string
- func NewOpenApiSpec() openapi3.T
- func ReadJSON[B any](context context.Context, input io.Reader) (B, error)
- func ReadString[B ~string](context context.Context, input io.Reader) (B, error)
- func ReadURLEncoded[B any](r *http.Request) (B, error)
- func ReadXML[B any](context context.Context, input io.Reader) (B, error)
- func ReadYAML[B any](context context.Context, input io.Reader) (B, error)
- func RegisterOpenAPIOperation[T, B any](group *RouterGroup, route Route[T, B]) (*openapi3.Operation, error)
- func Send(w http.ResponseWriter, r *http.Request, ans any) (err error)
- func SendHTMLError(w http.ResponseWriter, _ *http.Request, err error)
- func SendJSONError(w http.ResponseWriter, _ *http.Request, err error)
- func SendText(w http.ResponseWriter, _ *http.Request, ans any) error
- func SendTextError(w http.ResponseWriter, _ *http.Request, err error)
- func SendXMLError(w http.ResponseWriter, _ *http.Request, err error)
- func SendYAMLError(w http.ResponseWriter, _ *http.Request, err error)
- func TokenFromContext(ctx context.Context) (jwt.Claims, error)
- func TokenFromCookie(r *http.Request) string
- func TokenFromHeader(r *http.Request) string
- func TokenFromQueryParam(r *http.Request) string
- func Use(s *RouterGroup, middlewares ...func(http.Handler) http.Handler)
- func UseStd(s *RouterGroup, middlewares ...func(http.Handler) http.Handler)
- func WithAutoAuth(verifyUserInfo func(user, password string) (jwt.Claims, error)) func(*Server)
- func WithCorsMiddleware(corsMiddleware func(http.Handler) http.Handler) func(*Server)
- func WithDisallowUnknownFields(b bool) func(*Server)
- func WithErrorHandler(errorHandler func(err error) error) func(*Server)
- func WithErrorSerializer(serializer ErrorSender) func(*Server)
- func WithGlobalResponseTypes(code int, description string, errorType ...any) func(*Server)
- func WithLogHandler(handler slog.Handler) func(*Server)
- func WithMaxBodySize(maxBodySize int64) func(*Server)
- func WithSerializer(serializer Sender) func(*Server)
- func WithTemplateFS(fs fs.FS) func(*Server)
- func WithTemplateGlobs(patterns ...string) func(*Server)
- func WithTemplates(templates *template.Template) func(*Server)
- func WithValidator(newValidator *validator.Validate) func(*Server)
- func WithValue(ctx context.Context, val any) context.Context
- func WithXML() func(*Server)deprecated
- func WithoutAutoGroupTags() func(*Server)
- func WithoutLogger() func(*Server)
- func WithoutStartupMessages() func(*Server)
- type AutoAuthConfig
- type BadRequestError
- type ConflictError
- type ContextNoBody
- func (c ContextNoBody) Body() (any, error)
- func (c ContextNoBody) Context() context.Context
- func (c ContextNoBody) Cookie(name string) (*http.Cookie, error)
- func (c ContextNoBody) Deadline() (deadline time.Time, ok bool)
- func (c ContextNoBody) Done() <-chan struct{}
- func (c ContextNoBody) Err() error
- func (c ContextNoBody) Header(key string) string
- func (c ContextNoBody) MainLang() string
- func (c ContextNoBody) MainLocale() string
- func (c ContextNoBody) MustBody() any
- func (c ContextNoBody) PathParam(name string) string
- func (c ContextNoBody) QueryParam(name string) string
- func (c ContextNoBody) QueryParamArr(name string) []string
- func (c ContextNoBody) QueryParamBool(name string, defaultValue bool) bool
- func (c ContextNoBody) QueryParamBoolErr(name string) (bool, error)
- func (c ContextNoBody) QueryParamInt(name string, defaultValue int) int
- func (c ContextNoBody) QueryParamIntErr(name string) (int, error)
- func (c ContextNoBody) QueryParams() url.Values
- func (c ContextNoBody) Redirect(code int, url string) (any, error)
- func (c ContextNoBody) Render(templateToExecute string, data any, layoutsGlobs ...string) (CtxRenderer, error)
- func (c ContextNoBody) Request() *http.Request
- func (c ContextNoBody) Response() http.ResponseWriter
- func (c ContextNoBody) SetCookie(cookie http.Cookie)
- func (c ContextNoBody) SetHeader(key, value string)
- func (c ContextNoBody) SetStatus(code int)
- func (c ContextNoBody) Value(key any) any
- type ContextWithBody
- type CtxRenderer
- type DataOrTemplate
- func (m DataOrTemplate[T]) MarshalJSON() ([]byte, error)
- func (m DataOrTemplate[T]) MarshalXML(e *xml.Encoder, _ xml.StartElement) error
- func (m DataOrTemplate[T]) MarshalYAML() (interface{}, error)
- func (m DataOrTemplate[T]) Render(c context.Context, w io.Writer) error
- func (m DataOrTemplate[T]) String() string
- type ErrorItem
- type ErrorSender
- type ErrorWithStatus
- type ForbiddenError
- type Gomponent
- type GroupOption
- type H
- type HTML
- type HTTPError
- type InTransformer
- type LoginPayload
- type NotFoundError
- type OpenAPIConfig
- type OpenAPIDescriptioner
- type OpenAPIParam
- type OpenAPIParamOption
- type OutTransformer
- type ParamType
- type QueryParamInvalidTypeError
- type QueryParamNotFoundError
- type Renderer
- type Route
- func All[T, B any, Contexted ctx[B]](s *RouterGroup, path string, controller func(Contexted) (T, error), ...) Route[T, B]
- func AllStd(s *RouterGroup, path string, ...) Route[any, any]
- func Delete[T, B any, Contexted ctx[B]](s *RouterGroup, path string, controller func(Contexted) (T, error), ...) Route[T, B]
- func DeleteStd(s *RouterGroup, path string, ...) Route[any, any]
- func Get[T, B any, Contexted ctx[B]](s *RouterGroup, path string, controller func(Contexted) (T, error), ...) Route[T, B]
- func GetStd(s *RouterGroup, path string, ...) Route[any, any]
- func Handle(s *RouterGroup, path string, controller http.Handler, ...) Route[any, any]
- func Patch[T, B any, Contexted ctx[B]](s *RouterGroup, path string, controller func(Contexted) (T, error), ...) Route[T, B]
- func PatchStd(s *RouterGroup, path string, ...) Route[any, any]
- func Post[T, B any, Contexted ctx[B]](s *RouterGroup, path string, controller func(Contexted) (T, error), ...) Route[T, B]
- func PostStd(s *RouterGroup, path string, ...) Route[any, any]
- func Put[T, B any, Contexted ctx[B]](s *RouterGroup, path string, controller func(Contexted) (T, error), ...) Route[T, B]
- func PutStd(s *RouterGroup, path string, ...) Route[any, any]
- func Register[T, B any](group *RouterGroup, route Route[T, B], controller http.Handler, ...) Route[T, B]
- func (r Route[ResponseBody, RequestBody]) AddError(code int, description string, errorType ...any) Route[ResponseBody, RequestBody]
- func (r Route[ResponseBody, RequestBody]) AddTags(tags ...string) Route[ResponseBody, RequestBody]
- func (r Route[ResponseBody, RequestBody]) Cookie(name, description string, params ...OpenAPIParamOption) Route[ResponseBody, RequestBody]
- func (r Route[ResponseBody, RequestBody]) Deprecated() Route[ResponseBody, RequestBody]
- func (r Route[ResponseBody, RequestBody]) Description(description string) Route[ResponseBody, RequestBody]
- func (r Route[ResponseBody, RequestBody]) Header(name, description string, params ...OpenAPIParamOption) Route[ResponseBody, RequestBody]
- func (r Route[ResponseBody, RequestBody]) OperationID(operationID string) Route[ResponseBody, RequestBody]
- func (r Route[ResponseBody, RequestBody]) Param(paramType ParamType, name, description string, params ...OpenAPIParamOption) Route[ResponseBody, RequestBody]
- func (r Route[ResponseBody, RequestBody]) QueryParam(name, description string, params ...OpenAPIParamOption) Route[ResponseBody, RequestBody]
- func (r Route[ResponseBody, RequestBody]) RemoveTags(tags ...string) Route[ResponseBody, RequestBody]
- func (r Route[ResponseBody, RequestBody]) RequestContentType(consumes ...string) Route[ResponseBody, RequestBody]
- func (r Route[ResponseBody, RequestBody]) Summary(summary string) Route[ResponseBody, RequestBody]
- func (r Route[ResponseBody, RequestBody]) Tags(tags ...string) Route[ResponseBody, RequestBody]
- type RouterGroup
- func (s *RouterGroup) AddTags(tags ...string) *RouterGroup
- func (s *RouterGroup) Cookie(name, description string, params ...OpenAPIParamOption) *RouterGroup
- func (group *RouterGroup) Group(path string, groupOption ...GroupOption) *RouterGroup
- func (s *RouterGroup) Header(name, description string, params ...OpenAPIParamOption) *RouterGroup
- func (s *RouterGroup) Hide() *RouterGroup
- func (s *RouterGroup) Param(name, description string, params ...OpenAPIParamOption) *RouterGroup
- func (s *RouterGroup) Query(name, description string, params ...OpenAPIParamOption) *RouterGroup
- func (s *RouterGroup) RemoveTags(tags ...string) *RouterGroup
- func (s *RouterGroup) Show() *RouterGroup
- func (s *RouterGroup) Tags(tags ...string) *RouterGroup
- func (group *RouterGroup) Use(middlewares ...func(http.Handler) http.Handler)
- type Security
- func (security Security) CookieLogoutHandler(w http.ResponseWriter, r *http.Request)
- func (security Security) GenerateToken(claims jwt.Claims) (token string, err error)
- func (security Security) GenerateTokenToCookies(claims jwt.Claims, w http.ResponseWriter) (string, error)
- func (security Security) LoginHandler(verifyUserInfo func(user, password string) (jwt.Claims, error)) func(*ContextWithBody[LoginPayload]) (tokenResponse, error)
- func (security Security) RefreshHandler(w http.ResponseWriter, r *http.Request)
- func (security Security) StdLoginHandler(verifyUserInfo func(r *http.Request) (jwt.Claims, error)) func(w http.ResponseWriter, r *http.Request)
- func (security Security) TokenToContext(searchFunc ...func(*http.Request) string) func(next http.Handler) http.Handler
- func (security Security) ValidateToken(token string) (*jwt.Token, error)
- type Sender
- type Server
- type StdRenderer
- type Templ
- type Timing
- type UnauthorizedError
Examples ¶
Constants ¶
const JWTCookieName = "jwt_token"
Variables ¶
var ( ErrTokenNotFound = errors.New("token not found") ErrInvalidTokenType = errors.New("invalid token type") ErrInvalidRolesType = errors.New("invalid role type. Must be []string") ErrExpired = errors.New("token is expired") )
var ReadOptions = readOptions{ DisallowUnknownFields: true, MaxBodySize: maxBodySize, }
var SendError = func(w http.ResponseWriter, r *http.Request, err error) { for _, header := range parseAcceptHeader(r.Header) { switch inferAcceptHeader(header, nil) { case "application/xml": SendXMLError(w, nil, err) case "text/html": SendHTMLError(w, nil, err) case "text/plain": SendTextError(w, r, err) case "application/json": SendJSONError(w, nil, err) case "application/x-yaml", "text/yaml; charset=utf-8", "application/yaml": SendYAMLError(w, nil, err) default: continue } return } SendJSONError(w, r, err) }
SendError sends an error. Declared as a variable to be able to override it for clients that need to customize serialization.
var SendHTML = func(w http.ResponseWriter, r *http.Request, ans any) error { w.Header().Set("Content-Type", "text/html; charset=utf-8") ctxRenderer, ok := any(ans).(CtxRenderer) if ok { return ctxRenderer.Render(r.Context(), w) } renderer, ok := any(ans).(Renderer) if ok { return renderer.Render(w) } html, ok := any(ans).(HTML) if ok { _, err := w.Write([]byte(html)) return err } htmlString, ok := any(ans).(string) if ok { _, err := w.Write([]byte(htmlString)) return err } return fmt.Errorf("cannot serialize HTML from type %T (not string, fuego.HTML and does not implement fuego.CtxRenderer or fuego.Renderer)", ans) }
SendHTML sends a HTML response. Declared as a variable to be able to override it for clients that need to customize serialization.
var SendJSON = func(w http.ResponseWriter, _ *http.Request, ans any) error { w.Header().Set("Content-Type", "application/json") err := json.NewEncoder(w).Encode(ans) if err != nil { w.WriteHeader(http.StatusInternalServerError) slog.Error("Cannot serialize returned response to JSON", "error", err) _, _ = w.Write([]byte(`{"error":"Cannot serialize returned response to JSON"}`)) } return err }
SendJSON sends a JSON response. Declared as a variable to be able to override it for clients that need to customize serialization.
var SendXML = func(w http.ResponseWriter, _ *http.Request, ans any) error { w.Header().Set("Content-Type", "application/xml") return xml.NewEncoder(w).Encode(ans) }
SendXML sends a XML response. Declared as a variable to be able to override it for clients that need to customize serialization.
var SendYAML = func(w http.ResponseWriter, _ *http.Request, ans any) error { w.Header().Set("Content-Type", "application/x-yaml") err := yaml.NewEncoder(w).Encode(ans) if err != nil { w.WriteHeader(http.StatusInternalServerError) slog.Error("Cannot serialize returned response to YAML", "error", err) _, _ = w.Write([]byte(`{"error":"Cannot serialize returned response to YAML"}`)) } return err }
SendYAML sends a YAML response. Declared as a variable to be able to override it for clients that need to customize serialization.
Functions ¶
func AuthWall ¶
AuthWall is a middleware that checks if the user is authorized. If not, it returns an error. If authorized roles are provided, the user must have at least one of its role in the list. For example:
AuthWall("admin", "chef") // Will block a user with the "waiter" role and allow a user with a role "chef". AuthWall("chef") // Will block a user with the "admin" and "client" role. AuthWall() // Will block all users. To simply Check if the user is authenticated, use the [TokenToContext] middleware.
See the tests for more examples.
func AuthWallRegex ¶
AuthWallRegex is a middleware that checks if the user is authorized. If not, it returns an error. If authorized roles are provided, the user must have at least one of its role in the list that matches the regex. For example:
AuthWallRegex(`^(super)?admin$`) // Will block a user with the "waiter" role and allow a user with a role "admin".
See the tests for more examples.
func AuthWallRegexp ¶
AuthWallRegexp is a middleware that checks if the user is authorized. If not, it returns an error. If authorized roles are provided, the user must have at least one of its role in the list that matches the regex. For example:
myRegexRule := regexp.MustCompile(`^(super)?admin$`) AuthWallRegex(myRegexRule) // Will block a user with the "waiter" role and allow a user with a role "admin".
See the tests for more examples.
func DefaultOpenAPIHandler ¶
func ErrorHandler ¶
ErrorHandler is the default error handler used by the framework. It transforms any error into the unified error type HTTPError, Using the ErrorWithStatus and [ErrorWithInfo] interfaces.
func GetToken ¶
GetToken returns the validated token from the context, if found. To check if the user is authorized, use the AuthWall middleware, or create your own middleware. Example:
token, err := fuego.GetToken[MyCustomTokenType](ctx.Context())
func HTTPHandler ¶
func HTTPHandler[ReturnType, Body any, Contextable ctx[Body]](s *Server, controller func(c Contextable) (ReturnType, error)) http.HandlerFunc
HTTPHandler converts a Fuego controller into a http.HandlerFunc.
func NewOpenApiSpec ¶
func ReadJSON ¶
ReadJSON reads the request body as JSON. Can be used independently of Fuego framework. Customizable by modifying ReadOptions.
func ReadString ¶
ReadString reads the request body as string. Can be used independently of Fuego framework. Customizable by modifying ReadOptions.
func ReadURLEncoded ¶
ReadURLEncoded reads the request body as HTML Form.
func ReadXML ¶
ReadXML reads the request body as XML. Can be used independently of Fuego framework. Customizable by modifying ReadOptions.
func ReadYAML ¶
ReadYAML reads the request body as YAML. Can be used independently of Fuego framework. Customizable by modifying ReadOptions.
func RegisterOpenAPIOperation ¶
func RegisterOpenAPIOperation[T, B any](group *RouterGroup, route Route[T, B]) (*openapi3.Operation, error)
RegisterOpenAPIOperation registers an OpenAPI operation.
func Send ¶
Send sends a response. The format is determined by the Accept header. If Accept header `*/*` is found Send will Attempt to send HTML, and then JSON.
func SendHTMLError ¶
func SendHTMLError(w http.ResponseWriter, _ *http.Request, err error)
SendHTMLError sends a HTML response. If the error implements ErrorWithStatus, the status code will be set.
func SendJSONError ¶
func SendJSONError(w http.ResponseWriter, _ *http.Request, err error)
SendJSONError sends a JSON error response. If the error implements ErrorWithStatus, the status code will be set.
func SendText ¶
SendText sends a HTML response. Declared as a variable to be able to override it for clients that need to customize serialization.
func SendTextError ¶
func SendTextError(w http.ResponseWriter, _ *http.Request, err error)
SendTextError sends a Text response. If the error implements ErrorWithStatus, the status code will be set.
func SendXMLError ¶
func SendXMLError(w http.ResponseWriter, _ *http.Request, err error)
SendXMLError sends a XML error response. If the error implements ErrorWithStatus, the status code will be set.
func SendYAMLError ¶
func SendYAMLError(w http.ResponseWriter, _ *http.Request, err error)
SendYAMLError sends a YAML error response. If the error implements ErrorWithStatus, the status code will be set.
func TokenFromContext ¶
TokenFromContext returns the validated token from the context, if found. To check if the user is authorized, use the AuthWall middleware, or create your own middleware. Even though it returns a jwt.MapClaims, the real underlying type is the one you chose when calling Security.GenerateToken. Example:
token, err := fuego.TokenFromContext[MyCustomTokenType](ctx.Context())
func TokenFromCookie ¶
func TokenFromHeader ¶
func TokenFromQueryParam ¶
func WithAutoAuth ¶
func WithCorsMiddleware ¶
WithCorsMiddleware registers a middleware to handle CORS. It is not handled like other middlewares with Use because it applies routes that are not registered. For example:
import "github.com/rs/cors" s := fuego.NewServer( WithCorsMiddleware(cors.New(cors.Options{ AllowedOrigins: []string{"*"}, AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}, AllowedHeaders: []string{"*"}, AllowCredentials: true, }).Handler) )
func WithDisallowUnknownFields ¶
WithDisallowUnknownFields sets the DisallowUnknownFields option. If true, the server will return an error if the request body contains unknown fields. Useful for quick debugging in development. Defaults to true.
func WithErrorHandler ¶
func WithErrorSerializer ¶
func WithErrorSerializer(serializer ErrorSender) func(*Server)
WithErrorSerializer sets a custom serializer of type ErrorSender that overrides the default one. Please send a PR if you think the default serializer should be improved, instead of jumping to this option.
func WithGlobalResponseTypes ¶
WithGlobalResponseTypes adds default response types to the server. useful for adding global error types. For example:
app := fuego.NewServer( fuego.WithGlobalResponseTypes(400, "Bad Request _(validation or deserialization error)_", HTTPError{}), fuego.WithGlobalResponseTypes(401, "Unauthorized _(authentication error)_", HTTPError{}), fuego.WithGlobalResponseTypes(500, "Internal Server Error _(panics)_", HTTPError{}), )
func WithLogHandler ¶
WithLogHandler sets the log handler of the server.
func WithMaxBodySize ¶
func WithSerializer ¶
WithSerializer sets a custom serializer of type Sender that overrides the default one. Please send a PR if you think the default serializer should be improved, instead of jumping to this option.
func WithTemplateFS ¶
WithTemplateFS sets the filesystem used to load templates. To be used with WithTemplateGlobs or WithTemplates. For example:
WithTemplateFS(os.DirFS("./templates"))
or with embedded templates:
//go:embed templates var templates embed.FS ... WithTemplateFS(templates)
func WithTemplateGlobs ¶
WithTemplateGlobs loads templates matching the given patterns from the server filesystem. If the server filesystem is not set, it will use the OS filesystem, at folder "./templates". For example:
WithTemplateGlobs("*.html, */*.html", "*/*/*.html") WithTemplateGlobs("pages/*.html", "pages/admin/*.html")
for reference about the glob patterns in Go (no ** support for example): https://pkg.go.dev/path/filepath?utm_source=godoc#Match
func WithTemplates ¶
WithTemplates loads the templates used to render HTML. To be used with WithTemplateFS. If not set, it will use the os filesystem, at folder "./templates".
func WithValidator ¶
func WithValidator(newValidator *validator.Validate) func(*Server)
WithValidator sets the validator to be used by the fuego server. If no validator is provided, a default validator will be used.
Note: If you are using the default validator, you can add tags to your structs using the `validate` tag. For example:
type MyStruct struct { Field1 string `validate:"required"` Field2 int `validate:"min=10,max=20"` }
The above struct will be validated using the default validator, and if any errors occur, they will be returned as part of the response.
func WithoutAutoGroupTags ¶
func WithoutAutoGroupTags() func(*Server)
WithoutAutoGroupTags disables the automatic grouping of routes by tags. By default, routes are tagged by group. For example:
recipeGroup := fuego.Group(s, "/recipes") fuego.Get(recipeGroup, "/", func(*ContextNoBody) (ans, error) { return ans{}, nil }) RecipeThis route will be tagged with "recipes" by default, but with this option, they will not be tagged.
func WithoutStartupMessages ¶
func WithoutStartupMessages() func(*Server)
WithoutStartupMessages disables the startup message
Types ¶
type AutoAuthConfig ¶
type BadRequestError ¶
type BadRequestError HTTPError
BadRequestError is an error used to return a 400 status code.
func (BadRequestError) Error ¶
func (e BadRequestError) Error() string
func (BadRequestError) StatusCode ¶
func (e BadRequestError) StatusCode() int
func (BadRequestError) Unwrap ¶
func (e BadRequestError) Unwrap() error
type ConflictError ¶
type ConflictError HTTPError
ConflictError is an error used to return a 409 status code.
func (ConflictError) Error ¶
func (e ConflictError) Error() string
func (ConflictError) StatusCode ¶
func (e ConflictError) StatusCode() int
func (ConflictError) Unwrap ¶
func (e ConflictError) Unwrap() error
type ContextNoBody ¶
type ContextNoBody struct { Req *http.Request Res http.ResponseWriter // contains filtered or unexported fields }
ContextNoBody is used when the controller does not have a body. It is used as a base context for other Context types.
func (ContextNoBody) Body ¶
func (c ContextNoBody) Body() (any, error)
func (ContextNoBody) Context ¶
func (c ContextNoBody) Context() context.Context
ContextNoBody implements the context interface via net/http.Request.Context
func (ContextNoBody) Cookie ¶
func (c ContextNoBody) Cookie(name string) (*http.Cookie, error)
Get request cookie
func (ContextNoBody) Deadline ¶
func (c ContextNoBody) Deadline() (deadline time.Time, ok bool)
ContextNoBody implements the context interface via net/http.Request.Context
func (ContextNoBody) Done ¶
func (c ContextNoBody) Done() <-chan struct{}
ContextNoBody implements the context interface via net/http.Request.Context
func (ContextNoBody) Err ¶
func (c ContextNoBody) Err() error
ContextNoBody implements the context interface via net/http.Request.Context
func (ContextNoBody) MainLang ¶
func (c ContextNoBody) MainLang() string
func (ContextNoBody) MainLocale ¶
func (c ContextNoBody) MainLocale() string
func (ContextNoBody) MustBody ¶
func (c ContextNoBody) MustBody() any
func (ContextNoBody) PathParam ¶
func (c ContextNoBody) PathParam(name string) string
PathParams returns the path parameters of the request.
func (ContextNoBody) QueryParam ¶
func (c ContextNoBody) QueryParam(name string) string
QueryParam returns the query parameter with the given name.
func (ContextNoBody) QueryParamArr ¶
func (c ContextNoBody) QueryParamArr(name string) []string
QueryParamsArr returns an slice of string from the given query parameter.
func (ContextNoBody) QueryParamBool ¶
func (c ContextNoBody) QueryParamBool(name string, defaultValue bool) bool
func (ContextNoBody) QueryParamBoolErr ¶
func (c ContextNoBody) QueryParamBoolErr(name string) (bool, error)
QueryParamBool returns the query parameter with the given name as a bool. If the query parameter does not exist or is not a bool, it returns nil. Accepted values are defined as strconv.ParseBool
func (ContextNoBody) QueryParamInt ¶
func (c ContextNoBody) QueryParamInt(name string, defaultValue int) int
func (ContextNoBody) QueryParamIntErr ¶
func (c ContextNoBody) QueryParamIntErr(name string) (int, error)
func (ContextNoBody) QueryParams ¶
func (c ContextNoBody) QueryParams() url.Values
QueryParams returns the query parameters of the request. It is a shortcut for c.Req.URL.Query().
func (ContextNoBody) Render ¶
func (c ContextNoBody) Render(templateToExecute string, data any, layoutsGlobs ...string) (CtxRenderer, error)
Render renders the given templates with the given data. It returns just an empty string, because the response is written directly to the http.ResponseWriter.
Init templates if not already done. This has the side effect of making the Render method static, meaning that the templates will be parsed only once, removing the need to parse the templates on each request but also preventing to dynamically use new templates.
func (ContextNoBody) Request ¶
func (c ContextNoBody) Request() *http.Request
Request returns the HTTP request.
func (ContextNoBody) Response ¶
func (c ContextNoBody) Response() http.ResponseWriter
Response returns the HTTP response writer.
func (ContextNoBody) SetCookie ¶
func (c ContextNoBody) SetCookie(cookie http.Cookie)
Sets response cookie
Example ¶
s := NewServer() Get(s.RouterGroup(), "/test", func(c *ContextNoBody) (string, error) { c.SetCookie(http.Cookie{ Name: "name", Value: "value", }) return "test", nil }) w := httptest.NewRecorder() r := httptest.NewRequest(http.MethodGet, "/test", nil) s.ServeHTTP(w, r) fmt.Println(w.Result().Cookies()[0].Name) fmt.Println(w.Result().Cookies()[0].Value)
Output: name value
func (ContextNoBody) SetHeader ¶
func (c ContextNoBody) SetHeader(key, value string)
Sets response header
Example ¶
s := NewServer() Get(s.RouterGroup(), "/test", func(c *ContextNoBody) (string, error) { c.SetHeader("X-Test", "test") return "test", nil }) w := httptest.NewRecorder() r := httptest.NewRequest(http.MethodGet, "/test", nil) s.ServeHTTP(w, r) fmt.Println(w.Header().Get("X-Test"))
Output: test
func (ContextNoBody) SetStatus ¶
func (c ContextNoBody) SetStatus(code int)
SetStatus sets the status code of the response. Alias to http.ResponseWriter.WriteHeader.
func (ContextNoBody) Value ¶
func (c ContextNoBody) Value(key any) any
ContextNoBody implements the context interface via net/http.Request.Context
type ContextWithBody ¶
type ContextWithBody[Body any] struct { ContextNoBody // contains filtered or unexported fields }
ContextWithBody is the same as fuego.ContextNoBody, but has a Body. The Body type parameter represents the expected data type from http.Request.Body. Please do not use a pointer as a type parameter.
func NewContext ¶
func NewContext[B any](w http.ResponseWriter, r *http.Request, options readOptions) *ContextWithBody[B]
NewContext returns a new context. It is used internally by Fuego. You probably want to use Ctx[B] instead.
func (*ContextWithBody[B]) Body ¶
func (c *ContextWithBody[B]) Body() (B, error)
Body returns the body of the request. If (*B) implements InTransformer, it will be transformed after deserialization. It caches the result, so it can be called multiple times. The reason the body is cached is that it is impossible to read an HTTP request body multiple times, not because of performance. For decoding, it uses the Content-Type header. If it is not set, defaults to application/json.
func (*ContextWithBody[B]) MustBody ¶
func (c *ContextWithBody[B]) MustBody() B
MustBody works like Body, but panics if there is an error.
type CtxRenderer ¶
CtxRenderer is an interface that can be used to render a response. It is used with standard library templating engine, by using fuego.ContextXXX.Render It is compatible with github.com/a-h/templ out of the box. Example:
func getRecipes(ctx fuego.ContextNoBody) (fuego.CtxRenderer, error) { recipes, err := ctx.store.GetRecipes(ctx.Context()) if err != nil { return nil, err } return recipeComponent(recipes), nil // recipeComponent is templ component }
type DataOrTemplate ¶
DataOrTemplate is a struct that can return either data or a template depending on the asked type.
func DataOrHTML ¶
func DataOrHTML[T any](data T, template any) *DataOrTemplate[T]
Helper function to create a DataOrTemplate return item without specifying the type.
func (DataOrTemplate[T]) MarshalJSON ¶
func (m DataOrTemplate[T]) MarshalJSON() ([]byte, error)
func (DataOrTemplate[T]) MarshalXML ¶
func (m DataOrTemplate[T]) MarshalXML(e *xml.Encoder, _ xml.StartElement) error
func (DataOrTemplate[T]) MarshalYAML ¶
func (m DataOrTemplate[T]) MarshalYAML() (interface{}, error)
func (DataOrTemplate[T]) String ¶
func (m DataOrTemplate[T]) String() string
type ErrorItem ¶
type ErrorItem struct { Name string `json:"name" xml:"name" description:"For example, name of the parameter that caused the error"` Reason string `json:"reason" xml:"reason" description:"Human readable error message"` More map[string]any `json:"more,omitempty" xml:"more,omitempty" description:"Additional information about the error"` }
type ErrorSender ¶
type ErrorSender = func(http.ResponseWriter, *http.Request, error)
type ErrorWithStatus ¶
ErrorWithStatus is an interface that can be implemented by an error to provide additional information about the error.
type ForbiddenError ¶
type ForbiddenError HTTPError
ForbiddenError is an error used to return a 403 status code.
func (ForbiddenError) Error ¶
func (e ForbiddenError) Error() string
func (ForbiddenError) StatusCode ¶
func (e ForbiddenError) StatusCode() int
func (ForbiddenError) Unwrap ¶
func (e ForbiddenError) Unwrap() error
type Gomponent ¶
type Gomponent = Renderer
Gomponent is a shortcut for Renderer, which can be used with github.com/maragudk/gomponents
type GroupOption ¶
type HTML ¶
type HTML string
HTML is a marker type used to differentiate between a string response and an HTML response. To use templating, use [Ctx.Render].
type HTTPError ¶
type HTTPError struct { Err error `json:"-" xml:"-"` // Developer readable error message. Not shown to the user to avoid security leaks. Type string `` // URL of the error type. Can be used to lookup the error in a documentation /* 130-byte string literal not displayed */ Title string `json:"title,omitempty" xml:"title,omitempty" description:"Short title of the error"` // Short title of the error Status int `json:"status,omitempty" xml:"status,omitempty" description:"HTTP status code" example:"403"` // HTTP status code. If using a different type than [HTTPError], for example [BadRequestError], this will be automatically overridden after Fuego error handling. Detail string `json:"detail,omitempty" xml:"detail,omitempty" description:"Human readable error message"` // Human readable error message Instance string `json:"instance,omitempty" xml:"instance,omitempty"` Errors []ErrorItem `json:"errors,omitempty" xml:"errors,omitempty"` }
HTTPError is the error response used by the serialization part of the framework.
func (HTTPError) StatusCode ¶
type InTransformer ¶
InTransformer is an interface for entities that can be transformed. Useful for example for trimming strings, changing case, etc. Can also raise an error if the entity is not valid.
type LoginPayload ¶
type NotFoundError ¶
type NotFoundError HTTPError
NotFoundError is an error used to return a 404 status code.
func (NotFoundError) Error ¶
func (e NotFoundError) Error() string
func (NotFoundError) StatusCode ¶
func (e NotFoundError) StatusCode() int
func (NotFoundError) Unwrap ¶
func (e NotFoundError) Unwrap() error
type OpenAPIConfig ¶
type OpenAPIConfig struct { DisableSwagger bool // If true, the server will not serve the Swagger UI nor the OpenAPI JSON spec DisableSwaggerUI bool // If true, the server will not serve the Swagger UI DisableLocalSave bool // If true, the server will not save the OpenAPI JSON spec locally SwaggerUrl string // URL to serve the swagger UI UIHandler func(specURL string) http.Handler // Handler to serve the OpenAPI UI from spec URL JsonUrl string // URL to serve the OpenAPI JSON spec JsonFilePath string // Local path to save the OpenAPI JSON spec PrettyFormatJson bool // Pretty prints the OpenAPI spec with proper JSON indentation }
type OpenAPIDescriptioner ¶
type OpenAPIDescriptioner interface {
Description() string
}
type OpenAPIParam ¶
type OpenAPIParam struct { Name string Description string OpenAPIParamOption }
type OpenAPIParamOption ¶
type OutTransformer ¶
type OutTransformer interface {
OutTransform(context.Context) error // Transforms an entity before sending it.
}
OutTransformer is an interface for entities that can be transformed. Useful for example for trimming strings, changing case, etc. Can also raise an error if the entity is not valid. Must be implemented by a POINTER RECEIVER. Example:
type User struct { Name string `json:"name"` Password string `json:"password"` }
// Not (u User) but (u *User)
func (u *User) OutTransform(context.Context) error { u.Name = "M. " + u.Name u.Password = "*****" return nil }
type QueryParamInvalidTypeError ¶
type QueryParamInvalidTypeError struct { ParamName string ParamValue string ExpectedType string Err error }
func (QueryParamInvalidTypeError) Error ¶
func (e QueryParamInvalidTypeError) Error() string
type QueryParamNotFoundError ¶
type QueryParamNotFoundError struct {
ParamName string
}
func (QueryParamNotFoundError) Error ¶
func (e QueryParamNotFoundError) Error() string
type Renderer ¶
Renderer can be used with github.com/maragudk/gomponents Example:
func getRecipes(ctx fuego.ContextNoBody) (fuego.CtxRenderer, error) { recipes, err := ctx.store.GetRecipes(ctx.Context()) if err != nil { return nil, err } return recipeComponent(recipes), nil // recipeComponent is gomponents component }
type Route ¶
type Route[ResponseBody any, RequestBody any] struct { Operation *openapi3.Operation // GENERATED OpenAPI operation, do not set manually in Register function. You can change it after the route is registered. All bool // define route to all HTTP methods. If true, ignore Method Method string // HTTP method (GET, POST, PUT, PATCH, DELETE) Path string // URL path. Will be prefixed by the base path of the server and the group path if any Handler http.Handler // handler executed for this route // contains filtered or unexported fields }
func All ¶
func All[T, B any, Contexted ctx[B]](s *RouterGroup, path string, controller func(Contexted) (T, error), middlewares ...func(http.Handler) http.Handler) Route[T, B]
Capture all methods (GET, POST, PUT, PATCH, DELETE) and register a controller.
func Handle ¶
func Handle(s *RouterGroup, path string, controller http.Handler, middlewares ...func(http.Handler) http.Handler) Route[any, any]
Handle registers a standard HTTP handler into the default mux. Use this function if you want to use a standard HTTP handler instead of a Fuego controller.
func Register ¶
func Register[T, B any](group *RouterGroup, route Route[T, B], controller http.Handler, middlewares ...func(http.Handler) http.Handler) Route[T, B]
Register registers a controller into the default mux and documents it in the OpenAPI spec.
func (Route[ResponseBody, RequestBody]) AddError ¶
func (r Route[ResponseBody, RequestBody]) AddError(code int, description string, errorType ...any) Route[ResponseBody, RequestBody]
AddError adds an error to the route.
func (Route[ResponseBody, RequestBody]) Cookie ¶
func (r Route[ResponseBody, RequestBody]) Cookie(name, description string, params ...OpenAPIParamOption) Route[ResponseBody, RequestBody]
Cookie registers a cookie parameter for the route.
func (Route[ResponseBody, RequestBody]) Deprecated ¶
func (Route[ResponseBody, RequestBody]) Description ¶
func (r Route[ResponseBody, RequestBody]) Description(description string) Route[ResponseBody, RequestBody]
Overrides the description for the route.
func (Route[ResponseBody, RequestBody]) Header ¶
func (r Route[ResponseBody, RequestBody]) Header(name, description string, params ...OpenAPIParamOption) Route[ResponseBody, RequestBody]
Header registers a header parameter for the route.
func (Route[ResponseBody, RequestBody]) OperationID ¶
func (r Route[ResponseBody, RequestBody]) OperationID(operationID string) Route[ResponseBody, RequestBody]
Overrides the operationID for the route.
func (Route[ResponseBody, RequestBody]) Param ¶
func (r Route[ResponseBody, RequestBody]) Param(paramType ParamType, name, description string, params ...OpenAPIParamOption) Route[ResponseBody, RequestBody]
Param registers a parameter for the route. The paramType can be "query", "header" or "cookie" as defined in ParamType. [Cookie], [Header], [QueryParam] are shortcuts for Param.
func (Route[ResponseBody, RequestBody]) QueryParam ¶
func (r Route[ResponseBody, RequestBody]) QueryParam(name, description string, params ...OpenAPIParamOption) Route[ResponseBody, RequestBody]
QueryParam registers a query parameter for the route.
func (Route[ResponseBody, RequestBody]) RemoveTags ¶
func (r Route[ResponseBody, RequestBody]) RemoveTags(tags ...string) Route[ResponseBody, RequestBody]
RemoveTags removes tags from the route.
func (Route[ResponseBody, RequestBody]) RequestContentType ¶
func (r Route[ResponseBody, RequestBody]) RequestContentType(consumes ...string) Route[ResponseBody, RequestBody]
Replace the available request Content-Types for the route. By default, the request Content-Types are `application/json` and `application/xml`
type RouterGroup ¶
type RouterGroup struct { DisableOpenapi bool // If true, the routes within the group will not generate an OpenAPI spec. // contains filtered or unexported fields }
func Group ¶
func Group(group *RouterGroup, path string, groupOption ...GroupOption) *RouterGroup
func (*RouterGroup) AddTags ¶
func (s *RouterGroup) AddTags(tags ...string) *RouterGroup
AddTags adds tags from the Server (i.e Group) Tags from the parent Groups will be respected
func (*RouterGroup) Cookie ¶
func (s *RouterGroup) Cookie(name, description string, params ...OpenAPIParamOption) *RouterGroup
Registers a cookie param for all server routes.
func (*RouterGroup) Group ¶
func (group *RouterGroup) Group(path string, groupOption ...GroupOption) *RouterGroup
Group allows grouping routes under a common path. Middlewares are scoped to the group. For example:
s := fuego.NewServer() viewsRoutes := fuego.Group(s, "") apiRoutes := fuego.Group(s, "/api") // Registering a middlewares scoped to /api only fuego.Use(apiRoutes, myMiddleware) // Registering a route under /api/users fuego.Get(apiRoutes, "/users", func(c fuego.ContextNoBody) (ans, error) { return ans{Ans: "users"}, nil }) s.Run()
func (*RouterGroup) Header ¶
func (s *RouterGroup) Header(name, description string, params ...OpenAPIParamOption) *RouterGroup
Registers a header param for all server routes.
func (*RouterGroup) Hide ¶
func (s *RouterGroup) Hide() *RouterGroup
Hide prevents the routes in this server or group from being included in the OpenAPI spec.
func (*RouterGroup) Param ¶
func (s *RouterGroup) Param(name, description string, params ...OpenAPIParamOption) *RouterGroup
Registers a param for all server routes.
func (*RouterGroup) Query ¶
func (s *RouterGroup) Query(name, description string, params ...OpenAPIParamOption) *RouterGroup
Registers a query param for all server routes.
func (*RouterGroup) RemoveTags ¶
func (s *RouterGroup) RemoveTags(tags ...string) *RouterGroup
RemoveTags removes tags from the Server (i.e Group) if the parent Group(s) has matching tags they will be removed
func (*RouterGroup) Show ¶
func (s *RouterGroup) Show() *RouterGroup
Show allows displaying the routes. Activated by default so useless in most cases, but this can be useful if you deactivated the parent group.
func (*RouterGroup) Tags ¶
func (s *RouterGroup) Tags(tags ...string) *RouterGroup
Replaces Tags for the Server (i.e Group) By default, the tag is the type of the response body.
type Security ¶
type Security struct { Now func() time.Time ExpiresInterval time.Duration // contains filtered or unexported fields }
Security holds the key to sign the JWT tokens, and configuration information. The key isn't accessible once created to avoid leaking it. To use it, please use the methods provided.
func NewSecurity ¶
func NewSecurity() Security
func (Security) CookieLogoutHandler ¶
func (security Security) CookieLogoutHandler(w http.ResponseWriter, r *http.Request)
RemoveTokenFromCookies generates a JWT token with the given claims and writes it to the cookies. Usage:
fuego.PostStd(s, "/auth/logout", security.CookieLogoutHandler)
Dependency to Security is for symmetry with [RefreshHandler].
func (Security) GenerateToken ¶
GenerateToken generates a JWT token with the given claims. The claims must be a jwt.MapClaims or embed jwt.RegisteredClaims.
func (Security) GenerateTokenToCookies ¶
func (security Security) GenerateTokenToCookies(claims jwt.Claims, w http.ResponseWriter) (string, error)
GenerateTokenToCookies generates a JWT token with the given claims and writes it to the cookies.
func (Security) LoginHandler ¶
func (security Security) LoginHandler(verifyUserInfo func(user, password string) (jwt.Claims, error)) func(*ContextWithBody[LoginPayload]) (tokenResponse, error)
LoginHandler is a premade login handler. It takes a function that checks if the user is authorized. Example:
security := fuego.NewSecurity() security.ExpiresInterval = 24 * time.Hour fuego.Post(s, "/login", security.LoginHandler(verifyUserInfo)) ... func verifyUserInfo(r *http.Request) (jwt.Claims, error) { // Get the username and password from the request username := r.FormValue("username") password := r.FormValue("password") // ... // Check if the username and password are correct. // Usually, you would check in a database. if username != "myUsername" || password != "myPassword" { return nil, errors.New("invalid username or password") } // ... // Return the claims return &MyCustomToken{ It is recommended to embed jwt.RegisteredClaims in your custom struct that will define your JWT. RegisteredClaims: jwt.RegisteredClaims{ Issuer: username, Subject: username, Audience: jwt.ClaimStrings{"aud1", "aud2"}, ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)), IssuedAt: jwt.NewNumericDate(time.Now()), ID: "1234567890", }, Username: "myUsername", }, nil
func (Security) RefreshHandler ¶
func (security Security) RefreshHandler(w http.ResponseWriter, r *http.Request)
RefreshHandler is a premade refresh handler. It refreshes the token with the same information as the previous one, but with a new issued date. It sends the new token to the cookies and to the response. Usage:
fuego.PostStd(s, "/auth/refresh", security.RefreshHandler)
func (Security) StdLoginHandler ¶
func (security Security) StdLoginHandler(verifyUserInfo func(r *http.Request) (jwt.Claims, error)) func(w http.ResponseWriter, r *http.Request)
StdLoginHandler is a premade login handler. It takes a function that checks if the user is authorized. Example:
security := fuego.NewSecurity() security.ExpiresInterval = 24 * time.Hour fuego.Post(s, "/login", security.StdLoginHandler(verifyUserInfo)) ... func verifyUserInfo(r *http.Request) (jwt.Claims, error) { // Get the username and password from the request username := r.FormValue("username") password := r.FormValue("password") // ... // Check if the username and password are correct. // Usually, you would check in a database. if username != "myUsername" || password != "myPassword" { return nil, errors.New("invalid username or password") } // ... // Return the claims return &MyCustomToken{ It is recommended to embed jwt.RegisteredClaims in your custom struct that will define your JWT. RegisteredClaims: jwt.RegisteredClaims{ Issuer: username, Subject: username, Audience: jwt.ClaimStrings{"aud1", "aud2"}, ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)), IssuedAt: jwt.NewNumericDate(time.Now()), ID: "1234567890", }, Username: "myUsername", }, nil
func (Security) TokenToContext ¶
func (security Security) TokenToContext(searchFunc ...func(*http.Request) string) func(next http.Handler) http.Handler
TokenToContext is a middleware that checks if the user is authenticated from various authentication methods. Once found, the token is parsed, validated and the claims are set in the context. TLDR: after this middleware, the token is either non-existent or validated. You can use TokenFromContext to get the claims
func (Security) ValidateToken ¶
type Server ¶
type Server struct { OpenApiSpec openapi3.T // OpenAPI spec generated by the server Security Security DisallowUnknownFields bool // If true, the server will return an error if the request body contains unknown fields. Useful for quick debugging in development. Serialize Sender // Custom serializer that overrides the default one. SerializeError ErrorSender // Used to serialize the error response. Defaults to [SendError]. ErrorHandler func(err error) error // Used to transform any error into a unified error type structure with status code. Defaults to [ErrorHandler] // contains filtered or unexported fields }
func NewServer ¶
NewServer creates a new server with the given options. For example:
app := fuego.NewServer( fuego.WithAddr(":8080"), fuego.WithoutLogger(), )
Option all begin with `With`. Some default options are set in the function body.
func NewServerWithRouterGroup ¶
func NewServerWithRouterGroup(rg *gin.RouterGroup, options ...func(*Server)) *Server
func (*Server) OutputOpenAPISpec ¶
OutputOpenAPISpec takes the OpenAPI spec and outputs it to a JSON file and/or serves it on a URL. Also serves a Swagger UI. To modify its behavior, use the [WithOpenAPIConfig] option.
func (*Server) RouterGroup ¶
func (s *Server) RouterGroup() *RouterGroup
type StdRenderer ¶
type StdRenderer struct {
// contains filtered or unexported fields
}
StdRenderer renders a template using the standard library templating engine.
type Templ ¶
type Templ = CtxRenderer
Templ is a shortcut for CtxRenderer, which can be used with github.com/a-h/templ
type Timing ¶
Timing is a struct to represent a server timing. Used in the Server-Timing header.
func (Timing) String ¶
String returns a string representation of a Timing, as defined in https://www.w3.org/TR/server-timing/#the-server-timing-header-field
type UnauthorizedError ¶
type UnauthorizedError HTTPError
UnauthorizedError is an error used to return a 401 status code.
func (UnauthorizedError) Error ¶
func (e UnauthorizedError) Error() string
func (UnauthorizedError) StatusCode ¶
func (e UnauthorizedError) StatusCode() int
func (UnauthorizedError) Unwrap ¶
func (e UnauthorizedError) Unwrap() error