fuego

package module
v0.1.5 Latest Latest
Warning

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

Go to latest
Published: Sep 18, 2024 License: MIT Imports: 30 Imported by: 0

README

Fuego Logo

Fuego 🔥

Go Reference Go Report Card Coverage Status Discord Gophers

The framework for busy Go developers

Build your API or web application in minutes!

Go framework generating OpenAPI documentation from code. Inspired by Nest, built for Go developers.

Also empowers html/template, a-h/templ and maragudk/gomponents: see the example - actually running in prod!

Sponsors

Fuego is proudly sponsored by Zuplo, that provides a Fuego integration!

Fuego Logo

Zuplo allows you to secure your Fuego API, scale it globally, generate documentation from your OpenAPI, and monetize your users.

Why Fuego?

Chi, Gin, Fiber and Echo are great frameworks. But since they were designed a long time ago, their current API does not allow them to deduce OpenAPI types from signatures, things that are now possible with generics. Fuego offers a lot of "modern Go based" features that make it easy to develop APIs and web applications.

Features

  • OpenAPI: Fuego automatically generates OpenAPI documentation from code - not from comments nor YAML files!
  • 100% net/http compatible (no lock-in): Fuego is built on top of net/http, so you can use any http.Handler middleware or handler! Fuego also supports log/slog, context and html/template.
  • Routing: Fuego router is based on Go 1.22 net/http, with grouping and middleware support
  • Serialization/Deserialization: Fuego automatically serializes and deserializes JSON, XML and HTML Forms based on user-provided structs (or not, if you want to do it yourself)
  • Validation: Fuego provides a simple and fast validator based on go-playground/validator
  • Transformation: easily transform your data by implementing the fuego.InTransform and fuego.OutTransform interfaces - also useful for custom validation
  • Middlewares: easily add a custom net/http middleware or use the provided middlewares.
  • Error handling: Fuego provides centralized error handling with the standard RFC 9457.
  • Rendering: Fuego provides a simple and fast rendering system based on html/template - you can still also use your own template system like templ or gomponents

Examples

Hello World
package main

import "github.com/go-fuego/fuego"

func main() {
	s := fuego.NewServer()

	fuego.Get(s, "/", func(c fuego.ContextNoBody) (string, error) {
		return "Hello, World!", nil
	})

	s.Run()
}
Simple POST
package main

import "github.com/go-fuego/fuego"

type MyInput struct {
	Name string `json:"name" validate:"required"`
}

type MyOutput struct {
	Message string `json:"message"`
}

func main() {
	s := fuego.NewServer()

	// Automatically generates OpenAPI documentation for this route
	fuego.Post(s, "/", func(c *fuego.ContextWithBody[MyInput]) (MyOutput, error) {
		body, err := c.Body()
		if err != nil {
			return MyOutput{}, err
		}

		return MyOutput{
			Message: "Hello, " + body.Name,
		}, nil
	})

	s.Run()
}
With transformation & custom validation
type MyInput struct {
	Name string `json:"name" validate:"required"`
}

// Will be called just before returning c.Body()
func (r *MyInput) InTransform(context.Context) error {
	r.Name = strings.ToLower(r.Name)

	if r.Name == "fuego" {
		return errors.New("fuego is not a valid name for this input")
	}

	return nil
}

More OpenAPI documentation
package main

import "github.com/go-fuego/fuego"

func main() {
	s := fuego.NewServer()

	// Custom OpenAPI options that cannot be deduced by the controller signature
	fuego.Post(s, "/", myController).
		Description("This route does something").
		Summary("This is my summary").
		Tags("MyTag"). // A tag is set by default according to the return type (can be deactivated)
		Deprecated()

	s.Run()
}
Std lib compatibility
package main

import (
	"net/http"

	"github.com/go-fuego/fuego"
)

func main() {
	s := fuego.NewServer()

	// Standard net/http middleware
	fuego.Use(s, func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			w.Header().Set("X-Hello", "World")
			next.ServeHTTP(w, r)
		})
	})

	// Standard net/http handler with automatic OpenAPI route declaration
	fuego.GetStd(s, "/std", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("Hello, World!"))
	})

	s.Run()
}
Real-world examples

Please see the /examples folder for more examples.

All features
package main

import (
	"context"
	"errors"
	"net/http"
	"strings"

	chiMiddleware "github.com/go-chi/chi/v5/middleware"
	"github.com/rs/cors"

	"github.com/go-fuego/fuego"
)

type Received struct {
	Name string `json:"name" validate:"required"`
}

type MyResponse struct {
	Message       string `json:"message"`
	BestFramework string `json:"best"`
}

func main() {
	s := fuego.NewServer(
		fuego.WithAddr("localhost:8088"),
	)

	fuego.Use(s, cors.Default().Handler)
	fuego.Use(s, chiMiddleware.Compress(5, "text/html", "text/css"))

	// Fuego 🔥 handler with automatic OpenAPI generation, validation, (de)serialization and error handling
	fuego.Post(s, "/", func(c *fuego.ContextWithBody[Received]) (MyResponse, error) {
		data, err := c.Body()
		if err != nil {
			return MyResponse{}, err
		}

		c.Response().Header().Set("X-Hello", "World")

		return MyResponse{
			Message:       "Hello, " + data.Name,
			BestFramework: "Fuego!",
		}, nil
	})

	// Standard net/http handler with automatic OpenAPI route declaration
	fuego.GetStd(s, "/std", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("Hello, World!"))
	})

	s.Run()
}

// InTransform will be called when using c.Body().
// It can be used to transform the entity and raise custom errors
func (r *Received) InTransform(context.Context) error {
	r.Name = strings.ToLower(r.Name)
	if r.Name == "fuego" {
		return errors.New("fuego is not a name")
	}
	return nil
}

// OutTransform will be called before sending data
func (r *MyResponse) OutTransform(context.Context) error {
	r.Message = strings.ToUpper(r.Message)
	return nil
}
curl  http://localhost:8088/std
# Hello, World!
curl http://localhost:8088 -X POST -d '{"name": "Your Name"}' -H 'Content-Type: application/json'
# {"message":"HELLO, YOUR NAME","best":"Fuego!"}
curl http://localhost:8088 -X POST -d '{"name": "Fuego"}' -H 'Content-Type: application/json'
# {"error":"cannot transform request body: cannot transform request body: fuego is not a name"}

From net/http to Fuego in 10s

https://github.com/go-fuego/fuego/assets/46993939/7438a71c-75a4-4e88-a584-71da6362c575

Views
Before
image
After
image
Diff
image
Benefits of using Fuego views (controllers returning HTML)
  • Never forget to return after an error
  • OpenAPI schema generated, listing all the routes
  • Deserialization and validation are easier
  • Transition to Fuego is easy and fast

Contributing

See the contributing guide. Thanks to everyone who has contributed to this project! ❤️

Roadmap

See the board.

Disclaimer for experienced gophers

I know you might prefer to use net/http directly, but if having a frame can convince my company to use Go instead of Node, I'm happy to use it.

License

MIT

Documentation

Index

Examples

Constants

View Source
const JWTCookieName = "jwt_token"

Variables

View Source
var (
	ErrUnauthorized     = errors.New("unauthorized")
	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")
)
View Source
var ReadOptions = readOptions{
	DisallowUnknownFields: true,
	MaxBodySize:           maxBodySize,
}
View Source
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.

View Source
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.

View Source
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.

View Source
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.

View Source
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

func AuthWall(authorizedRoles ...string) func(next http.Handler) http.Handler

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

func AuthWallRegex(acceptedRolesRegex string) func(next http.Handler) http.Handler

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

func AuthWallRegexp(acceptedRolesRegex *regexp.Regexp) func(next http.Handler) http.Handler

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 DefaultOpenAPIHandler(specURL string) http.Handler

func ErrorHandler

func ErrorHandler(err error) error

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

func GetToken[T any](ctx context.Context) (T, error)

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 InferAcceptHeaderFromType

func InferAcceptHeaderFromType(ans any) string

func NewOpenApiSpec

func NewOpenApiSpec() openapi3.T

func ReadJSON

func ReadJSON[B any](context context.Context, input io.Reader) (B, error)

ReadJSON reads the request body as JSON. Can be used independently of Fuego framework. Customizable by modifying ReadOptions.

func ReadString

func ReadString[B ~string](context context.Context, input io.Reader) (B, error)

ReadString reads the request body as string. Can be used independently of Fuego framework. Customizable by modifying ReadOptions.

func ReadURLEncoded

func ReadURLEncoded[B any](r *http.Request) (B, error)

ReadURLEncoded reads the request body as HTML Form.

func ReadXML

func ReadXML[B any](context context.Context, input io.Reader) (B, error)

ReadXML reads the request body as XML. Can be used independently of Fuego framework. Customizable by modifying ReadOptions.

func ReadYAML

func ReadYAML[B any](context context.Context, input io.Reader) (B, error)

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

func Send(w http.ResponseWriter, r *http.Request, ans any) (err error)

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

func SendText(w http.ResponseWriter, _ *http.Request, ans any) error

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

func TokenFromContext(ctx context.Context) (jwt.Claims, error)

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 TokenFromCookie(r *http.Request) string

func TokenFromHeader

func TokenFromHeader(r *http.Request) string

func TokenFromQueryParam

func TokenFromQueryParam(r *http.Request) string

func Use

func Use(s *RouterGroup, middlewares ...func(http.Handler) http.Handler)

func UseStd

func UseStd(s *RouterGroup, middlewares ...func(http.Handler) http.Handler)

func WithAutoAuth

func WithAutoAuth(verifyUserInfo func(user, password string) (jwt.Claims, error)) func(*Server)

func WithCorsMiddleware

func WithCorsMiddleware(corsMiddleware func(http.Handler) http.Handler) func(*Server)

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

func WithDisallowUnknownFields(b bool) func(*Server)

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 WithErrorHandler(errorHandler func(err error) error) func(*Server)

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

func WithGlobalResponseTypes(code int, description string, errorType ...any) func(*Server)

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

func WithLogHandler(handler slog.Handler) func(*Server)

WithLogHandler sets the log handler of the server.

func WithMaxBodySize

func WithMaxBodySize(maxBodySize int64) func(*Server)

func WithSerializer

func WithSerializer(serializer Sender) func(*Server)

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

func WithTemplateFS(fs fs.FS) func(*Server)

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

func WithTemplateGlobs(patterns ...string) func(*Server)

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

func WithTemplates(templates *template.Template) func(*Server)

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 WithValue

func WithValue(ctx context.Context, val any) context.Context

func WithXML deprecated

func WithXML() func(*Server)

WithXML sets the serializer to XML

Deprecated: fuego supports automatic XML serialization when using the header "Accept: application/xml".

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 WithoutLogger

func WithoutLogger() func(*Server)

WithoutLogger disables the default logger.

func WithoutStartupMessages

func WithoutStartupMessages() func(*Server)

WithoutStartupMessages disables the startup message

Types

type AutoAuthConfig

type AutoAuthConfig struct {
	Enabled        bool
	VerifyUserInfo func(user, password string) (jwt.Claims, error) // Must check the username and password, and return the claims
}

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) Header

func (c ContextNoBody) Header(key string) string

Get request header

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) Redirect

func (c ContextNoBody) Redirect(code int, url string) (any, error)

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

type CtxRenderer interface {
	Render(context.Context, io.Writer) error
}

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

type DataOrTemplate[T any] struct {
	Data     T
	Template any
}

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]) Render

func (m DataOrTemplate[T]) Render(c context.Context, w io.Writer) 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

type ErrorWithStatus interface {
	error
	StatusCode() int
}

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 GroupOption struct {
	HideTag bool
	Tag     openapi3.Tag
}

type H

type H map[string]any

H is a shortcut for map[string]any

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) Error

func (e HTTPError) Error() string

func (HTTPError) StatusCode

func (e HTTPError) StatusCode() int

func (HTTPError) Unwrap

func (e HTTPError) Unwrap() error

type InTransformer

type InTransformer interface {
	InTransform(context.Context) error // InTransforms the entity.
}

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 LoginPayload struct {
	User     string `json:"user" validate:"required"` // Might be an email, a username, or anything else that identifies uniquely the user
	Password string `json:"password" validate:"required"`
}

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 OpenAPIParamOption struct {
	Required bool
	Example  string
	Type     ParamType
}

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 ParamType

type ParamType string
const (
	QueryParamType  ParamType = "query"
	HeaderParamType ParamType = "header"
	CookieParamType ParamType = "cookie"
)

type QueryParamInvalidTypeError

type QueryParamInvalidTypeError struct {
	ParamName    string
	ParamValue   string
	ExpectedType string
	Err          error
}

func (QueryParamInvalidTypeError) Error

type QueryParamNotFoundError

type QueryParamNotFoundError struct {
	ParamName string
}

func (QueryParamNotFoundError) Error

func (e QueryParamNotFoundError) Error() string

type Renderer

type Renderer interface {
	Render(io.Writer) error
}

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 AllStd

func AllStd(s *RouterGroup, path string, controller func(http.ResponseWriter, *http.Request), middlewares ...func(http.Handler) http.Handler) Route[any, any]

func Delete

func Delete[T, B any, Contexted ctx[B]](s *RouterGroup, path string, controller func(Contexted) (T, error), middlewares ...func(http.Handler) http.Handler) Route[T, B]

func DeleteStd

func DeleteStd(s *RouterGroup, path string, controller func(http.ResponseWriter, *http.Request), middlewares ...func(http.Handler) http.Handler) Route[any, any]

func Get

func Get[T, B any, Contexted ctx[B]](s *RouterGroup, path string, controller func(Contexted) (T, error), middlewares ...func(http.Handler) http.Handler) Route[T, B]

func GetStd

func GetStd(s *RouterGroup, path string, controller func(http.ResponseWriter, *http.Request), middlewares ...func(http.Handler) http.Handler) Route[any, any]

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 Patch

func Patch[T, B any, Contexted ctx[B]](s *RouterGroup, path string, controller func(Contexted) (T, error), middlewares ...func(http.Handler) http.Handler) Route[T, B]

func PatchStd

func PatchStd(s *RouterGroup, path string, controller func(http.ResponseWriter, *http.Request), middlewares ...func(http.Handler) http.Handler) Route[any, any]

func Post

func Post[T, B any, Contexted ctx[B]](s *RouterGroup, path string, controller func(Contexted) (T, error), middlewares ...func(http.Handler) http.Handler) Route[T, B]

func PostStd

func PostStd(s *RouterGroup, path string, controller func(http.ResponseWriter, *http.Request), middlewares ...func(http.Handler) http.Handler) Route[any, any]

func Put

func Put[T, B any, Contexted ctx[B]](s *RouterGroup, path string, controller func(Contexted) (T, error), middlewares ...func(http.Handler) http.Handler) Route[T, B]

func PutStd

func PutStd(s *RouterGroup, path string, controller func(http.ResponseWriter, *http.Request), middlewares ...func(http.Handler) http.Handler) Route[any, any]

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]) AddTags

func (r Route[ResponseBody, RequestBody]) AddTags(tags ...string) Route[ResponseBody, RequestBody]

AddTags adds tags 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 (r Route[ResponseBody, RequestBody]) Deprecated() Route[ResponseBody, RequestBody]

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`

func (Route[ResponseBody, RequestBody]) Summary

func (r Route[ResponseBody, RequestBody]) Summary(summary string) Route[ResponseBody, RequestBody]

Overrides the summary for the route.

func (Route[ResponseBody, RequestBody]) Tags

func (r Route[ResponseBody, RequestBody]) Tags(tags ...string) Route[ResponseBody, RequestBody]

Replace the tags for the route. By default, the tag is the type of the response body.

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.

func (*RouterGroup) Use

func (group *RouterGroup) Use(middlewares ...func(http.Handler) http.Handler)

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

func (security Security) GenerateToken(claims jwt.Claims) (token string, err error)

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

func (security Security) ValidateToken(token string) (*jwt.Token, error)

type Sender

type Sender func(http.ResponseWriter, *http.Request, any) error

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

func NewServer(options ...func(*Server)) *Server

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) MarshalSpec

func (s *Server) MarshalSpec(prettyFormatJSON bool) ([]byte, error)

func (*Server) OutputOpenAPISpec

func (s *Server) OutputOpenAPISpec() openapi3.T

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

func (*Server) Run

func (s *Server) Run(addr string) error

Run starts the server. It is blocking. It returns an error if the server could not start (it could not bind to the port for example). It also generates the OpenAPI spec and outputs it to a file, the UI, and a handler (if enabled).

func (*Server) ServeHTTP

func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)

type StdRenderer

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

StdRenderer renders a template using the standard library templating engine.

func (StdRenderer) Render

func (s StdRenderer) Render(ctx context.Context, w io.Writer) error

type Templ

type Templ = CtxRenderer

Templ is a shortcut for CtxRenderer, which can be used with github.com/a-h/templ

type Timing

type Timing struct {
	Name string
	Dur  time.Duration
	Desc string
}

Timing is a struct to represent a server timing. Used in the Server-Timing header.

func (Timing) String

func (t Timing) String() 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

Directories

Path Synopsis
middleware

Jump to

Keyboard shortcuts

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