GoWeb is a lightweight Go web framework that mimics the structure, design, and fluent API of Java Spring Boot. It embraces convention over configuration using reflection-based routing, request/response DTOs, and a fluent ResponseEntity builder.
- ✅ Spring Boot–style
Controllerstructure (BasePath()+Routes()) - ✅ Automatic path variable and request body binding
- ✅ Strongly-typed
RequestandResponseDTOs - ✅ Fluent
ResponseEntityresponse builder - ✅
HttpStatusconstants (e.g.httpstatus.CREATED) - ✅ Reflection-powered routing using method signatures
- ✅ Minimal, clean design using Go standard library only
- 🚀 Usage
- 🧱 Core Concepts
- 💡 Why These Matter
- 🧪 Response Builder
- 📌 Example JSON Response
- ⚙️ Configuration
- 🌐 CORS Middleware
- ❤️ Inspired By
// models/UserRequest.go
type UserRequest struct {
Name string `json:"name"`
Email string `json:"email"`
}
// models/UserResponse.go
type UserResponse struct {
Id int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}type UsersController struct{}
func (c *UsersController) BasePath() string {
return "/api/v1/users"
}
func (c *UsersController) Routes() []types.Route {
return []types.Route{
{Method: "GET", Path: "/", Handler: "GetAll"},
{Method: "GET", Path: "/{userid}", Handler: "Get"},
{Method: "POST", Path: "/", Handler: "Post"},
{Method: "PUT", Path: "/{userid}", Handler: "Put"},
{Method: "DELETE", Path: "/{userid}", Handler: "Delete"},
}
}
func (c *UsersController) Get(userid int) *types.ResponseEntity {
return ResponseEntity.Status(...).Body(...)
}func main() {
// Create router
router := app.NewRouter()
// Register controllers
router.RegisterControllers(
&controllers.UsersController{}, // You can create a controller through OOP
controllers.New(), // You can create a controller using the builder
)
// Launch the server
logger.Info("Server listening on http://localhost:8080")
err := router.Listen(":8080")
if err != nil {
logger.Fatal("Server failed to launch:", err)
}
}GoWeb is built on a clean and extendable foundation inspired by Spring Boot, but optimized for Go. Below are the key architectural components of the framework:
| Concept | Description |
|---|---|
Controller |
A struct implementing BasePath() and Routes() to define a route group. It may embed ControllerBase to enable optional controller-specific middleware. |
Route |
Defines a single HTTP endpoint via Method, Path, and a string-based Handler name that maps to a function in the controller. |
| DTOs | Plain structs representing request or response data (e.g., UserRequest, UserResponse). GoWeb automatically binds path/query/body values to arguments. |
ResponseEntity |
A fluent builder for setting status, body, and headers. Example: ResponseEntity.Status(200).Body(data).Send(w) or return it directly from controllers. |
HttpStatus |
Enum-style constants for all HTTP status codes, e.g., HttpStatus.OK, HttpStatus.CREATED, etc., making your response code more readable. |
HttpMethod |
Enum-like constants for HTTP methods (GET, POST, etc.) and helpers like IsValid(method) to validate custom usage. |
exception |
Standardized error response utilities like BadRequestException(...) or InternalServerException(...) that send JSON error responses with status codes. |
| Middleware | Middleware objects implement the Middleware interface. They're registered globally or per controller using app.Use(...) or controller.Use(...). |
| Middleware Builder | Use NewMiddlewareBuilder(...) to create strongly-typed, reusable middleware with config (.Config), init logic (.WithInit()), and error hooks (.OnError()). |
| Request Context Helpers | Access path params, query strings, and headers using types.PathVar(ctx, "id"), QueryParam(ctx, "q"), and Header(ctx, "X-Token"). Injected automatically by the router. |
| Configuration | A very straight-forward and easy way to manage configurations that your entire project can easily access via the app/config util |
-
✅ Minimal and clean: Core concepts like
ControllerandRouteare simple, composable structs. -
✅ Extensible: The middleware system uses generics and fluent chaining to support per-middleware config and lifecycle hooks.
-
✅ Type-safe binding: Reflect-based argument resolution injects only what your handler expects — nothing more.
-
✅ Production-ready responses: Use
ResponseEntityandexceptionto consistently shape output without boilerplate. -
✅ Testable architecture: Middleware and controllers can be unit tested with standard Go tools (
httptest).
Example of just sending a message:
ResponseEntity.Status(HttpStatus.OK).
Body(map[string]string{"hello": "world"}).
Header("X-Test", "Value").
Send(w)An example of sending an entity
newUser := Models.UserResponseModel{
Id: newId,
Name: req.Name,
Email: req.Email,
}
return ResponseEntity.Status(201).Body(newUser)HTTP/1.1 201 Created
Content-Type: application/json
X-Custom: example
{
"Id": 1
"Name": "Test"
"Email": "[email protected]"
}This project supports simple, extensible configuration using a single JSON file, typically located at ./application.json. All key server settings—such as port and static resource mappings—are defined here.
{
"server": {
"port": 8080
},
"static": [
{ "path": "/public", "directory": "./public" },
{ "path": "/static", "directory": "./static" }
]
}- Server Port
- The server listens on the port defined at server.port
- you can use any valid port number (e.g.,
8080,3000, etc.).
- Static Resources
- Each entry in the
staticarray maps a URL prefix (path) to a directory on disk (directory). - For example, requests to
/public/example.pngwill serve the file located at./public/example.png.
- Each entry in the
To add more static resources, just simply add new entries in the static array:
"static": [
{ "path": "/assets", "directory": "./assets" },
{ "path": "/media", "directory": "./media" }
]Each mapping supports any valid URL prefix and directory path (relative to your project root)
On startup, the server loads application.json and applies the configuration automatically. Config values are available anywhere in your Go code via the config package (works as a singleton).
import (
"github.com/isaacwallace123/GoWeb/app/config"
"github.com/isaacwallace123/GoUtils/logger"
"github.com/isaacwallace123/GoWeb/app"
)
func main() {
// This is load your configs into a singleton struct.
if err := config.LoadConfig("./dev/application.json"); err != nil {
logger.Fatal("Failed to load config: %v", err)
}
router := app.NewRouter()
// UseStatic is a method that will automatically create a static resource URI to the designated directory
for _, s := range config.Static {
router.UseStatic(s.Path, s.Directory)
}
// Get the configured port (as string)
port := config.PortString() // e.g., ":8080"
}GoWeb includes a built-in CORS middleware that allows you to control which origins, methods, and headers are allowed to access your server across different domains. This is especially useful when building frontend-backend systems or public APIs.
To enable it globally:
app.Use(middlewares.CORS)Then configure it as needed:
middlewares.CORS.Config.AllowedOrigins = []string{"https://example.com"}
middlewares.CORS.Config.AllowedMethods = []string{"GET", "POST"}
middlewares.CORS.Config.AllowedHeaders = []string{"Content-Type", "Authorization"}
middlewares.CORS.Config.AllowCredentials = true| Feature | Description |
|---|---|
AllowedOrigins |
List of allowed domains (use "*" for all) |
AllowedMethods |
List of allowed HTTP methods (GET, POST, etc.) |
AllowedHeaders |
List of allowed request headers |
AllowCredentials |
Enables Access-Control-Allow-Credentials: true |
Auto-Handles OPTIONS |
Returns 204 No Content and skips route logic |
| Blocks Disallowed Methods | Returns 405 Method Not Allowed if the request method is not permitted |
app.Use(middlewares.CORS)
middlewares.CORS.Config.AllowedMethods = []string{"GET"}If a client sends a POST request, the server will respond with:
HTTP/1.1 405 Method Not Allowed
Access-Control-Allow-Methods: GET
Access-Control-Allow-Origin: https://example.com- Java Spring Boot
- Go’s minimalistic standard library
- Clean Architecture principles