### Initialize and Start Goyave Server (Old) Source: https://github.com/go-goyave/goyave.dev/blob/master/src/upgrade-guide.md This is the old way of initializing and starting the Goyave server, shown for comparison. ```go goyave.RegisterStartupHook(func() { goyave.Logger.Println("Server is listening") }) goyave.RegisterShutdownHook(func() { goyave.Logger.Println("Server is shutting down") }) if err := goyave.Start(route.Register); err != nil { os.Exit(err.(*goyave.Error).ExitCode) } ``` -------------------------------- ### Initialize and Start Goyave Server (New) Source: https://github.com/go-goyave/goyave.dev/blob/master/src/upgrade-guide.md This is the new way to initialize and start the Goyave server, including registering hooks and routes. ```go server, err := goyave.New(opts) if err != nil { fmt.Fprintln(os.Stderr, err.(*errors.Error).String()) os.Exit(1) } server.Logger.Info("Registering hooks") server.RegisterSignalHook() server.RegisterStartupHook(func(s *goyave.Server) { server.Logger.Info("Server is listening", "host", s.Host()) }) server.RegisterShutdownHook(func(s *goyave.Server) { s.Logger.Info("Server is shutting down") }) server.Logger.Info("Registering routes") server.RegisterRoutes(route.Register) if err := server.Start(); err != nil { server.Logger.Error(err) os.Exit(2) } ``` -------------------------------- ### Install Goyave Filter Library Source: https://github.com/go-goyave/goyave.dev/blob/master/src/libraries/filter.md Install the filter library using go get. ```sh go get goyave.dev/filter ``` -------------------------------- ### Initialize Go Module and Get Goyave Source: https://github.com/go-goyave/goyave.dev/blob/master/src/getting-started/installation.md Manually initialize your Go project with `go mod init` and install the Goyave framework using `go get`. Replace the module name with your project's. ```shell $ go mod init github.com/username/projectname $ go get -u goyave.dev/goyave/v5 ``` -------------------------------- ### Starting the Server Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/server.md Initiate the server to start accepting connections after all configurations, hooks, and routes are set up. The error returned is always of type `*goyave.dev/goyave/v5/util/errors.Error`. ```go if err := server.Start(); err != nil { server.Logger.Error(err) os.Exit(3) } ``` -------------------------------- ### Start Goyave Server Source: https://github.com/go-goyave/goyave.dev/blob/master/src/getting-started/architecture.md Starts the Goyave HTTP server, creating the network listener and beginning to serve requests. Startup hooks are executed after the server is ready. ```go server.Start(app) ``` -------------------------------- ### Install Goyave v5 Source: https://github.com/go-goyave/goyave.dev/blob/master/src/upgrade-guide.md Install the latest version of Goyave v5 alongside v4 using go get. This allows for a gradual transition. ```sh go get -u goyave.dev/goyave/v5 ``` -------------------------------- ### User Repository Implementation Source: https://github.com/go-goyave/goyave.dev/blob/master/src/advanced/authentication.md Example of a user repository implementation to find a user by email. ```go func (r *User) FindByUsername(ctx context.Context, email string) (*model.User, error) { var user *model.User db := session.DB(ctx, r.DB).Where("email", email).First(&user) return user, errors.New(db.Error) } ``` -------------------------------- ### New Rule Set Function Example Source: https://github.com/go-goyave/goyave.dev/blob/master/src/changelog/v5.0.0.md This example demonstrates how to define a rule set function that returns validators for different fields. It shows how to specify required fields, data types, and minimum values. ```go func SomeRequest(_ *goyave.Request) v.RuleSet { return v.RuleSet{ {Path: v.CurrentElement, Rules: v.List{v.Required(), v.Object()}}, {Path: "string", Rules: v.List{v.Required(), v.String()}}, {Path: "number", Rules: v.List{v.Required(), v.Float64(), v.Min(10)}}, } } ``` -------------------------------- ### Applying Rule Sets to Routes Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/validation.md This example shows how to apply rule set functions to routes using `ValidateQuery` and `ValidateBody`. ```go func (ctrl *Controller) RegisterRoutes(router *goyave.Router) { subrouter := router.Subrouter("/products") subrouter.Get("/", ctrl.Index).ValidateQuery(IndexRequest) subrouter.Post("/", ctrl.Create).ValidateBody(CreateRequest) // or if using a receiver: // subrouter.Get("/", ctrl.Index).ValidateQuery(ctrl.IndexRequest) // subrouter.Post("/", ctrl.Create).ValidateBody(ctrl.CreateRequest) } ``` -------------------------------- ### User Service Implementation Source: https://github.com/go-goyave/goyave.dev/blob/master/src/advanced/authentication.md Example of a user service implementation that finds a user by username. ```go func (s *Service) FindByUsername(ctx context.Context, username any) (*dto.InternalUser, error) { u, err := s.repository.FindByUsername(ctx, fmt.Sprintf("%v", username)) return typeutil.MustConvert[*dto.InternalUser](u), errors.New(err) } ``` -------------------------------- ### Basic Authentication Configuration Source: https://github.com/go-goyave/goyave.dev/blob/master/src/advanced/authentication.md Example JSON configuration for basic authentication, specifying username and password. ```json { //... "auth": { "basic": { "username": "admin", "password": "admin" } } } ``` -------------------------------- ### User Repository Implementation Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/repositories.md Provides a full example of a User repository, including methods for pagination, fetching by ID, and creating a user. It demonstrates dependency on Gorm's DB and uses custom error handling. ```go package repository import ( "context" "gorm.io/gorm" "gorm.io/gorm/clause" "goyave.dev/goyave/v5/database" "goyave.dev/goyave/v5/util/errors" "goyave.dev/template/database/model" ) // User repository for user manipulation in the database. type User struct { DB *gorm.DB } // NewUser create a new user repository. func NewUser(db *gorm.DB) *User { return &User{ DB: db, } } // Paginate returns a paginator after executing it. func (r *User) Paginate(ctx context.Context, page int, pageSize int) (*database.Paginator[*model.User], error) { users := []*model.User{} paginator := database.NewPaginator(r.DB, page, pageSize, &users) err := paginator.Find() return paginator, err } // GetByID returns the user identified by the given ID, or `nil`. // If not found, returns `gorm.ErrRecordNotFound`. func (r *User) GetByID(ctx context.Context, id int64) (*model.User, error) { var user *model.User db := r.DB.Where("id", id).First(&user) return user, errors.New(db.Error) } func (r *User) Create(ctx context.Context, user *model.User) (*model.User, error) { db := r.DB.Omit(clause.Associations).Create(&user) return user, errors.New(db.Error) } ``` -------------------------------- ### Register a Startup Hook Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/server.md Register a function to be executed after the network listener starts accepting connections. This hook runs in a shared goroutine. ```go server, err := goyave.New(goyave.Options{}) if err != nil { fmt.Fprintln(os.Stderr, err.(*errors.Error).String()) os.Exit(1) } server.RegisterStartupHook(func(s *goyave.Server) { s.Logger.Info("Server is listening", "host", s.Host()) }) ``` -------------------------------- ### Implement a User Service Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/services.md A full example of a user service implementation, including its repository interface, constructor, and methods for retrieving and paginating users. It adheres to the `goyave.Service` interface. ```go // service/user/user.go package user import ( "context" "goyave.dev/goyave/v5/database" "goyave.dev/goyave/v5/util/errors" "goyave.dev/goyave/v5/util/typeutil" "my-project/database/model" "my-project/dto" "my-project/service" ) // Repository defines the DB functions this service relies on when manipulating users. type Repository interface { First(ctx context.Context, id int64) (*model.User, error) Paginate(ctx context.Context, page int, pageSize int) (*database.Paginator[*model.User], error) } // Service for the user resource. type Service struct { repository Repository } // NewService create a new user Service. func NewService(repository Repository) *Service { return &Service{ repository: repository, } } // First returns the first user identified by the given ID. func (s *Service) First(ctx context.Context, id int64) (*dto.User, error) { u, err := s.repository.First(ctx, id) return typeutil.MustConvert[*dto.User](u), errors.New(err) } // Paginate returns a paginator containing all the records that match the given filter request. func (s *Service) Paginate(ctx context.Context, page, pageSize int) (*database.PaginatorDTO[*dto.User], error) { paginator, err := s.repository.Paginate(ctx, page, pageSize) return typeutil.MustConvert[*database.PaginatorDTO[*dto.User]](paginator), errors.New(err) } // Name returns the service name. func (s *Service) Name() string { return service.User } ``` -------------------------------- ### Install and Run Goyave Website Source: https://github.com/go-goyave/goyave.dev/blob/master/README.md Use these commands to set up the development environment for the Goyave website. Ensure Node Version Manager (nvm) is used for managing Node.js versions. ```bash nvm use npm install npm run dev ``` -------------------------------- ### Define Basic HTTP Routes Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/routing.md All HTTP methods are supported, and there are shortcuts for the most common methods like GET, POST, PUT, PATCH, DELETE, and OPTIONS. ```go func Register(_ *goyave.Server, router *goyave.Router) { router.Get("/get", handler) router.Post("/post", handler) router.Put("/put", handler) router.Patch("/patch", handler) router.Delete("/delete", handler) router.Options("/options", handler) } ``` -------------------------------- ### Main Application Entry Point Source: https://github.com/go-goyave/goyave.dev/blob/master/src/getting-started/installation.md This Go code sets up the main entry point for a Goyave application. It initializes the server, registers signal hooks, startup/shutdown hooks, and routes, then starts the server. ```go package main import ( "fmt" "os" "github.com/username/projectname/http/route" "goyave.dev/goyave/v5" "goyave.dev/goyave/v5/util/errors" ) func main() { opts := goyave.Options{} server, err := goyave.New(opts) if err != nil { fmt.Fprintln(os.Stderr, err.(*errors.Error).String()) os.Exit(1) } server.Logger.Info("Registering hooks") server.RegisterSignalHook() server.RegisterStartupHook(func(s *goyave.Server) { s.Logger.Info("Server is listening", "host", s.Host()) }) server.RegisterShutdownHook(func(s *goyave.Server) { s.Logger.Info("Server is shutting down") }) server.Logger.Info("Registering routes") server.RegisterRoutes(route.Register) if err := server.Start(); err != nil { server.Logger.Error(err) os.Exit(2) } } ``` -------------------------------- ### Product CRUD Controller Example Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/controllers.md This Go code defines a controller for managing products, including methods for indexing, showing, creating, updating, and deleting products. It demonstrates dependency injection of a product service and registration of routes. ```Go package product import ( "context" "net/http" "strconv" "goyave.dev/goyave/v5" "goyave.dev/goyave/v5/database" "goyave.dev/goyave/v5/util/typeutil" "my-project/dto" "my-project/service" ) type Service interface { GetByID(ctx context.Context, id int64) (*dto.Product, error) Paginate(ctx context.Context, page int, pageSize int) (*database.PaginatorDTO[*dto.User], error) Create(ctx context.Context, createDTO *dto.CreateProduct) (*dto.Product, error) Update(ctx context.Context, id int64, updateDTO *dto.UpdateProduct) error Delete(ctx context.Context, id int64) error } type Controller struct { goyave.Component ProductService Service } func (ctrl *Controller) Init(server *goyave.Server) { ctrl.ProductService = server.Service(service.Product).(Service) ctrl.Component.Init(server) } func (ctrl *Controller) RegisterRoutes(router *goyave.Router) { subrouter := router.Subrouter("/products") subrouter.Get("/", ctrl.Index).ValidateQuery(IndexRequest) subrouter.Post("/", ctrl.Create).ValidateBody(CreateRequest) subrouter.Get("/{productID:[0-9+]}", ctrl.Show) subrouter.Patch("/{productID:[0-9+]}", ctrl.Update).ValidateBody(UpdateRequest) subrouter.Delete("/{productID:[0-9+]}", ctrl.Delete) } func (ctrl *Controller) Index(response *goyave.Response, request *goyave.Request) { query := typeutil.MustConvert[*dto.Index](request.Query) paginator, err := ctrl.ProductService.Paginate(request.Context(), query.Page.Default(1), query.PerPage.Default(20)) if response.WriteDBError(err) { return } response.JSON(http.StatusOK, paginator) } func (ctrl *Controller) Show(response *goyave.Response, request *goyave.Request) { productID, err := strconv.ParseInt(request.RouteParams["productID"], 10, 64) if err != nil { response.Status(http.StatusNotFound) return } user, err := ctrl.ProductService.GetByID(request.Context(), productID) if response.WriteDBError(err) { return } response.JSON(http.StatusOK, user) } func (ctrl *Controller) Create(response *goyave.Response, request *goyave.Request) { createDTO := typeutil.MustConvert[*dto.CreateProduct](request.Data) product, err := ctrl.ProductService.Create(request.Context(), createDTO) if response.WriteDBError(err) { return } response.JSON(http.StatusCreated, map[string]int64{"id": product.ID}) } func (ctrl *Controller) Update(response *goyave.Response, request *goyave.Request) { productID, err := strconv.ParseInt(request.RouteParams["productID"], 10, 64) if err != nil { response.Status(http.StatusNotFound) return } updateDTO := typeutil.MustConvert[*dto.UpdateProduct](request.Data) err = ctrl.ProductService.Update(request.Context(), productID, updateDTO) response.WriteDBError(err) } func (ctrl *Controller) Delete(response *goyave.Response, request *goyave.Request) { productID, err := strconv.ParseInt(request.RouteParams["productID"], 10, 64) if err != nil { response.Status(http.StatusNotFound) return } err = ctrl.ProductService.Delete(request.Context(), productID) response.WriteDBError(err) } ``` -------------------------------- ### Implement a Logging Chained Writer Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/response.md This example demonstrates a custom `LogWriter` that logs the response body before writing it. It includes a `LogMiddleware` to set this writer for the response. ```go import ( io "goyave.dev/goyave/v5" "goyave.dev/goyave/v5/util/errors" ) type LogWriter struct { goyave.CommonWriter response *goyave.Response body []byte } func NewWriter(response *goyave.Response) *LogWriter { return &LogWriter{ CommonWriter: goyave.NewCommonWriter(response.Writer()), response: response, } } func (w *LogWriter) Write(b []byte) (int, error) { w.body = append(w.body, b...) n, err := w.CommonWriter.Write(b) return n, errors.New(err) } func (w *LogWriter) Close() error { w.Logger().Info("RESPONSE", "body", string(w.body)) return errors.New(w.CommonWriter.Close()) } type LogMiddleware struct { goyave.Component } func (m *LogMiddleware) Handle(next goyave.Handler) goyave.Handler { return func(response *goyave.Response, request *goyave.Request) { logWriter := NewWriter(response) response.SetWriter(logWriter) next(response, request) } } ``` -------------------------------- ### Metadata Inheritance Example Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/routing.md Demonstrates how metadata set on a router is inherited by its routes. LookupMeta will find the value from the parent router if not present on the route itself. ```go router.SetMeta("key", "value") router.Get("/hello", func(response *goyave.Response, request *goyave.Request) { request.Route.LookupMeta("key") // "value" (from router) }) ``` -------------------------------- ### Apply Middleware to All Routes on Router Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/routing.md This example shows how to apply the Gzip middleware to all routes defined within a specific router. Both '/hello' and '/compressed' routes will be compressed. ```go router.Middleware(compressMiddleware) router.Get("/hello", handler) router.Get("/compressed", handler) ``` -------------------------------- ### Registering Routes Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/server.md Register your application's routes before starting the server. The `route.Register` function is a callback that receives the server and router instances. ```go server, err := goyave.New(goyave.Options{}) if err != nil { fmt.Fprintln(os.Stderr, err.(*errors.Error).String()) os.Exit(1) } server.RegisterRoutes(route.Register) // route.Register is a func(*Server, *Router) ``` -------------------------------- ### Import Goyave Websocket Package Source: https://github.com/go-goyave/goyave.dev/blob/master/src/advanced/websockets.md Import the main Goyave websocket package to start using its functionalities. ```go import "goyave.dev/goyave/v5/websocket" ``` -------------------------------- ### Implement Custom Gzip Encoder Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/middleware.md Example of creating a custom encoder for the compress middleware by implementing the compress.Encoder interface for gzip compression. ```go import ( "compress/gzip" "goyave.dev/goyave/v5/util/errors" ) type Gzip struct { Level int } func (w *Gzip) Encoding() string { return "gzip" } func (w *Gzip) NewWriter(wr io.Writer) io.WriteCloser { writer, err := gzip.NewWriterLevel(wr, w.Level) if err != nil { panic(errors.New(err)) } return writer } ``` -------------------------------- ### Add Hello World Route Source: https://github.com/go-goyave/goyave.dev/blob/master/src/getting-started/installation.md Register a simple "Hello world" route to your Goyave application. This is a basic example of how to define routes. ```go // http/route/route.go router.Get("/hello", func(response *goyave.Response, _ *goyave.Request) { response.String(http.StatusOK, "Hello world") }) ``` -------------------------------- ### Configure Custom Access Log Formatter Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/middleware.md Allows defining a custom formatter for access logs by implementing the log.Formatter function type. This example shows how to format method and URI. ```go import "goyave.dev/goyave/v5/log" router.GlobalMiddleware(&log.AccessMiddleware{Formatter: CustomFormatter}) ``` -------------------------------- ### Mock Database Connection Source: https://github.com/go-goyave/goyave.dev/blob/master/src/advanced/testing.md Replace the server's default database with a mock using `server.ReplaceDB()` for testing database interactions without a real database. This example demonstrates using `go-sqlmock` with a PostgreSQL dialector. Disable prepared statements in the configuration for `go-sqlmock` to function correctly. ```go import ( testing "github.com/DATA-DOG/go-sqlmock" "gorm.io/driver/postgres" "goyave.dev/goyave/v5" "goyave.dev/goyave/v5/config" "goyave.dev/goyave/v5/util/testutil" ) func TestMockDB(t *testing.T) { // Important! Disable prepared statements for mock expectations to work cfg := config.LoadDefault() cfg.Set("database.config.prepareStmt", false) server := testutil.NewTestServerWithOptions(t, goyave.Options{Config: cfg}) mockDB, mock, err := sqlmock.New() if err != nil { panic(err) } dialector := postgres.New(postgres.Config{ DSN: "mock_db", DriverName: "postgres", Conn: mockDB, PreferSimpleProtocol: true, }) err = server.ReplaceDB(dialector) //... mock.ExpectClose() } ``` -------------------------------- ### Paginate with Search Query Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/database.md This example shows how to paginate search results by adding a `WHERE` clause to the database query before creating the paginator. The condition is applied to both the count and data queries. ```go import ( "context" "goyave.dev/goyave/v5/database" "goyave.dev/goyave/v5/util/sqlutil" "my-project/database/model" ) func (r *User) Paginate(ctx context.Context, page int, pageSize int, search string) (*database.Paginator[*model.User], error) { users := []*model.User{} db := r.DB if search != "" { db = db.Where("email", "%"+sqlutil.EscapeLike(search)+"%") } paginator := database.NewPaginator(db, page, pageSize, &users) err := paginator.Find() return paginator, err } ``` -------------------------------- ### Defining a Basic Rule Set Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/validation.md A rule set function receives a request and returns a `v.RuleSet`. This example defines rules for 'page' and 'perPage' query parameters. ```go // http/controller/product/validation.go package product import ( "goyave.dev/goyave/v5" v "goyave.dev/goyave/v5/validation" ) func IndexRequest(_ *goyave.Request) v.RuleSet { return v.RuleSet{ {Path: v.CurrentElement, Rules: v.List{v.Object()}}, {Path: "page", Rules: v.List{v.Int(), v.Min(1)}}, {Path: "perPage", Rules: v.List{v.Int(), v.Between(1, 100)}}, } } ``` -------------------------------- ### Simulate HTTP Request with Mocked Service Source: https://github.com/go-goyave/goyave.dev/blob/master/src/advanced/testing.md This snippet demonstrates how to test an HTTP route by simulating a GET request to '/users/123'. It includes setting up a test server, mocking a service, registering routes, and making the request. Use this for end-to-end testing of your API routes. ```Go package user import ( "context" "net/http" "net/http/httptest" "testing" "goyave.dev/goyave/v5" "goyave.dev/goyave/v5/config" "goyave.dev/goyave/v5/util/testutil" "my-project/dto" "my-project/service" ) type MockService struct{} func (*MockService) First(_ context.Context, id int64) (*dto.User, error) { return &dto.User{ ID: id, Name: "John Doe", Email: "johndoe@example.org", }, nil } func (*MockService) Name() string { return service.User } func TestShowUser(t *testing.T) { server := testutil.NewTestServerWithOptions(t, goyave.Options{Config: config.LoadDefault()}) server.RegisterService(&MockService{}) server.RegisterRoutes(func(_ *goyave.Server, r *goyave.Router) { r.Controller(&Controller{}) // The controller registers /users/{userID:[0-9+]} }) request := httptest.NewRequest(http.MethodGet, "/users/123", nil) response := server.TestRequest(request) defer response.Body.Close() //... } ``` -------------------------------- ### Apply Middleware and Meta with Groups Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/routing.md Use groups (subrouters with empty prefixes) to apply middleware and meta to multiple routes without repetition. This example shows applying authentication to specific routes. ```go router.Middleware(auth.ConfigBasicAuth()) resource := router.Subrouter("/resource") resource.Get("/{id:[0-9]+}", func(response *goyave.Response, request *goyave.Request) { // user is NOT authenticated //... }) resourceAuth := resource.Group().SetMeta(auth.MetaAuth, true) resourceAuth.Patch("/{id:[0-9]+}", func(response *goyave.Response, request *goyave.Request) { // user is authenticated //... }) ``` -------------------------------- ### Find Inactive Users Example Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/repositories.md Demonstrates a custom repository method to find inactive users based on a specified inactivity period. This follows the convention for specific use-case methods. ```go func (r *User) FindInactive(ctx context.Context, inactivityPeriod time.Duration) ([]*model.User, error) ``` -------------------------------- ### Create New Database Instance with Config Source: https://github.com/go-goyave/goyave.dev/blob/master/src/changelog/v5.0.0.md Use `database.New()` to create a new database instance with the provided configuration. This is the standard way to initialize a database connection. ```go db := database.New(config) ``` -------------------------------- ### Create Test Server Source: https://github.com/go-goyave/goyave.dev/blob/master/src/advanced/testing.md Instantiate a test server using `NewTestServer` with a configuration file or `NewTestServerWithOptions` for more control over server options. ```go func TestSomething(t *testing.T) { server := testutil.NewTestServer(t, "config.test.json") // or cfg := config.LoadDefault() cfg.Set("app.debug", false) opts := goyave.Options{ Config: cfg, //... } server := testutil.NewTestServerWithOptions(t, opts) //... } ``` -------------------------------- ### Get Proxy Base URL for Reverse Proxy Setup Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/routing.md Retrieve the proxy base URL using server.ProxyBaseURL(). This is useful when running behind a reverse proxy. It respects proxy configuration for protocol, host, port, and base path. ```go server.ProxyBaseURL() // "https://myproxydomain.example.com/basepath" ``` -------------------------------- ### HTTP Authorization Header Example Source: https://github.com/go-goyave/goyave.dev/blob/master/src/advanced/authentication.md An example of the required Authorization header format for JWT authenticated routes. ```http Authorization: Bearer ``` -------------------------------- ### Create a New Server Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/server.md Create a new server instance using `goyave.New()` with optional configuration. This initializes the server with default or provided options, loads configuration and language files, and sets up the HTTP server and database connection pool. ```go server := goyave.New(options) ``` -------------------------------- ### Get Localized String Source: https://github.com/go-goyave/goyave.dev/blob/master/src/advanced/localization.md Retrieve localized strings using the `Get()` method on a request's language object or directly from the controller's language manager. ```go func (ctrl *Controller) Handle(response *goyave.Response, request *goyave.Request) { request.Lang.Get("customMessage") // or ctrl.Lang().GetDefault().Get("customMessage") ctrl.Lang().Get("en-US", "customMessage") } ``` -------------------------------- ### Define HEAD Route for Expensive Operations Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/routing.md Register a specific HEAD route before the GET route to avoid executing expensive operations for HEAD requests. Ensure the returned headers match the GET handler. ```go func Register(_ *goyave.Server, router *goyave.Router) { router.Route([]string{http.MethodHead}, "/expensive", func(response *goyave.Response, _ *goyave.Request) { response.Header().Set("Content-Type", "application/json; charset=utf-8") response.Status(http.StatusOK) }) router.Get("/expensive", handler) } ``` -------------------------------- ### Check Server Readiness in Startup Hook Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/server.md In startup hooks, it's good practice to re-check if the server is ready, especially if the hook depends on server resources, due to potential concurrency issues. ```go server.RegisterStartupHook(func(s *goyave.Server) { if !s.IsReady() { return } //... }) ``` -------------------------------- ### Clickhouse DSN Options Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/database.md Example of DSN options for ClickHouse. Configures connection timeouts. ```text dial_timeout=10s&read_timeout=20s ``` -------------------------------- ### Using OS File System with Goyave Source: https://github.com/go-goyave/goyave.dev/blob/master/src/advanced/file-systems.md Demonstrates how to use the OS's local file system with Goyave's fsutil.FS interface. Compatible with various fsutil interfaces. ```go root, _ := os.OpenRoot("resources/public") fs := root.FS().(fsutil.FS) ``` -------------------------------- ### MSSQL DSN Options Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/database.md Example of DSN options for MSSQL. Primarily used for connection encryption settings. ```text encrypt=disable ``` -------------------------------- ### Bootstrap Project (Linux/MacOS) Source: https://github.com/go-goyave/goyave.dev/blob/master/src/getting-started/installation.md Use this command to quickly set up a new Goyave project using the template on Linux or MacOS. Replace the module name with your project's. ```shell $ curl https://goyave.dev/install.sh | bash -s github.com/username/projectname ``` -------------------------------- ### SQLite DSN Options Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/database.md Example of DSN options for SQLite. Supports cache modes and memory-based databases. ```text cache=shared&mode=memory ``` -------------------------------- ### PostgreSQL DSN Options Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/database.md Example of DSN options for PostgreSQL. Includes SSL mode and application name. ```text sslmode=disable application_name=goyave ``` -------------------------------- ### MySQL DSN Options Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/database.md Example of DSN options for MySQL. Ensure `parseTime=true` for correct `time.Time` handling. ```text charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local ``` -------------------------------- ### Import Database Drivers Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/database.md Import necessary Gorm database drivers into your main.go file. Comment out unused drivers. ```go import _ "goyave.dev/goyave/v5/database/dialect/mysql" import _ "goyave.dev/goyave/v5/database/dialect/postgres" import _ "goyave.dev/goyave/v5/database/dialect/sqlite" import _ "goyave.dev/goyave/v5/database/dialect/mssql" import _ "goyave.dev/goyave/v5/database/dialect/clickhouse" import _ "goyave.dev/goyave/v5/database/dialect/bigquery" ``` -------------------------------- ### Specify file system for response.File and response.Download Source: https://github.com/go-goyave/goyave.dev/blob/master/src/upgrade-guide.md The `response.File()` and `response.Download()` functions now require a file system as the first parameter. Use `&osfs.FS{}` to maintain the previous behavior of using the operating system's file system. ```go response.File(path) response.Download(path) // becomes response.File(&osfs.FS{}, path) response.Download(&osfs.FS{}, path) ``` -------------------------------- ### Get Database Connection Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/server.md Retrieve the database connection from the server instance. This is the primary way to access the database. ```go server.DB() ``` -------------------------------- ### Testing Basic Authentication with Curl Source: https://github.com/go-goyave/goyave.dev/blob/master/src/advanced/authentication.md Example command to test a route protected by basic authentication using curl. ```sh $ curl -u username:password http://localhost:8080/hello ``` -------------------------------- ### Successful Authentication Response Source: https://github.com/go-goyave/goyave.dev/blob/master/src/advanced/authentication.md Example of the JSON response received upon successful JWT authentication, containing the generated token. ```json { "token": "eyJhbGc..." } ``` -------------------------------- ### Generate Test Server Source: https://github.com/go-goyave/goyave.dev/blob/master/src/upgrade-guide.md Use `testutil.NewTestServer()` to create a test server instance for testing routes without needing to manually manage a running server. ```go server := testutil.NewTestServer(t) server.RegisterRoutes(route.Register) // Use server to test routes ``` -------------------------------- ### Apply Middleware to Specific Route Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/routing.md This example demonstrates applying the defined Gzip middleware only to the '/compressed' route. Other routes will not use compression. ```go router.Get("/hello", handler) router.Get("/compressed", handler).Middleware(compressMiddleware) ``` -------------------------------- ### Dockerfile for Goyave Application Deployment Source: https://github.com/go-goyave/goyave.dev/blob/master/src/getting-started/deployment.md This Dockerfile demonstrates how to build and deploy a Goyave application. It includes steps for setting up a build environment, compiling the application with production flags, copying necessary resources and configuration, and running the application as a non-root user with production environment variables. ```Dockerfile FROM golang:alpine as builder WORKDIR /app COPY . . # Add "-tags production" if you are using embedded configuration RUN go build -ldflags "-w -s" FROM alpine:latest WORKDIR /app COPY --from=builder /app/docker-goyave ./docker-goyave # Not needed if you are using embed resources COPY resources /app/resources # Not needed if you are using embed configuration COPY config.production.json ./config.production.json RUN adduser --system --no-create-home --home /app go-exec RUN chown -R go-exec /app USER go-exec EXPOSE 80 ENV GOYAVE_ENV=production ENTRYPOINT [ "./docker-goyave" ] ``` -------------------------------- ### Initialize Goyave Application Source: https://github.com/go-goyave/goyave.dev/blob/master/src/getting-started/architecture.md Automatically initializes the application by loading configuration and language files, setting up the HTTP server and database connection pool, and optionally registering OS signal hooks. ```go app := goyave.New() // Optionally register hooks, services, and routes here server.Start(app) ``` -------------------------------- ### Serve Static Resources from OS Filesystem Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/routing.md Use `router.Static()` with `osfs.FS` to serve files from the operating system's filesystem. The `false` parameter for `download` means files will be displayed inline by default. ```go import "goyave.dev/goyave/v5/util/fsutil/osfs" router.Static(&osfs.FS{}, "/static", false) ``` -------------------------------- ### Blocking Middleware for Authentication Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/middleware.md Example of a blocking middleware that checks for user authentication. If the user is not authenticated, it responds with Unauthorized and stops further processing. ```go type CustomAuth struct { goyave.Component } func (m *CustomAuth) Handle(next goyave.Handler) goyave.Handler { return func(response *goyave.Response, request *goyave.Request) { if !auth.Check(request) { response.Status(http.StatusUnauthorized) return } next(response, request) } } ``` -------------------------------- ### Bootstrap Project (Windows PowerShell) Source: https://github.com/go-goyave/goyave.dev/blob/master/src/getting-started/installation.md Use this command to quickly set up a new Goyave project using the template on Windows PowerShell. Replace the module name with your project's. ```powershell > & ([scriptblock]::Create((curl "https://goyave.dev/install.ps1").Content)) -moduleName github.com/username/projectname ``` -------------------------------- ### Basic Filter Example Source: https://github.com/go-goyave/goyave.dev/blob/master/src/libraries/filter.md Use the 'filter' parameter to specify a field, operator, and value for WHERE clauses. Multiple filters are ANDed by default. ```text ?filter=name||$cont||Jack ``` -------------------------------- ### Rule Set with Controller Receiver Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/validation.md You can add a receiver to your rule set functions to access controller services. This example uses a `UserService` to validate uniqueness. ```go // http/controller/product/validation.go func (ctrl *Controller) CreateRequest(_ *goyave.Request) v.RuleSet { return v.RuleSet{ {Path: v.CurrentElement, Rules: v.List{v.Object()}}, {Path: "name", Rules: v.List{ v.Required(), v.String(), v.Unique(ctrl.UserService.UniqueScope("name")), }}, //... } } ``` -------------------------------- ### Register User: Map DTO to Model and Create Source: https://github.com/go-goyave/goyave.dev/blob/master/src/advanced/dto-and-model-mapping.md Maps a `dto.RegisterUser` to a `model.User` using `typeutil.Copy` for creation. Ensure the repository's `Create` method handles the model. ```go package service import ( //... "goyave.dev/goyave/v5/util/typeutil" ) func (s *Service) Register(ctx context.Context, user *dto.RegisterUser) (*dto.User, error) { u := typeutil.Copy(&model.User{}, user) u, err := s.repository.Create(ctx, u) return typeutil.MustConvert[*dto.User](u), errors.New(err) } ``` ```go package repository func (r *User) Create(ctx context.Context, user *model.User) (*model.User, error) { db := session.DB(ctx, r.DB).Omit(clause.Associations).Create(user) return user, errors.New(db.Error) } ``` -------------------------------- ### Upgrade HTTP Testing Utilities Source: https://github.com/go-goyave/goyave.dev/blob/master/src/upgrade-guide.md Replaces the old `suite.RunServer` pattern with `testutil.NewTestServerWithOptions` for more flexible HTTP testing without requiring a running server. ```go suite.RunServer(route.Register, func() { resp, err := suite.Get("/hello", nil) suite.Nil(err) suite.NotNil(resp) if resp != nil { defer resp.Body.Close() suite.Equal(200, resp.StatusCode) suite.Equal("Hi!", string(suite.GetBody(resp))) } }) ``` ```go server := testutil.NewTestServerWithOptions(t, goyave.Options{Config: config.LoadDefault()}) server.RegisterRoutes(route.Register) request := httptest.NewRequest(http.MethodGet, "/hello", nil) response := server.TestRequest(request) defer response.Body.Close() // assertions ``` -------------------------------- ### Custom Token-Based Authenticator Implementation Source: https://github.com/go-goyave/goyave.dev/blob/master/src/advanced/authentication.md Implement a custom authenticator that authenticates users based on a token stored in the database. This example defines a `UserService` interface and a `CustomAuthenticator` struct. ```go package auth import ( "context" "fmt" stderrors "errors" "gorm.io/gorm" "goyave.dev/goyave/v5" "goyave.dev/goyave/v5/util/errors" ) type UserService[T any] interface { FindUserByToken(ctx context.Context, token string) (*T, error) } type CustomAuthenticator[T any] struct { goyave.Component UserService UserService[T] } func (a *CustomAuthenticator[T]) Authenticate(request *goyave.Request) (*T, error) { token, ok := request.BearerToken() if !ok { return nil, fmt.Errorf(request.Lang.Get("auth.no-credentials-provided")) } user, err := a.UserService.FindUserByToken(request.Context(), token) if err != nil { if stderrors.Is(err, gorm.ErrRecordNotFound) { return nil, fmt.Errorf(request.Lang.Get("auth.invalid-credentials")) } panic(errors.New(err)) } return user, nil } ``` -------------------------------- ### Registering Services with Session Dependency Source: https://github.com/go-goyave/goyave.dev/blob/master/src/advanced/transactions.md This snippet shows how to initialize services with a session dependency, abstracting GORM for database operations. Repositories will use session.DB() to access the GORM instance. ```go // main.go import ( "database/sql" "my-project/database/repository" "my-project/service/user" "goyave.dev/goyave/v5" "goyave.dev/goyave/v5/util/session" ) func registerServices(server *goyave.Server) { server.Logger.Info("Registering services") session := session.GORM(server.DB(), &sql.TxOptions{}) userRepository := repository.NewUser(server.DB()) userService := user.NewService(session, userRepository) server.RegisterService(userService) } ``` -------------------------------- ### Controller with Constructor for Dependency Injection Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/controllers.md Define a controller with a constructor that accepts dependencies as parameters. This method is an alternative to using `controller.Init()` and is useful when registering routes from the main route registration function. ```go // http/controller/product/product.go type Controller struct { goyave.Component ProductService Service } func NewController(server *goyave.Server, productService Service) *Controller { ctrl := &Controller{ ProductService: productService, } ctrl.Init(server) return ctrl } ``` -------------------------------- ### Get Translated Line from Request Language Source: https://github.com/go-goyave/goyave.dev/blob/master/src/changelog/v5.0.0.md Access translated lines directly from the request's language object. This replaces the previous method of specifying the language name. ```go request.Lang.Get("custom-line") ``` -------------------------------- ### Specify file system for router.Static Source: https://github.com/go-goyave/goyave.dev/blob/master/src/upgrade-guide.md The `router.Static()` function now requires a file system as the first parameter. ```go router.Static("/public", "./public") // becomes router.Static("/public", &osfs.FS{}, "./public") ``` -------------------------------- ### Define Custom Access Log Formatter Function Source: https://github.com/go-goyave/goyave.dev/blob/master/src/basics/middleware.md Example implementation of a custom log formatter function that extracts request method and URI to create a log message and attributes. ```go func CustomFormatter(ctx *log.Context) (string, []slog.Attr) { method := ctx.Request.Method() uri := ctx.Request.URL().RequestURI() message: = fmt.Sprintf("%s %s", method, uri) details := slog.Group("details", slog.String("method", req.Method), slog.String("uri", uri), ) return message, []slog.Attr{details} } ``` -------------------------------- ### Initialize JWT Authenticator and Middleware Source: https://github.com/go-goyave/goyave.dev/blob/master/src/advanced/authentication.md Set up the JWT authenticator with a user service and apply it as global middleware. Routes protected by this authenticator require an 'Authorization: Bearer ' header. ```go authenticator := auth.NewJWTAuthenticator(userService) authMiddleware := auth.Middleware(authenticator) router.GlobalMiddleware(authMiddleware).SetMeta(auth.MetaAuth, true) ``` -------------------------------- ### Import Gorilla Websocket Package with Alias Source: https://github.com/go-goyave/goyave.dev/blob/master/src/advanced/websockets.md If needed, import the underlying gorilla/websocket package with an alias for clarity. ```go import ws "github.com/gorilla/websocket" ``` -------------------------------- ### Custom Panic Status Handler Source: https://github.com/go-goyave/goyave.dev/blob/master/src/advanced/error-handling.md Replace the default status handler to manage errors centrally. This example shows how to notify an error tracking service and send a JSON response. ```go package status import ( "net/http" "github.com/google/jsonapi" "github.com/zaquestion/goyave" "github.com/zaquestion/goyave/errortracker" ) type PanicStatusHandler struct { goyave.Component } func (*PanicStatusHandler) Handle(response *goyave.Response, _ *goyave.Request) { errortracker.Notify(response.GetError()) message := map[string]string{ "error": http.StatusText(response.GetStatus()), } response.JSON(response.GetStatus(), message) } ``` -------------------------------- ### Load Configuration from a Specific File Source: https://github.com/go-goyave/goyave.dev/blob/master/src/getting-started/configuration.md Load configuration directly from a specified file path. The path can be absolute or relative to the working directory. This method bypasses the environment-based loading logic. ```go import ( "fmt" "os" "goyave.dev/goyave/v5/config" "goyave.dev/goyave/v5/util/errors" ) func main() { cfg, err := config.LoadFrom("config.json") if err != nil { fmt.Fprintln(os.Stderr, err.(*errors.Error).String()) os.Exit(1) } opts := goyave.Options{ Config: cfg, } //... } ```