Archived
Template
1
0

Improves documentation (#13)

* Documents all env variables and adds an example project

* Adds godoc comments

* Fixed package naming issue
This commit is contained in:
Markus Tenghamn
2022-01-09 14:42:03 +01:00
committed by GitHub
parent 5d01717111
commit e586933a6b
31 changed files with 248 additions and 78 deletions

33
main.go
View File

@ -15,58 +15,85 @@ import (
"time"
)
// staticFS is an embedded file system
//go:embed dist/*
var staticFS embed.FS
// Run is the main function that runs the entire package and starts the webserver, this is called by /cmd/base/main.go
func Run() {
// When generating random strings we need to provide a seed otherwise we always get the same strings the next time our application starts
rand.Seed(time.Now().UnixNano())
var t *template.Template
// We load environment variables, these are only read when the application launches
conf := loadEnvVariables()
// We connect to the database using the configuration generated from the environment variables.
db, err := connectToDatabase(conf)
if err != nil {
log.Fatalln(err)
}
// Once a database connection is established we run any needed migrations
err = migrateDatabase(db)
if err != nil {
log.Fatalln(err)
}
// t will hold all our html templates used to render pages
var t *template.Template
// We parse and load the html files into our t variable
t, err = loadTemplates()
if err != nil {
log.Fatalln(err)
}
// A gin Engine instance with the default configuration
r := gin.Default()
// We create a new cookie store with a key used to secure cookies with HMAC
store := cookie.NewStore([]byte(conf.CookieSecret))
// We define our session middleware to be used globally on all routes
r.Use(sessions.Sessions("golang_base_project_session", store))
// We pase our template variable t to the gin engine so it can be used to render html pages
r.SetHTMLTemplate(t)
// our assets are only located in a section of our file system. so we create a sub file system.
subFS, err := fs.Sub(staticFS, "dist/assets")
if err != nil {
log.Fatalln(err)
}
// All static assets are under the /assets path so we make this its own group called assets
assets := r.Group("/assets")
// This middleware sets the Cache-Control header and is applied to the assets group only
assets.Use(middleware.Cache(conf.CacheMaxAge))
// All requests to /assets will use the sub fil system which contains all our static assets
assets.StaticFS("/", http.FS(subFS))
// Session middleware is applied to all groups after this point.
r.Use(middleware.Session(db))
// A General middleware is defined to add default headers to improve site security
r.Use(middleware.General())
// A new instance of the routes controller is created
controller := routes.New(db, conf)
// Any request to / will call controller.Index
r.GET("/", controller.Index)
// We want to handle both POST and GET requests on the /search route. We define both but use the same function to handle the requests.
r.GET("/search", controller.Search)
r.POST("/search", controller.Search)
// We define our 404 handler for when a page can not be found
r.NoRoute(controller.NoRoute)
// noAuth is a group for routes which should only be accessed if the user is not authenticated
noAuth := r.Group("/")
noAuth.Use(middleware.NoAuth())
@ -77,6 +104,7 @@ func Run() {
noAuth.GET("/user/password/forgot", controller.ForgotPassword)
noAuth.GET("/user/password/reset/:token", controller.ResetPassword)
// We make a separate group for our post requests on the same endpoints so that we can define our throttling middleware on POST requests only.
noAuthPost := noAuth.Group("/")
noAuthPost.Use(middleware.Throttle(conf.RequestsPerMinute))
@ -86,6 +114,7 @@ func Run() {
noAuthPost.POST("/user/password/forgot", controller.ForgotPasswordPost)
noAuthPost.POST("/user/password/reset/:token", controller.ResetPasswordPost)
// the admin group handles routes that should only be accessible to authenticated users
admin := r.Group("/")
admin.Use(middleware.Auth())
admin.Use(middleware.Sensitive())
@ -95,6 +124,8 @@ func Run() {
admin.POST("/admin", controller.Admin)
admin.GET("/logout", controller.Logout)
// This starts our webserver, our application will not stop running or go past this point unless
// an error occurs or the web server is stopped for some reason. It is designed to run forever.
err = r.Run(conf.Port)
if err != nil {
log.Fatalln(err)