### Minimal gorest Application Setup Source: https://context7_llms This Go code snippet demonstrates the minimal setup for a gorest application. It includes loading configuration, initializing databases (RDBMS and Redis if enabled), and starting the HTTP server with graceful shutdown capabilities. ```go package main import ( "net/http" "time" gconfig "github.com/pilinux/gorest/config" gdb "github.com/pilinux/gorest/database" gserver "github.com/pilinux/gorest/lib/server" ) func main() { // Load configuration from .env if err := gconfig.Config(); err != nil { panic(err) } configure := gconfig.GetConfig() // Initialize databases if gconfig.IsRDBMS() { if err := gdb.InitDB().Error; err != nil { panic(err) } } if gconfig.IsRedis() { if _, err := gdb.InitRedis(); err != nil { panic(err) } } // Setup router and start server // setupRouter is user-supplied (see router example below) r := setupRouter(configure) srv := &http.Server{ Addr: configure.Server.ServerHost + ":" + configure.Server.ServerPort, Handler: r, } done := make(chan struct{}) go gserver.GracefulShutdown(srv, 30*time.Second, done, gdb.CloseAllDB) srv.ListenAndServe() <-done } ``` -------------------------------- ### Install gorest using go get Source: https://context7_llms This command installs the gorest package and its dependencies using the Go build tool. It ensures that the latest version of gorest is available for your project. ```bash go get github.com/pilinux/gorest ``` -------------------------------- ### Redis Initialization and Usage with Radix v4 in Go Source: https://context7_llms Demonstrates how to initialize, get, and close a Redis client using the Gorest database package. It also shows basic usage patterns for setting and getting values with and without expiry times, using Radix v4. ```go import gdb "github.com/pilinux/gorest/database" if _, err := gdb.InitRedis(); err != nil { panic(err) } client := gdb.GetRedis() deffer gdb.CloseRedis() ``` ```go import ( "context" "time" "github.com/mediocregopher/radix/v4" gdb "github.com/pilinux/gorest/database" ) func SetValue(key, value string) error { client := gdb.GetRedis() ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() var result string return client.Do(ctx, radix.FlatCmd(&result, "SET", key, value)) } func GetValue(key string) (string, error) { client := gdb.GetRedis() ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() var value string err := client.Do(ctx, radix.FlatCmd(&value, "GET", key)) return value, err } func SetWithExpiry(key, value string, seconds int) error { client := gdb.GetRedis() ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() var result string return client.Do(ctx, radix.FlatCmd(&result, "SET", key, value, "EX", seconds)) } // Set with absolute Unix expiry (seconds) func SetWithExpiryAt(key, value string, unixSeconds int64) error { client := gdb.GetRedis() ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() var result string return client.Do(ctx, radix.FlatCmd(&result, "SET", key, value, "EXAT", unixSeconds)) } // Millisecond TTL (PX) and conditional set (NX/XX) func SetWithMsTTL(key, value string, ms int) error { client := gdb.GetRedis() ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() var result string return client.Do(ctx, radix.FlatCmd(&result, "SET", key, value, "PX", ms, "NX")) } ``` -------------------------------- ### MongoDB Initialization with QMGO in Go Source: https://context7_llms Shows how to initialize and get a MongoDB client using the Gorest database package with the QMGO driver. It includes error handling for initialization and ensures the client is closed properly. ```go import gdb "github.com/pilinux/gorest/database" if _, err := gdb.InitMongo(); err != nil { panic(err) } client := gdb.GetMongo() deffer gdb.CloseMongo() ``` -------------------------------- ### Initialize and Run Go Application with Gorest Source: https://context7_llms The main function initializes the application by loading configuration, setting up database connections (RDBMS, Redis, MongoDB) with retry mechanisms, applying migrations, and starting the HTTP server with graceful shutdown capabilities. It depends on the 'gorest' library for configuration, database, and server functionalities, as well as internal packages for routing and migrations. ```go package main import ( "fmt" "net/http" "time" gconfig "github.com/pilinux/gorest/config" gdb "github.com/pilinux/gorest/database" gserver "github.com/pilinux/gorest/lib/server" "myapp/internal/database/migrate" "myapp/internal/router" ) func main() { if err := gconfig.Config(); err != nil { fmt.Println(err) return } configure := gconfig.GetConfig() if gconfig.IsRDBMS() { // retry loop for RDBMS initialization for { if err := gdb.InitDB().Error; err != nil { fmt.Println(err) time.Sleep(10 * time.Second) continue } break } if err := migrate.StartMigration(*configure); err != nil { fmt.Println(err) return } } if gconfig.IsRedis() { // retry loop for Redis initialization for { if _, err := gdb.InitRedis(); err != nil { fmt.Println(err) time.Sleep(10 * time.Second) continue } break } } if gconfig.IsMongo() { // retry loop for MongoDB initialization for { if _, err := gdb.InitMongo(); err != nil { fmt.Println(err) time.Sleep(10 * time.Second) continue } break } } r, err := router.SetupRouter(configure) if err != nil { fmt.Println(err) return } srv := &http.Server{ Addr: configure.Server.ServerHost + ":" + configure.Server.ServerPort, Handler: r, ReadTimeout: 30 * time.Second, ReadHeaderTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, IdleTimeout: 60 * time.Second, } const shutdownTimeout = 30 * time.Second done := make(chan struct{}) go func() { err := gserver.GracefulShutdown(srv, shutdownTimeout, done, gdb.CloseAllDB) if err != nil { fmt.Println(err) } }() if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { fmt.Printf("server error: %v\n", err) } <-done fmt.Println("server shutdown complete") } ``` -------------------------------- ### Implement Repository Pattern for Addresses (Go) Source: https://context7_llms An example of the repository pattern for managing 'Address' data in MongoDB. It includes CRUD operations (Create, FindByID, FindAll, Update, Delete) and utilizes the 'qmgo' driver. ```go package repo import ( "context" "github.com/qiniu/qmgo" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" ) type Address struct { ID primitive.ObjectID `bson:"_id" json:"id"` Street string `bson:"street" json:"street"` City string `bson:"city" json:"city"` CountryCode string `bson:"countryCode" json:"countryCode"` } type AddressRepo struct { db *qmgo.Client } func (r *AddressRepo) coll() *qmgo.Collection { return r.db.Database("mydb").Collection("addresses") } func (r *AddressRepo) Create(ctx context.Context, addr *Address) error { addr.ID = primitive.NewObjectID() _, err := r.coll().InsertOne(ctx, addr) return err } func (r *AddressRepo) FindByID(ctx context.Context, id primitive.ObjectID) (*Address, error) { var addr Address err := r.coll().Find(ctx, bson.M{"_id": id}).One(&addr) return &addr, err } func (r *AddressRepo) FindAll(ctx context.Context) ([]Address, error) { var addrs []Address err := r.coll().Find(ctx, bson.M{}).All(&addrs) return addrs, err } func (r *AddressRepo) Update(ctx context.Context, addr *Address) error { return r.coll().UpdateOne(ctx, bson.M{"_id": addr.ID}, bson.M{"$set": addr}) } func (r *AddressRepo) Delete(ctx context.Context, id primitive.ObjectID) error { return r.coll().Remove(ctx, bson.M{"_id": id}) } ``` -------------------------------- ### Repository Pattern API Source: https://context7_llms Example implementation of a repository pattern for MongoDB data operations, including Create, FindByID, FindAll, Update, and Delete. ```APIDOC ## Repository Pattern API (Example) ### Description This section demonstrates a repository pattern for interacting with a MongoDB collection (e.g., 'addresses'). It provides methods for common CRUD operations. ### Method - `Create` (Go function) - `FindByID` (Go function) - `FindAll` (Go function) - `Update` (Go function) - `Delete` (Go function) ### Endpoint N/A (These are methods of a Go struct, not direct HTTP endpoints) ### Parameters #### Create - **ctx** (context.Context) - The request context. - **addr** (*Address) - A pointer to the Address object to create. #### FindByID - **ctx** (context.Context) - The request context. - **id** (primitive.ObjectID) - The ID of the address to find. #### FindAll - **ctx** (context.Context) - The request context. #### Update - **ctx** (context.Context) - The request context. - **addr** (*Address) - A pointer to the Address object to update (must contain the ID). #### Delete - **ctx** (context.Context) - The request context. - **id** (primitive.ObjectID) - The ID of the address to delete. ### Request Example ```go // Assuming 'r' is an initialized AddressRepo and 'ctx' is a valid context // Create newAddr := &Address{Street: "123 Main St", City: "Anytown", CountryCode: "US"} err := r.Create(ctx, newAddr) // FindByID foundAddr, err := r.FindByID(ctx, newAddr.ID) // FindAll allAddrs, err := r.FindAll(ctx) // Update foundAddr.Street = "456 New St" err = r.Update(ctx, foundAddr) // Delete err = r.Delete(ctx, newAddr.ID) ``` ### Response N/A (These are function calls; errors are returned as Go errors.) ``` -------------------------------- ### Define Custom User and Post Models in Go Source: https://context7_llms Provides examples of custom model definitions for `User` and `Post` entities. These models are structured for use with a database ORM like GORM, including primary keys, timestamps, and foreign key references. ```go package model import "time" type User struct { UserID uint64 `gorm:"primaryKey" json:"userID" CreatedAt int64 `json:"createdAt" UpdatedAt int64 `json:"updatedAt" FirstName string `json:"firstName" LastName string `json:"lastName" IDAuth uint64 `gorm:"index" json:"-" } type Post struct { PostID uint64 `gorm:"primaryKey" json:"postID" CreatedAt int64 `json:"createdAt" UpdatedAt int64 `json:"updatedAt" Title string `json:"title" Body string `json:"body" IDAuth uint64 `gorm:"index" json:"-" IDUser uint64 `gorm:"index" json:"-" } ``` -------------------------------- ### GET /api/v1/posts Source: https://context7_llms Retrieves a list of all posts. If no posts are found, a 404 status is returned. ```APIDOC ## GET /api/v1/posts ### Description Retrieves a list of all posts. If no posts are found, a 404 status is returned. ### Method GET ### Endpoint /api/v1/posts ### Parameters #### Query Parameters None #### Request Body None ### Request Example None ### Response #### Success Response (200) - **message** (object|array) - The list of posts or a success message. #### Error Response (404) - **message** (string) - "no posts found" #### Response Example (200) ```json { "message": [ { "id": 1, "title": "First Post", "content": "This is the content of the first post." } ] } ``` #### Response Example (404) ```json { "message": "no posts found" } ``` ``` -------------------------------- ### Setup API Routes with GoreSt Source: https://context7_llms Defines API routes for user authentication, email verification, password management, and protected endpoints using JWT middleware. It groups routes into public and protected categories, with specific sub-groups for logout, 2FA, and email updates. ```go import ( "github.com/gin-gonic/gin" gcontroller "github.com/pilinux/gorest/controller" gmiddleware "github.com/pilinux/gorest/lib/middleware" gservice "github.com/pilinux/gorest/service" ) func SetupRoutes(r *gin.Engine) { v1 := r.Group("/api/v1") // Public routes v1.POST("register", gcontroller.CreateUserAuth) v1.POST("login", gcontroller.Login) v1.POST("verify", gcontroller.VerifyEmail) v1.POST("resend-verification-email", gcontroller.CreateVerificationEmail) v1.POST("verify-updated-email", gcontroller.VerifyUpdatedEmail) v1.POST("password/forgot", gcontroller.PasswordForgot) v1.POST("password/reset", gcontroller.PasswordRecover) // Protected routes (access token required) protected := v1.Group("") protected.Use(gmiddleware.JWT()) protected.Use(gservice.JWTBlacklistChecker()) { // Logout (needs both access and refresh tokens) logout := protected.Group("logout") logout.Use(gmiddleware.RefreshJWT()) logout.POST("", gcontroller.Logout) // 2FA routes twoFA := protected.Group("2fa") twoFA.POST("setup", gcontroller.Setup2FA) twoFA.POST("activate", gcontroller.Activate2FA) twoFA.POST("validate", gcontroller.Validate2FA) // Routes requiring verified 2FA verified := protected.Group("") verified.Use(gmiddleware.TwoFA("on", "off", "verified")) verified.POST("password/edit", gcontroller.PasswordUpdate) verified.POST("2fa/deactivate", gcontroller.Deactivate2FA) // Email update routes verified.POST("email/update", gcontroller.UpdateEmail) verified.GET("email/unverified", gcontroller.GetUnverifiedEmail) verified.POST("email/resend-verification-email", gcontroller.ResendVerificationCodeToModifyActiveEmail) } // Refresh token route refresh := v1.Group("refresh") refresh.Use(gmiddleware.RefreshJWT()) refresh.Use(gservice.JWTBlacklistChecker()) refresh.POST("", gcontroller.Refresh) } ``` -------------------------------- ### Two-Factor Authentication (TOTP) and QR Code Generation Source: https://context7_llms Handles the creation, generation, and validation of Time-based One-Time Passwords (TOTP) for two-factor authentication. It also supports generating QR codes for easy setup and saving them to files. ```go import "crypto" // Create TOTP otpBytes, err := glib.NewTOTP("user@example.com", "MyApp", crypto.SHA1, 6) // Generate QR code qrPNG, err := glib.NewQR(otpBytes, "MyApp") // Validate OTP updatedOTP, err := glib.ValidateTOTP(otpBytes, "MyApp", "123456") // Save QR to file filename, err := glib.ByteToPNG(qrPNG, "/tmp/qrcodes") ``` -------------------------------- ### Issue JWT Access and Refresh Tokens Source: https://context7_llms Provides examples of issuing JWT access and refresh tokens with custom claims. It also lists the available JWT validation functions, including general and algorithm-specific validators. ```go claims := gmiddleware.MyCustomClaims{ AuthID: 123, Email: "user@example.com", Role: "admin", Scope: "read write", TwoFA: "verified", Azp: "authorized-party", Fva: []int{0, 1}, Sid: "session-id", V: 1, SiteLan: "en", Custom1: "value1", Custom2: "value2", } accessToken, jti, err := gmiddleware.GetJWT(claims, "access") refreshToken, jti, err := gmiddleware.GetJWT(claims, "refresh") // JWT validation functions (used internally by middleware, also exported) // ValidateAccessJWT dispatches to the algorithm-specific validator gmiddleware.ValidateAccessJWT(token *jwt.Token) (any, error) gmiddleware.ValidateRefreshJWT(token *jwt.Token) (any, error) // Algorithm-specific validators gmiddleware.ValidateHMACAccess(token *jwt.Token) (any, error) gmiddleware.ValidateHMACRefresh(token *jwt.Token) (any, error) gmiddleware.ValidateECDSA(token *jwt.Token) (any, error) gmiddleware.ValidateEdDSA(token *jwt.Token) (any, error) gmiddleware.ValidateRSA(token *jwt.Token) (any, error) // JWTClaims embeds custom claims with registered claims type JWTClaims struct { MyCustomClaims jwt.RegisteredClaims } ``` -------------------------------- ### Go Handler Functions for Two-Factor Authentication Source: https://context7_llms Provides Go functions for managing two-factor authentication (2FA) including setup, activation, validation, deactivation, and backup code generation/validation. These handlers are in the Gorest handler package and use `AuthPayload` and custom claims for operations. ```go import ghandler "github.com/pilinux/gorest/handler" // Two-Factor Authentication ghandler.Setup2FA(claims middleware.MyCustomClaims, authPayload model.AuthPayload) (model.HTTPResponse, int) ghandler.Activate2FA(claims middleware.MyCustomClaims, authPayload model.AuthPayload) (model.HTTPResponse, int) ghandler.Validate2FA(claims middleware.MyCustomClaims, authPayload model.AuthPayload) (model.HTTPResponse, int) ghandler.Deactivate2FA(claims middleware.MyCustomClaims, authPayload model.AuthPayload) (model.HTTPResponse, int) ghandler.CreateBackup2FA(claims middleware.MyCustomClaims, authPayload model.AuthPayload) (model.HTTPResponse, int) ghandler.ValidateBackup2FA(claims middleware.MyCustomClaims, authPayload model.AuthPayload) (model.HTTPResponse, int) ``` -------------------------------- ### Get Current CORS Configuration Source: https://context7_llms Retrieves the current CORS configuration, which is stored in a `CORSConfig` struct. This struct contains details about allowed origins, methods, headers, exposed headers, max age, and whether credentials are allowed. ```go // Get current CORS configuration corsConfig := gmiddleware.GetCORS() // returns CORSConfig struct // CORSConfig struct type CORSConfig struct { AllowedOrigins []string AllowedMethods []string AllowedHeaders []string ExposedHeaders []string MaxAge int AllowCredentials bool } ``` -------------------------------- ### GET /api/v1/posts/{id} Source: https://context7_llms Retrieves a specific post by its ID. Returns a 404 if the post is not found or 400 if the ID is invalid. ```APIDOC ## GET /api/v1/posts/{id} ### Description Retrieves a specific post by its ID. Returns a 404 if the post is not found or 400 if the ID is invalid. ### Method GET ### Endpoint /api/v1/posts/{id} ### Parameters #### Path Parameters - **id** (uint64) - Required - The unique identifier of the post. #### Query Parameters None #### Request Body None ### Request Example None ### Response #### Success Response (200) - **message** (object) - The post object. #### Error Response (404) - **message** (string) - "post not found" #### Error Response (400) - **message** (string) - "invalid id" #### Response Example (200) ```json { "message": { "id": 1, "title": "First Post", "content": "This is the content of the first post." } } ``` #### Response Example (404) ```json { "message": "post not found" } ``` #### Response Example (400) ```json { "message": "invalid id" } ``` ``` -------------------------------- ### Initialize Database Connections with Gorest Source: https://context7_llms This Go code snippet demonstrates how to initialize database connections using the Gorest library. It covers initialization for RDBMS (MySQL, PostgreSQL, SQLite), Redis, and MongoDB. It also shows how to retrieve the database connection, close individual connections, and close all database connections. ```go import gdb "github.com/pilinux/gorest/database" // Constants const gdb.RecordNotFound = "record not found" // Variables var gdb.RedisConnTTL int // context deadline in seconds for Redis connections (set by InitRedis) // Initialize (reads config automatically) if err := gdb.InitDB().Error; err != nil { panic(err) } // Initialize with TLS (MySQL only) gdb.InitTLSMySQL() // Get connection db := gdb.GetDB() // Close connections gdb.CloseSQL() // close RDBMS gdb.CloseRedis() // close Redis gdb.CloseMongo() // close MongoDB gdb.CloseAllDB() // close all database connections (returns error) ``` -------------------------------- ### Configure Gin Router and API Routes with Gorest Source: https://context7_llms The SetupRouter function configures a Gin engine, applying middleware such as CORS, WAF, and rate limiting based on application configuration. It sets up dependency injection for repositories and services, and defines API routes for authentication and protected resources like posts. This function relies on the 'gorest' library for middleware and controllers, and internal packages for handlers, repositories, and services. ```go package router import ( "github.com/gin-gonic/gin" gconfig "github.com/pilinux/gorest/config" gcontroller "github.com/pilinux/gorest/controller" gdb "github.com/pilinux/gorest/database" glib "github.com/pilinux/gorest/lib" gmiddleware "github.com/pilinux/gorest/lib/middleware" gservice "github.com/pilinux/gorest/service" "myapp/internal/handler" "myapp/internal/repo" "myapp/internal/service" ) func SetupRouter(cfg *gconfig.Configuration) (*gin.Engine, error) { if gconfig.IsProd() { gin.SetMode(gin.ReleaseMode) } r := gin.Default() r.SetTrustedProxies(nil) r.TrustedPlatform = cfg.Security.TrustedPlatform // Middleware if gconfig.IsCORS() { r.Use(gmiddleware.CORS(cfg.Security.CORS)) } if gconfig.IsWAF() { r.Use(gmiddleware.Firewall(cfg.Security.Firewall.ListType, cfg.Security.Firewall.IP)) } if gconfig.IsRateLimit() { limiter, _ := glib.InitRateLimiter(cfg.Security.RateLimit, cfg.Security.TrustedPlatform) r.Use(gmiddleware.RateLimit(limiter)) } // Dependency injection db := gdb.GetDB() postRepo := repo.NewPostRepo(db) postService := service.NewPostService(postRepo) postHandler := handler.NewPostHandler(postService) // Routes v1 := r.Group("/api/v1") // Auth routes (from gorest) v1.POST("register", gcontroller.CreateUserAuth) v1.POST("login", gcontroller.Login) // Protected routes protected := v1.Group("") protected.Use(gmiddleware.JWT()) protected.Use(gservice.JWTBlacklistChecker()) // Posts posts := protected.Group("posts") posts.GET("", postHandler.GetPosts) posts.GET(":id", postHandler.GetPost) posts.POST("", postHandler.CreatePost) posts.PUT(":id", postHandler.UpdatePost) posts.DELETE(":id", postHandler.DeletePost) return r, nil } ``` -------------------------------- ### Load gorest Configuration Source: https://context7_llms These Go code snippets show how to load configuration settings in a gorest application. It covers loading from a .env file, loading all configurations from environment variables, and retrieving the loaded configuration object. ```go import gconfig "github.com/pilinux/gorest/config" // Load .env file (calls godotenv.Load()) err := gconfig.Env() // Load all configuration from environment variables err := gconfig.Config() // Retrieve the loaded configuration configure := gconfig.GetConfig() ``` -------------------------------- ### Initialize and Apply Rate Limiting Middleware Source: https://context7_llms Initializes a rate limiter with a specified count and period (e.g., '100-M' for 100 requests per minute) and applies it to the router. It uses the 'X-Real-Ip' header to identify clients. Ensure the `gorest/lib` package is imported. ```go import glib "github.com/pilinux/gorest/lib" // Format: "count-period" where period is S, M, H, D limiter, _ := glib.InitRateLimiter("100-M", "X-Real-Ip") // 100/minute router.Use(gmiddleware.RateLimit(limiter)) ``` -------------------------------- ### Go Constants for Configuration Source: https://context7_llms Defines constants used for activating services and for Redis key prefixes. These constants provide standardized values for common configuration settings. ```go const gconfig.Activated string = "yes" // keyword to activate a service const gconfig.PrefixJtiBlacklist string = "gorest-blacklist-jti:" // Redis key prefix for JWT blacklist ``` -------------------------------- ### Gorest Application Directory Structure Source: https://context7_llms Illustrates a standard directory structure for an application built with the Gorest framework. This structure organizes code into logical components like command entry points, internal modules (database, handlers, repositories, services, routers), environment configuration, and Go module definitions. ```text myapp/ ├── cmd/ │ └── main.go ├── internal/ │ ├── database/ │ │ ├── migrate/ │ │ │ └── migrate.go │ │ └── model/ │ │ └── models.go │ ├── handler/ │ │ └── post.go │ ├── repo/ │ │ └── post.go │ ├── service/ │ │ └── post.go │ └── router/ │ └── router.go ├── .env └── go.mod ``` -------------------------------- ### Manage MongoDB Indexes with Gorest (Go) Source: https://context7_llms Demonstrates how to create single and multiple indexes, and drop indexes in MongoDB using the Gorest database utility. It requires the 'gdb' and 'qmgo' packages. ```go import ( gdb "github.com/pilinux/gorest/database" "github.com/qiniu/qmgo/options" ) // Create single index index := options.IndexModel{Key: []string{"email"}} gdb.MongoCreateIndex("mydb", "users", index) // Create multiple indexes indexes := []options.IndexModel{ {Key: []string{"email"}}, {Key: []string{"createdAt"}}, } gdb.MongoCreateIndexes("mydb", "users", indexes) // Drop indexes gdb.MongoDropIndex("mydb", "users", []string{"email"}) gdb.MongoDropAllIndexes("mydb", "users") ``` -------------------------------- ### Go Configuration Structs Source: https://context7_llms Defines the main Configuration struct and its nested components for various application settings. Includes database, email, logger, server, security, and view configurations. ```go type Configuration struct { Version string Database DatabaseConfig EmailConf EmailConfig Logger LoggerConfig Server ServerConfig Security SecurityConfig ViewConfig ViewConfig } type ServerConfig struct { ServerHost string ServerPort string ServerEnv string } type LoggerConfig struct { Activate string SentryDsn string PerformanceTracing string TracesSampleRate string } type ViewConfig struct { Activate string Directory string } type DatabaseConfig struct { RDBMS RDBMS REDIS REDIS MongoDB MongoDB } type RDBMS struct { Activate string Env struct { Driver string Host string Port string TimeZone string } Access struct { DbName string User string Pass string } Ssl struct { Sslmode string MinTLS string RootCA string ServerCert string ClientCert string ClientKey string } Conn struct { MaxIdleConns int MaxOpenConns int ConnMaxLifetime time.Duration } Log struct { LogLevel int } } type REDIS struct { Activate string Env struct { Host string Port string } Conn struct { PoolSize int ConnTTL int } } type MongoDB struct { Activate string Env struct { AppName string URI string PoolSize uint64 PoolMon string ConnTTL int } } type EmailConfig struct { Activate string Provider string APIToken string AddrFrom string TrackOpens bool TrackLinks string DeliveryType string EmailVerificationTemplateID int64 PasswordRecoverTemplateID int64 EmailUpdateVerifyTemplateID int64 EmailVerificationCodeUUIDv4 bool EmailVerificationCodeLength uint64 PasswordRecoverCodeUUIDv4 bool PasswordRecoverCodeLength uint64 EmailVerificationTag string PasswordRecoverTag string HTMLModel string EmailVerifyValidityPeriod uint64 // in seconds PassRecoverValidityPeriod uint64 // in seconds } type SecurityConfig struct { UserPassMinLength int MustBasicAuth string BasicAuth struct { Username string Password string } MustJWT string JWT middleware.JWTParameters InvalidateJWT string AuthCookieActivate bool AuthCookiePath string AuthCookieDomain string AuthCookieSecure bool AuthCookieHTTPOnly bool AuthCookieSameSite http.SameSite ServeJwtAsResBody bool MustHash string HashPass lib.HashPassConfig HashSec string MustCipher bool CipherKey []byte Blake2bSec []byte VerifyEmail bool RecoverPass bool MustFW string Firewall struct { ListType string IP string } MustCORS string CORS []middleware.CORSPolicy CheckOrigin string RateLimit string TrustedPlatform string Must2FA string TwoFA struct { Issuer string Crypto crypto.Hash Digits int Status Status2FA PathQR string DoubleHash bool } } type Status2FA struct { Verified string On string Off string Invalid string } ``` -------------------------------- ### Database Migrations with GORM in Go Source: https://context7_llms Manages database schema migrations using GORM. It supports different SQL drivers like MySQL by setting specific table options. It also provides a function to drop all tables, which should be used with extreme caution. ```go package migrate import ( gconfig "github.com/pilinux/gorest/config" gdb "github.com/pilinux/gorest/database" gmodel "github.com/pilinux/gorest/database/model" "your-app/database/model" ) type auth gmodel.Auth type twoFA gmodel.TwoFA type twoFABackup gmodel.TwoFABackup type tempEmail gmodel.TempEmail type user model.User type post model.Post func StartMigration(configure gconfig.Configuration) error { db := gdb.GetDB() driver := configure.Database.RDBMS.Env.Driver if driver == "mysql" { return db.Set("gorm:table_options", "ENGINE=InnoDB").AutoMigrate( &auth{}, &twoFA{}, &twoFABackup{}, &tempEmail{}, &user{}, &post{}, ) } return db.AutoMigrate(&auth{}, &twoFA{}, &twoFABackup{}, &tempEmail{}, &user{}, &post{}) } // DropAllTables drops all database tables. Use with caution. func DropAllTables() error { db := gdb.GetDB() return db.Migrator().DropTable( &tempEmail{}, &twoFABackup{}, &twoFA{}, &auth{}, ) } ``` -------------------------------- ### Initialize and Apply Sentry Middleware Source: https://context7_llms Initializes Sentry error tracking with a DSN and optional configuration parameters like environment, release version, and tracing settings. It then applies the Sentry capture middleware to the router. Ensure the `sentrylogrus` hook is correctly handled. ```go // InitSentry(sentryDsn string, v ...string) (sentrylogrus.Hook, error) // - required: sentryDsn // - optional variadic v[0]: environment ("development" or "production") // - optional variadic v[1]: release version or git commit number // - optional variadic v[2]: enableTracing ("yes" or "no") // - optional variadic v[3]: tracesSampleRate ("0.0" - "1.0") _, err := gmiddleware.InitSentry( "https://key@sentry.io/project", "production", "v1.0.0", "yes", "0.5", ) // NewSentryHook creates a new Sentry hook for goroutine-specific loggers // NewSentryHook(sentryDsn string, v ...string) (sentrylogrus.Hook, error) hook, err := gmiddleware.NewSentryHook("https://key@sentry.io/project", "production") // DestroySentry destroys the global sentry hook gmiddleware.DestroySentry() router.Use(gmiddleware.SentryCapture()) ``` -------------------------------- ### gorest Project Structure Overview Source: https://context7_llms This text-based diagram illustrates the typical project structure of a gorest application. It outlines the main directories and their purposes, including configuration, controllers, database models, handlers, services, and libraries. ```text github.com/pilinux/gorest/ ├── config/ # Configuration loading from environment ├── controller/ # HTTP request handlers (thin layer) ├── database/ # Database connections and models │ ├── model/ # GORM models (Auth, TwoFA, etc.) │ └── migrate/ # Auto-migration utilities ├── handler/ # Business logic layer ├── service/ # Utility services (email, crypto, validation) ├── lib/ # Core utilities │ ├── middleware/ # Gin middleware (JWT, CORS, etc.) │ ├── renderer/ # HTTP response renderer │ └── server/ # Graceful shutdown └── example2/ # Recommended application structure ├── cmd/app/ # Application entry point └── internal/ ├── database/ │ ├── migrate/ # Auto-migration utilities │ └── model/ # GORM models ├── handler/ # API handlers ├── repo/ # Repository pattern (data access) ├── router/ # Route definitions └── service/ # Business logic ``` -------------------------------- ### Configure Template Rendering Middleware Source: https://context7_llms Sets up the Pongo2 template rendering engine, specifying the directory where templates are located. It also demonstrates how to set template names and data in the Gin context for rendering. ```go router.Use(gmiddleware.Pongo2("templates/")) router.GET("/", func(c *gin.Context) { c.Set("template", "index.html") c.Set("data", map[string]any{ "title": "Welcome", }) }) ``` -------------------------------- ### File System Utilities Source: https://context7_llms Offers functions for common file operations, including checking file existence, validating paths to prevent traversal attacks, removing whitespace from strings, and processing string data for HTML email templates. ```go // Check file exists if glib.FileExist("/path/to/file") { // File exists } // Validate path (prevent traversal attacks) safePath, err := glib.ValidatePath("/uploads/../etc/passwd", "/uploads") // Returns error if path escapes allowed directory // Remove all whitespace from a string cleaned := glib.RemoveAllSpace(" hello world ") // "helloworld" // HTML email template model helpers // StrArrHTMLModel splits a semicolon-separated string of key:value pairs // into a flat slice: ["key1", "value1", "key2", "value2", ...] strArr := glib.StrArrHTMLModel("key1:value1;key2:value2") // returns []string // HTMLModel converts a flat key-value slice into a map for templated emails model := glib.HTMLModel(strArr) // returns map[string]any ``` -------------------------------- ### Handle Post Requests in Go Source: https://context7_llms Implements HTTP handlers for post-related operations using the Gin framework. It interacts with the PostService to perform actions like fetching all posts, fetching a single post by ID, and creating a new post. Input validation and error handling are included, returning responses via the grenderer. ```go package handler import ( "context" "net/http" "strconv" "strings" "time" "github.com/gin-gonic/gin" gmodel "github.com/pilinux/gorest/database/model" grenderer "github.com/pilinux/gorest/lib/renderer" gservice "github.com/pilinux/gorest/service" "myapp/internal/database/model" "myapp/internal/service" ) type PostHandler struct { svc *service.PostService } func NewPostHandler(svc *service.PostService) *PostHandler { return &PostHandler{svc: svc} } func (h *PostHandler) GetPosts(c *gin.Context) { ctx, cancel := context.WithTimeout(c.Request.Context(), 5*time.Second) defer cancel() resp, status := h.svc.GetPosts(ctx) grenderer.Render(c, resp, status) } func (h *PostHandler) GetPost(c *gin.Context) { id, err := strconv.ParseUint(strings.TrimSpace(c.Param("id")), 10, 64) if err != nil { grenderer.Render(c, gmodel.HTTPResponse{Message: "invalid id"}, http.StatusBadRequest) return } ctx, cancel := context.WithTimeout(c.Request.Context(), 5*time.Second) defer cancel() resp, status := h.svc.GetPost(ctx, id) grenderer.Render(c, resp, status) } func (h *PostHandler) CreatePost(c *gin.Context) { claims := gservice.GetClaims(c) if claims.AuthID == 0 { grenderer.Render(c, gmodel.HTTPResponse{Message: "unauthorized"}, http.StatusUnauthorized) return } var post model.Post if err := c.ShouldBindJSON(&post); err != nil { grenderer.Render(c, gmodel.HTTPResponse{Message: err.Error()}, http.StatusBadRequest) return } post.IDAuth = claims.AuthID ctx, cancel := context.WithTimeout(c.Request.Context(), 5*time.Second) defer cancel() resp, status := h.svc.CreatePost(ctx, &post) grenderer.Render(c, resp, status) } ``` -------------------------------- ### Configure GoreSt JWT Parameters Source: https://context7_llms Shows how to globally configure JWT parameters, including algorithms, key settings, token expiration times, and cryptographic keys (ECDSA, EdDSA, RSA). These parameters are typically auto-configured from environment variables. ```go // Global JWT parameters (auto-configured from env) gmiddleware.JWTParams = gmiddleware.JWTParameters{ Algorithm: "HS256", AccessKey: []byte("secret"), AccessKeyTTL: 5, // minutes RefreshKey: []byte("refresh-secret"), RefreshKeyTTL: 60, // minutes PrivKeyECDSA: *ecdsa.PrivateKey, // ECDSA private key (loaded from PEM) PubKeyECDSA: *ecdsa.PublicKey, // ECDSA public key (loaded from PEM) PrivKeyEdDSA: ed25519.PrivateKey, // EdDSA private key (loaded from PEM) PubKeyEdDSA: ed25519.PublicKey, // EdDSA public key (loaded from PEM) PrivKeyRSA: *rsa.PrivateKey, // RSA private key (loaded from PEM) PubKeyRSA: *rsa.PublicKey, // RSA public key (loaded from PEM) Audience: "myapp", Issuer: "gorest", AccNbf: 0, // access token not-before offset (seconds) RefNbf: 0, // refresh token not-before offset (seconds) Subject: "user", // JWT subject claim } ``` -------------------------------- ### Configure CORS Middleware Source: https://context7_llms Sets up Cross-Origin Resource Sharing (CORS) policies for the router. It allows configuration of allowed origins, methods, headers, and credentials. Note that wildcard origins are incompatible with `Access-Control-Allow-Credentials`. ```go cp := []gmiddleware.CORSPolicy{ {Key: "Access-Control-Allow-Origin", Value: "https://example.com"}, {Key: "Access-Control-Allow-Methods", Value: "GET, POST, PUT, DELETE"}, {Key: "Access-Control-Allow-Headers", Value: "Content-Type, Authorization"}, {Key: "Access-Control-Allow-Credentials", Value: "true"}, {Key: "X-Content-Type-Options", Value: "nosniff"}, {Key: "X-Frame-Options", Value: "DENY"}, } router.Use(gmiddleware.CORS(cp)) ``` -------------------------------- ### Post Repository Pattern in Go Source: https://context7_llms Implements the repository pattern for interacting with Post data. It defines an interface for CRUD operations and provides a concrete implementation using GORM. This pattern abstracts data access logic. ```go package repo import ( "context" "gorm.io/gorm" "your-app/database/model" ) type PostRepository interface { GetPosts(ctx context.Context) ([]model.Post, error) GetPost(ctx context.Context, id uint64) (*model.Post, error) CreatePost(ctx context.Context, post *model.Post) error UpdatePost(ctx context.Context, post *model.Post) error DeletePost(ctx context.Context, id uint64) error } type PostRepo struct { db *gorm.DB } // Compile-time interface check var _ PostRepository = (*PostRepo)(nil) func NewPostRepo(db *gorm.DB) *PostRepo { return &PostRepo{db: db} } func (r *PostRepo) GetPosts(ctx context.Context) ([]model.Post, error) { var posts []model.Post err := r.db.WithContext(ctx).Find(&posts).Error return posts, err } func (r *PostRepo) GetPost(ctx context.Context, id uint64) (*model.Post, error) { var post model.Post err := r.db.WithContext(ctx).Where("post_id = ?", id).First(&post).Error return &post, err } func (r *PostRepo) CreatePost(ctx context.Context, post *model.Post) error { return r.db.WithContext(ctx).Create(post).Error } func (r *PostRepo) UpdatePost(ctx context.Context, post *model.Post) error { return r.db.WithContext(ctx).Save(post).Error } func (r *PostRepo) DeletePost(ctx context.Context, id uint64) error { return r.db.WithContext(ctx).Where("post_id = ?", id).Delete(&model.Post{}).Error } ```