Server options
When creating a new server with goyave.New()
, you can now pass a goyave.Options
structure that will override the default values. Currently, you can replace the automatically loaded config, the logger and provide a file system to load the language files. You can find out more about this in the section below.
Adding a structure as parameter is flexible from an API point of view, as more options can be added without breaking changes. For developers, it is easier to use and more intuitive than to manually replace those elements after creating the server. This also removes unnecessary startup operations in case developers want to replace those components.
This change is breaking compared to the preview pre-release version of the framework.
goyave.NewWithConfig()
was removed, usegoyave.New(goyave.Options{Config: cfg})
instead.testutil.NewTestServerWithConfig(t, cfg, routeRegistrer)
becomestestutil.NewTestServerWithOptions, options, routeRegistrer)
. By default, the test servers useosfs.FS
.
File systems
All features using files in some way have been revisited and improved to take full advantage of the standard io/fs
package. All future components of the framework will be designed with this in mind. The util/fsutil
package now defines a few useful interfaces in addition to standard ones in io/fs
.
fsutil.FS
: combination offs.ReadDirFS
andfs.StatFS
.fsutil.WorkingDirFS
fsutil.MkdirFS
fsutil.WritableFS
fsutil.RemoveFS
The fsutil.Embed
structure allows easy implementation of fs.StatFS
on embed.FS
:
//go:embed resources
var resources embed.FS
func main() {
resourcesFS := fsutil.Embed{FS: resources}
}
A new package util/fsutil/osfs
contains an implementation of the OS filesystem. This structure is just a proxy to the standard os
package so it can be passed around as an interface parameter.
Below is a list of features that can now take advantage of this abstraction. These changes introduce breaking changes compared to the preview pre-release version of the framework.
auth.JWTService
now takes a file system for loading the signing keysauth.NewJWTService(config)
becomesauth.NewJWTService(config, fs)
- By default, and when added automatically by the
JWTController
, the service usesosfs.FS
.
- Language loading now takes a
fsutil.FS
parameterlang.Languages.Load(language, path)
becomeslang.Languages.Load(fs, language, path)
lang.Languages.LoadLoadAllAvailableLanguages()
becomeslang.Languages.LoadLoadAllAvailableLanguages(fs)
lang.Languages.LoadDirectory(directory)
becomeslang.Languages.LoadDirectory(fs, directory)
Response.File(path)
andResponse.Download(path, fileName)
becomeResponse.File(fs, path)
andResponse.Download(fs, path, fileName)
Router.Static(uri, directory, download)
becomesRouter.Static(fs, uri, directory, download)
fsutil.File.Save(path, name)
becomesfsutil.File.Save(fs, path, name)
fsutil.GetMIMEType(file)
becomesfsutil.GetMIMEType(fs, file)
fsutil.FileExists(file)
becomesfsutil.FileExists(fs, file)
fsutil.IsDirectory(path)
becomesfsutil.IsDirectory(fs, path)
fsutil.Delete(path)
was removed. Useosfs.FS.Remove()
instead.testutil.WriteMultipartFile(writer, path, fieldName)
becomestestutil.WriteMultipartFile(writer, fs, path, fieldName)
-
testutil.CreateTestFiles(file1, file2)
becomestestutil.WriteMultipartFile(fs, file1, file2)
Using this abstraction is beneficial in many ways for maximum flexibility:
- It is easily possible to serve remote resources, such as static assets stored on a cloud storage bucket
- It is possible to take advantage of the embedding capabilities of Go, be it for language files, or static assets. Bundling your executable will require less external resources.
It is advised to expose the file systems through a service so all components have centralized and easy access to them.
Misc
- Removed default values for database configuration. Previously, they were defaults for the MySQL DB engine. The framework had no reason assuming this engine should be the default.
- New exported readonly field
validation.Context.Invalid
, making it easier to unit-test validators that use the now removedcontext.Valid()
method. - In the log middleware, the slog attributes are ignored to reduce clutter. The message itself is enough.
- The internal config loader has been refactored to use
io/fs
too so it's future-proof. - Avoid duplicate CORS middleware if the middleware is already defined as a global middleware.