├── tests ├── config │ ├── .env.test │ └── config_test.go ├── lessgo │ └── framework_benchmark_test.go └── concurrency │ └── concurrency_test.go ├── examples └── rest-example │ ├── src │ ├── test │ │ ├── test_model.go │ │ ├── test_service.go │ │ ├── test_module.go │ │ └── test_controller.go │ ├── user │ │ ├── user_model.go │ │ ├── user_service.go │ │ └── user_module.go │ ├── root_service.go │ ├── upload │ │ ├── upload_module.go │ │ ├── upload_controller.go │ │ └── upload_service.go │ ├── root_controller.go │ └── root_module.go │ └── cmd │ └── main.go ├── internal ├── core │ ├── middleware │ │ ├── wrapper.go │ │ ├── cookie_parser.go │ │ ├── template.go │ │ ├── timeoutMiddleware.go │ │ ├── profiling.go │ │ ├── middleware.go │ │ ├── XSS.go │ │ ├── json_parser.go │ │ ├── CSRF.go │ │ ├── cors.go │ │ ├── cacher.go │ │ ├── file_uploader.go │ │ └── ratelimiter.go │ ├── factory │ │ └── factory.go │ ├── service │ │ └── service.go │ ├── controller │ │ └── controller.go │ ├── config │ │ ├── http.config.go │ │ └── env.config.go │ ├── job │ │ └── scheduler.go │ ├── module │ │ └── module.go │ ├── di │ │ └── di.go │ ├── concurrency │ │ └── concurrency.go │ ├── websocket │ │ └── websocket.go │ ├── context │ │ └── context.go │ └── router │ │ └── router.go └── utils │ └── utils.go ├── AUTHORS.md ├── go.mod ├── CODE_OF_CONDUCT.md ├── .gitignore ├── LICENSE ├── CONTRIBUTING.md ├── docs ├── config.md ├── controller.md ├── scheduler.md ├── lessgo.md ├── introduction.md └── context.md ├── go.sum ├── README.md └── pkg └── lessgo └── less.go /tests/config/.env.test: -------------------------------------------------------------------------------- 1 | PORT=3000 2 | DEBUG=true 3 | MAX_CONNECTIONS=10 4 | PI=3.14 5 | -------------------------------------------------------------------------------- /examples/rest-example/src/test/test_model.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | type User struct { 4 | Name string `json:"name"` 5 | Email string `json:"email"` 6 | } 7 | -------------------------------------------------------------------------------- /examples/rest-example/src/user/user_model.go: -------------------------------------------------------------------------------- 1 | package user 2 | 3 | type User struct { 4 | Name string `json:"name"` 5 | Email string `json:"email"` 6 | } 7 | -------------------------------------------------------------------------------- /examples/rest-example/src/root_service.go: -------------------------------------------------------------------------------- 1 | package src 2 | 3 | type IRootService interface{} 4 | 5 | type RootService struct { 6 | // Add any shared dependencies or methods here 7 | } 8 | 9 | func NewRootService() *RootService { 10 | return &RootService{} 11 | } 12 | 13 | // Add methods that interact with other services 14 | -------------------------------------------------------------------------------- /internal/core/middleware/wrapper.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import "net/http" 4 | 5 | // MiddlewareWrapper wraps a function to match the Middleware interface 6 | type MiddlewareWrapper struct { 7 | HandlerFunc func(next http.Handler) http.Handler 8 | } 9 | 10 | // Handle implements the Middleware interface 11 | func (mw MiddlewareWrapper) Handle(next http.Handler) http.Handler { 12 | return mw.HandlerFunc(next) 13 | } 14 | -------------------------------------------------------------------------------- /examples/rest-example/src/test/test_service.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "log" 5 | 6 | LessGo "github.com/hokamsingh/lessgo/pkg/lessgo" 7 | ) 8 | 9 | type ITestService interface{} 10 | 11 | type TestService struct { 12 | LessGo.BaseService 13 | } 14 | 15 | func NewTestService() *TestService { 16 | return &TestService{} 17 | } 18 | 19 | func (es *TestService) DoSomething() string { 20 | log.Print("Service Logic Executed") 21 | return "Service Logic Executed" 22 | } 23 | -------------------------------------------------------------------------------- /examples/rest-example/src/user/user_service.go: -------------------------------------------------------------------------------- 1 | package user 2 | 3 | import ( 4 | "log" 5 | 6 | LessGo "github.com/hokamsingh/lessgo/pkg/lessgo" 7 | ) 8 | 9 | type IUserService interface{} 10 | 11 | type UserService struct { 12 | LessGo.BaseService 13 | } 14 | 15 | func NewUserService() *UserService { 16 | return &UserService{} 17 | } 18 | 19 | func (es *UserService) DoSomething() string { 20 | log.Print("Service Logic Executed") 21 | return "Service Logic Executed" 22 | } 23 | -------------------------------------------------------------------------------- /AUTHORS.md: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | 4 | # AUTHORS 5 | 6 | This project is made possible by the following contributors: 7 | 8 | - **Hokam Singh** – Creator and Lead Maintainer 9 | GitHub: [hokamsingh](https://github.com/hokamsingh) 10 | 11 | - **KlassnayaAfrodita** – Contributor 12 | GitHub: [KlassnayaAfrodita](https://github.com/KlassnayaAfrodita) 13 | 14 | We thank all contributors for their support and input. If you'd like to contribute, please check the [CONTRIBUTE.md](CONTRIBUTE.md) file. 15 | 16 | --- 17 | -------------------------------------------------------------------------------- /examples/rest-example/src/upload/upload_module.go: -------------------------------------------------------------------------------- 1 | package upload 2 | 3 | import ( 4 | LessGo "github.com/hokamsingh/lessgo/pkg/lessgo" 5 | ) 6 | 7 | type UploadModule struct { 8 | LessGo.Module 9 | } 10 | 11 | func NewUploadModule() *UploadModule { 12 | service := NewUploadService("uploads") 13 | controller := NewUploadController(service, "/upload") 14 | return &UploadModule{ 15 | Module: *LessGo.NewModule("Upload", 16 | []interface{}{controller}, 17 | []interface{}{service}, 18 | []LessGo.IModule{}, 19 | ), 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /examples/rest-example/src/root_controller.go: -------------------------------------------------------------------------------- 1 | package src 2 | 3 | import LessGo "github.com/hokamsingh/lessgo/pkg/lessgo" 4 | 5 | type RootController struct { 6 | Path string 7 | Service RootService 8 | } 9 | 10 | func NewRootController(s *RootService, path string) *RootController { 11 | return &RootController{ 12 | Path: path, 13 | Service: *s, 14 | } 15 | } 16 | 17 | func (rc *RootController) RegisterRoutes(r *LessGo.Router) { 18 | // r.Get("/hello", func(ctx *LessGo.Context) { 19 | // ctx.Send("Hello world") 20 | // }) 21 | } 22 | -------------------------------------------------------------------------------- /examples/rest-example/src/user/user_module.go: -------------------------------------------------------------------------------- 1 | package user 2 | 3 | import ( 4 | LessGo "github.com/hokamsingh/lessgo/pkg/lessgo" 5 | ) 6 | 7 | type UserModule struct { 8 | LessGo.Module 9 | } 10 | 11 | func NewUserModule() *UserModule { 12 | userService := NewUserService() 13 | userController := NewUserController(userService, "/users") 14 | return &UserModule{ 15 | Module: *LessGo.NewModule("User", 16 | []interface{}{userController}, // Controllers 17 | []interface{}{userService}, // Services 18 | []LessGo.IModule{}, 19 | ), 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/hokamsingh/lessgo 2 | 3 | go 1.22.5 4 | 5 | require ( 6 | github.com/go-redis/redis/v8 v8.11.5 7 | github.com/google/uuid v1.6.0 8 | github.com/gorilla/mux v1.8.1 9 | github.com/gorilla/websocket v1.5.3 10 | github.com/joho/godotenv v1.5.1 11 | github.com/robfig/cron/v3 v3.0.1 12 | go.uber.org/dig v1.18.0 13 | ) 14 | 15 | require ( 16 | github.com/cespare/xxhash/v2 v2.3.0 // indirect 17 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect 18 | github.com/stretchr/testify v1.9.0 // indirect 19 | golang.org/x/net v0.26.0 // indirect 20 | golang.org/x/sys v0.22.0 // indirect 21 | ) 22 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | 4 | # Contributor Code of Conduct 5 | 6 | ## Our Pledge 7 | 8 | We pledge to foster an open and welcoming environment for everyone. All contributors, maintainers, and users are expected to engage respectfully. 9 | 10 | ## Our Standards 11 | 12 | - Be respectful and considerate. 13 | - Provide constructive feedback. 14 | - Avoid offensive language or behavior. 15 | 16 | ## Enforcement 17 | 18 | Instances of inappropriate conduct may be reported to the project team at singhhokam704@gmail.com. We will review and respond to reports in a fair and timely manner. 19 | 20 | ## Scope 21 | 22 | This Code of Conduct applies within all project spaces and interactions. 23 | 24 | --- 25 | -------------------------------------------------------------------------------- /examples/rest-example/src/test/test_module.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | LessGo "github.com/hokamsingh/lessgo/pkg/lessgo" 5 | ) 6 | 7 | type TestModule struct { 8 | LessGo.Module 9 | } 10 | 11 | // NewTestModule creates a new instance of TestModule 12 | func NewTestModule() *TestModule { 13 | testService := NewTestService() 14 | testController := NewTestController(testService, "/test") 15 | 16 | return &TestModule{ 17 | Module: *LessGo.NewModule( // You need to initialize the embedded Module field 18 | "Test", // Name of the module 19 | []interface{}{testController}, // Controllers 20 | []interface{}{testService}, // Services 21 | []LessGo.IModule{}, 22 | ), 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /internal/core/middleware/cookie_parser.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "context" 5 | "net/http" 6 | ) 7 | 8 | type CookieParser struct{} 9 | 10 | func NewCookieParser() *CookieParser { 11 | return &CookieParser{} 12 | } 13 | 14 | type Cookies string 15 | 16 | func (cp *CookieParser) Handle(next http.Handler) http.Handler { 17 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 18 | cookies := r.Cookies() 19 | cookieMap := make(map[string]string) 20 | for _, cookie := range cookies { 21 | cookieMap[cookie.Name] = cookie.Value 22 | } 23 | cookiesKey := Cookies("cookies") 24 | r = r.WithContext(context.WithValue(r.Context(), cookiesKey, cookieMap)) 25 | next.ServeHTTP(w, r) 26 | }) 27 | } 28 | -------------------------------------------------------------------------------- /internal/core/factory/factory.go: -------------------------------------------------------------------------------- 1 | package factory 2 | 3 | import ( 4 | "github.com/hokamsingh/lessgo/internal/core/config" 5 | "github.com/hokamsingh/lessgo/internal/core/di" 6 | "github.com/hokamsingh/lessgo/internal/core/router" 7 | ) 8 | 9 | // App represents the main application structure 10 | type App struct { 11 | Router *router.Router 12 | Container *di.Container 13 | } 14 | 15 | // NewApp creates a new App instance 16 | func NewApp(router *router.Router, container *di.Container) *App { 17 | return &App{ 18 | Router: router, 19 | Container: container, 20 | } 21 | } 22 | 23 | // Start the HTTP server on the specified address 24 | func (app *App) Start(addr string, httpConfig *config.HttpConfig) error { 25 | return app.Router.Listen(addr, httpConfig) 26 | } 27 | -------------------------------------------------------------------------------- /examples/rest-example/src/upload/upload_controller.go: -------------------------------------------------------------------------------- 1 | package upload 2 | 3 | import ( 4 | LessGo "github.com/hokamsingh/lessgo/pkg/lessgo" 5 | ) 6 | 7 | type UploadController struct { 8 | Path string 9 | Service UploadService 10 | } 11 | 12 | func NewUploadController(service *UploadService, path string) *UploadController { 13 | // if !LessGo.ValidatePath(path) { 14 | // log.Fatalf("Invalid path provided: %s", path) 15 | // } 16 | return &UploadController{Path: path, Service: *service} 17 | } 18 | 19 | func (uc *UploadController) RegisterRoutes(r *LessGo.Router) { 20 | size := int64(5 * 1024 * 1024) // 5 mb in bytes 21 | ur := r.SubRouter(uc.Path, LessGo.WithFileUpload("uploads", size, []string{".jpg", ".png"})) 22 | 23 | ur.Post("/files", func(ctx *LessGo.Context) { 24 | ctx.Send("file saved") 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /examples/rest-example/src/root_module.go: -------------------------------------------------------------------------------- 1 | package src 2 | 3 | import ( 4 | "github.com/hokamsingh/lessgo/app/src/test" 5 | "github.com/hokamsingh/lessgo/app/src/upload" 6 | user "github.com/hokamsingh/lessgo/app/src/user" 7 | LessGo "github.com/hokamsingh/lessgo/pkg/lessgo" 8 | ) 9 | 10 | type RootModule struct { 11 | LessGo.Module 12 | } 13 | 14 | func NewRootModule(r *LessGo.Router) *RootModule { 15 | // Initialize and collect all modules 16 | modules := []LessGo.IModule{ 17 | test.NewTestModule(), 18 | upload.NewUploadModule(), 19 | user.NewUserModule(), 20 | } 21 | 22 | // Register all modules 23 | LessGo.RegisterModules(r, modules) 24 | service := NewRootService() 25 | controller := NewRootController(service, "/") 26 | return &RootModule{ 27 | Module: *LessGo.NewModule("Root", []interface{}{controller}, []interface{}{service}, modules), 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | *.yml 8 | 9 | # Output of the go coverage tool 10 | *.out 11 | 12 | # IDE and Editor specific files 13 | .vscode/ 14 | .idea/ 15 | *.sublime-project 16 | *.sublime-workspace 17 | 18 | # Go workspace and build files 19 | bin/ 20 | build/ 21 | dist/ 22 | app/ 23 | uploads/ 24 | temp/ 25 | 26 | # Go modules and cache 27 | vendor/ 28 | # *.mod 29 | # *.sum 30 | 31 | # Logs 32 | *.log 33 | 34 | # Environment variables 35 | .env 36 | 37 | # Ignore the `node_modules` folder if you use any Node.js for frontend 38 | node_modules/ 39 | 40 | # MacOS specific files 41 | .DS_Store 42 | 43 | # Windows specific files 44 | Thumbs.db 45 | 46 | # Docker files 47 | Dockerfile 48 | docker-compose.yml 49 | 50 | .air.toml 51 | 52 | #makefile 53 | Makefile 54 | 55 | *.crt 56 | *.csr 57 | *.key 58 | *.pem -------------------------------------------------------------------------------- /examples/rest-example/src/upload/upload_service.go: -------------------------------------------------------------------------------- 1 | package upload 2 | 3 | import ( 4 | "errors" 5 | "io" 6 | "net/http" 7 | "os" 8 | "path/filepath" 9 | "strings" 10 | 11 | LessGo "github.com/hokamsingh/lessgo/pkg/lessgo" 12 | ) 13 | 14 | type IUploadService interface{} 15 | 16 | type UploadService struct { 17 | UploadDir string 18 | LessGo.BaseService 19 | } 20 | 21 | func NewUploadService(uploadDir string) *UploadService { 22 | return &UploadService{UploadDir: uploadDir} 23 | } 24 | 25 | func (s *UploadService) SaveFile(file http.File, fileName string) (string, error) { 26 | filePath := filepath.Join(s.UploadDir, fileName) 27 | cleanFilePath := filepath.Clean(filePath) 28 | if !strings.HasPrefix(cleanFilePath, s.UploadDir) { 29 | return "", errors.New("invalid file path") 30 | } 31 | destFile, err := os.Create(filePath) 32 | if err != nil { 33 | return "", err 34 | } 35 | defer destFile.Close() 36 | 37 | _, err = io.Copy(destFile, file) 38 | if err != nil { 39 | return "", err 40 | } 41 | 42 | return filePath, nil 43 | } 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 https://github.com/hokamsingh/lessgo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /internal/core/middleware/template.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "context" 5 | "html/template" 6 | "net/http" 7 | "os" 8 | "path/filepath" 9 | ) 10 | 11 | type TemplateMiddleware struct { 12 | Tmpl *template.Template 13 | } 14 | 15 | func NewTemplateMiddleware(templateDir string) *TemplateMiddleware { 16 | tmpl := template.New("") 17 | 18 | // Walk through the directory and parse all .html files 19 | filepath.Walk(templateDir, func(path string, info os.FileInfo, err error) error { 20 | if err == nil && !info.IsDir() && filepath.Ext(path) == ".html" { 21 | tmpl.ParseFiles(path) 22 | } 23 | return nil 24 | }) 25 | 26 | return &TemplateMiddleware{Tmpl: tmpl} 27 | } 28 | 29 | func (tm *TemplateMiddleware) Handle(next http.Handler) http.Handler { 30 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 31 | // Pass the template object into the context 32 | ctx := context.WithValue(r.Context(), templateKey{}, tm.Tmpl) 33 | next.ServeHTTP(w, r.WithContext(ctx)) 34 | }) 35 | } 36 | 37 | type templateKey struct{} 38 | 39 | // GetTemplate returns the template from the context 40 | func GetTemplate(ctx context.Context) *template.Template { 41 | if tmpl, ok := ctx.Value(templateKey{}).(*template.Template); ok { 42 | return tmpl 43 | } 44 | return nil 45 | } 46 | -------------------------------------------------------------------------------- /internal/core/middleware/timeoutMiddleware.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "context" 5 | "net/http" 6 | "time" 7 | ) 8 | 9 | type TimeoutMiddleware struct { 10 | Timeout time.Duration 11 | } 12 | 13 | // NewTimeoutMiddleware creates a new instance of timeout middleware 14 | func NewTimeoutMiddleware(timeout time.Duration) *TimeoutMiddleware { 15 | return &TimeoutMiddleware{Timeout: timeout} 16 | } 17 | 18 | // Handle adds a timeout to the request context 19 | func (tm *TimeoutMiddleware) Handle(next http.Handler) http.Handler { 20 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 21 | 22 | ctx, cancel := context.WithTimeout(r.Context(), tm.Timeout) 23 | defer cancel() 24 | 25 | // Replace the request context with a new context with a timeout 26 | r = r.WithContext(ctx) 27 | 28 | done := make(chan struct{}) 29 | go func() { 30 | next.ServeHTTP(w, r) 31 | close(done) 32 | }() 33 | 34 | // End the request when the timeout is reached or after the main handler completes 35 | select { 36 | case <-done: 37 | // The handler completed its work before the timeout 38 | case <-ctx.Done(): 39 | // Timeout: cancel the request and return 504 status 40 | http.Error(w, http.StatusText(http.StatusGatewayTimeout), http.StatusGatewayTimeout) 41 | } 42 | }) 43 | } 44 | -------------------------------------------------------------------------------- /internal/core/middleware/profiling.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | "time" 7 | ) 8 | 9 | // ProfilingMiddleware represents a structure for profiling requests 10 | type ProfilingMiddleware struct { 11 | } 12 | 13 | // NewProfilingMiddleware creates a new instance of ProfilingMiddleware 14 | func NewProfilingMiddleware() *ProfilingMiddleware { 15 | return &ProfilingMiddleware{} 16 | } 17 | 18 | // Handle processes the requests and measures their execution time 19 | func (pm *ProfilingMiddleware) Handle(next http.Handler) http.Handler { 20 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 21 | start := time.Now() // Record the start time of the request 22 | 23 | // Pass the request to the next handler in the middleware chain 24 | next.ServeHTTP(w, r) 25 | 26 | // After the request is completed, measure the execution time 27 | duration := time.Since(start) 28 | 29 | // Log information about the request and its execution time 30 | log.Printf("Request: %s %s | Time: %v | From IP: %s", r.Method, r.URL.Path, duration, getClientIP(r)) 31 | }) 32 | } 33 | 34 | // getClientIP extracts the client's IP address from the request 35 | func getClientIP(r *http.Request) string { 36 | ip, _, err := net.SplitHostPort(r.RemoteAddr) 37 | if err != nil { 38 | return r.RemoteAddr 39 | } 40 | return ip 41 | } 42 | -------------------------------------------------------------------------------- /internal/core/service/service.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package service provides a base structure and interface for defining and implementing services in the application. 3 | 4 | This package defines a Service interface, which can be extended to implement various services. Additionally, it provides a BaseService struct with a default method implementation. 5 | */ 6 | package service 7 | 8 | // Service defines the interface for all services in the application. 9 | // Implementations of this interface can provide specific functionalities 10 | // required by different parts of the application. 11 | type Service interface { 12 | } 13 | 14 | // BaseService provides a default implementation of the Service interface. 15 | // This struct can be embedded in other service implementations to inherit 16 | // common functionalities or to be extended with custom methods. 17 | type BaseService struct{} 18 | 19 | // PerformTask is a method of BaseService that performs a generic task. 20 | // This method can be overridden by services embedding BaseService to provide 21 | // specific behavior or functionality. 22 | // 23 | // Example: 24 | // 25 | // type MyService struct { 26 | // service.BaseService 27 | // } 28 | // 29 | // func (s *MyService) PerformTask() { 30 | // // Custom task implementation 31 | // fmt.Println("Performing a custom task") 32 | // } 33 | // 34 | // func main() { 35 | // s := MyService{} 36 | // s.PerformTask() // Outputs: Performing a custom task 37 | // } 38 | func (bs *BaseService) PerformTask() { 39 | 40 | } 41 | -------------------------------------------------------------------------------- /tests/lessgo/framework_benchmark_test.go: -------------------------------------------------------------------------------- 1 | package lessgo_test 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | "net/http/httptest" 7 | "testing" 8 | "time" 9 | 10 | LessGo "github.com/hokamsingh/lessgo/pkg/lessgo" 11 | ) 12 | 13 | // BenchmarkHandler benchmarks the /ping handler in the lessgo framework. 14 | func BenchmarkHandler(b *testing.B) { 15 | // Initialize the lessgo app with necessary middlewares 16 | corsOptions := LessGo.NewCorsOptions( 17 | []string{"*"}, 18 | []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}, 19 | []string{"Content-Type", "Authorization"}, 20 | ) 21 | 22 | size := LessGo.ConvertToBytes(int64(1024), LessGo.Kilobytes) 23 | parserOptions := LessGo.NewParserOptions(size * 5) 24 | 25 | rClient := LessGo.NewRedisClient("localhost:6379") 26 | App := LessGo.App( 27 | LessGo.WithCORS(*corsOptions), 28 | LessGo.WithJSONParser(*parserOptions), 29 | LessGo.WithCookieParser(), 30 | LessGo.WithCsrf(), 31 | LessGo.WithXss(), 32 | LessGo.WithCaching(rClient, 5*time.Minute, true), 33 | LessGo.WithRedisRateLimiter(rClient, 100, 1*time.Second), 34 | ) 35 | 36 | // Add a simple /ping route 37 | App.Get("/ping", func(ctx *LessGo.Context) { 38 | ctx.Send("pong") 39 | }) 40 | 41 | // Create a request to benchmark the /ping handler 42 | req, _ := http.NewRequest("GET", "/ping", nil) 43 | w := httptest.NewRecorder() 44 | 45 | log.Println("Starting benchmark") 46 | for i := 0; i < b.N; i++ { 47 | log.Printf("Iteration: %d", i) 48 | App.Mux.ServeHTTP(w, req) 49 | } 50 | log.Println("Benchmark completed") 51 | } 52 | -------------------------------------------------------------------------------- /internal/core/middleware/middleware.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package middleware provides a simple interface and base implementation for creating HTTP middlewares. 3 | 4 | This package defines a `Middleware` interface with a `Handle` method that allows chaining HTTP handlers. It also includes a `BaseMiddleware` struct that provides a basic implementation of the middleware pattern. 5 | 6 | Usage: 7 | 8 | import ( 9 | "net/http" 10 | "github.com/hokamsingh/lessgo/pkg/lessgo/middleware" 11 | ) 12 | 13 | func main() { 14 | mw := &middleware.BaseMiddleware{} 15 | 16 | mux := http.NewServeMux() 17 | mux.Handle("/", mw.Handle(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 18 | w.Write([]byte("Hello, World!")) 19 | }))) 20 | 21 | http.ListenAndServe(":8080", mux) 22 | } 23 | */ 24 | package middleware 25 | 26 | import "net/http" 27 | 28 | // Middleware defines the interface for HTTP middlewares. 29 | // Implementers should provide a `Handle` method that takes an `http.Handler` and returns a new `http.Handler`. 30 | // This allows for wrapping existing handlers with additional functionality. 31 | type Middleware interface { 32 | Handle(next http.Handler) http.Handler 33 | } 34 | 35 | // BaseMiddleware provides a basic implementation of the Middleware interface. 36 | // It allows chaining of HTTP handlers by passing the request to the next handler in the chain. 37 | // 38 | // Example: 39 | // 40 | // mw := &middleware.BaseMiddleware{} 41 | // http.Handle("/", mw.Handle(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 42 | // w.Write([]byte("Hello, World!")) 43 | // }))) 44 | // 45 | // http.ListenAndServe(":8080", nil) 46 | type BaseMiddleware struct{} 47 | 48 | // Handle is the method that wraps an existing `http.Handler` with additional functionality. 49 | // This method calls the next handler in the chain after executing any custom logic. 50 | // 51 | // Example: 52 | // 53 | // mw := &middleware.BaseMiddleware{} 54 | // 55 | // http.Handle("/", mw.Handle(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 56 | // log.Println("Request received") 57 | // w.W 58 | -------------------------------------------------------------------------------- /internal/core/middleware/XSS.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "net/http" 5 | "regexp" 6 | "strings" 7 | ) 8 | 9 | type XSSProtection struct{} 10 | 11 | // Creates a new middleware for XSS protection 12 | func NewXSSProtection() *XSSProtection { 13 | return &XSSProtection{} 14 | } 15 | 16 | // Regular expression to detect potentially harmful XSS patterns, including encoded variants 17 | var unsafePattern = regexp.MustCompile(`(?i)|javascript:|data:text/html|onerror=|onload=|onclick=|