Mastering Gobox: A Go Lightweight Framework for Seamless HTTP Routing
This article introduces Gobox, a self‑developed lightweight Go framework that treats each module as a reusable box, explains its HTTP request handling architecture—including System, Router, SimpleRouter, ActionContext, and Controller components—provides detailed code snippets, routing rules, and a complete example with graceful server restart support.
Gobox Overview
Gobox is a lightweight Go framework where each independent module is packaged as a box . All boxes together form the Gobox framework, which can be imported into a project using Go's package management. With Go's dep tool, each box can be managed as a separate project.
HTTP Request Handling Architecture
The framework provides several core objects:
System : Implements the http.Handler interface and defines the ServeHTTP method.
Router : Defines and implements the MVC routing lookup process.
Router Interface
<code>type Router interface {
MapRouteItems(cls ...controller.Controller) // automatically map Controller actions to the routing table
DefineRouteItem(pattern string, cl controller.Controller, actionName string) // manually add a route rule, pattern is a regular expression
FindRoute(path string) *Route // perform route lookup
}
</code>SimpleRouter Implementation
SimpleRouter automatically maps routes based on naming conventions:
Controller name must match ([A‑Z][A‑Za‑z0‑9_]*)Controller$ ; the matched part (lower‑cased) becomes the controller name.
Action name must match ([A‑Z][A‑Za‑z0‑9_]*)Action$ ; after lower‑casing and removing the before and after suffixes, the remaining part is the action name.
Automatic routing rules:
The request URI is interpreted as /controller/action .
If the controller does not exist, it defaults to index (configurable).
If the action does not exist, it defaults to index (configurable).
Custom routing can use regular expressions; captured groups become additional string parameters passed to the action.
ActionContext and Controller
For each request, an ActionContext object is created to hold request and response data.
<code>type ActionContext interface {
Request() *http.Request
ResponseWriter() http.ResponseWriter
ResponseBody() []byte
SetResponseBody(body []byte)
BeforeAction()
AfterAction()
Destruct()
}
</code>The Controller interface creates a new ActionContext for a request.
<code>type Controller interface {
NewActionContext(req *http.Request, respWriter http.ResponseWriter) ActionContext
}
</code>A base implementation provides common fields and methods.
<code>type BaseActionContext struct {
Req *http.Request
RespWriter http.ResponseWriter
RespBody []byte
}
func (c *BaseActionContext) Request() *http.Request { return c.Req }
func (c *BaseActionContext) ResponseWriter() http.ResponseWriter { return c.RespWriter }
func (c *BaseActionContext) ResponseBody() []byte { return c.RespBody }
func (c *BaseActionContext) SetResponseBody(body []byte) { c.RespBody = body }
func (c *BaseActionContext) BeforeAction() { c.RespBody = append(c.RespBody, []byte(" index before ")...) }
func (c *BaseActionContext) AfterAction() { c.RespBody = append(c.RespBody, []byte(" index after ")...) }
func (c *BaseActionContext) Destruct() { println(" index destruct ") }
</code>Example controllers:
<code>type IndexController struct{}
func (c *IndexController) NewActionContext(req *http.Request, respWriter http.ResponseWriter) ActionContext {
return &BaseActionContext{Req: req, RespWriter: respWriter}
}
func (c *IndexController) IndexAction(ctx *BaseActionContext) {
ctx.RespBody = append(ctx.RespBody, []byte(" index action ")...)
}
func (c *IndexController) RedirectAction(ctx *BaseActionContext) {
// use system to issue a 302 redirect
system.Redirect302("https://github.com/goinbox")
}
</code>Graceful HTTP Server (gracehttp)
The framework includes gracehttp , which supports smooth server restarts without dropping connections.
Complete Example
<code>package main
import (
"github.com/goinbox/gohttp/controller"
"github.com/goinbox/gohttp/gracehttp"
"github.com/goinbox/gohttp/router"
"github.com/goinbox/gohttp/system"
"net/http"
)
func main() {
dcl := new(DemoController)
r := router.NewSimpleRouter()
r.DefineRouteItem("^/g/([0-9]+)$", dcl, "get")
r.MapRouteItems(new(IndexController), dcl)
sys := system.NewSystem(r)
gracehttp.ListenAndServe(":8001", sys)
}
// ... (DemoController, DemoActionContext, IndexController definitions as shown above)
</code>Running the program yields responses such as:
<code>curl http://127.0.0.1:8001/ → "index before index action index after "
curl -I http://127.0.0.1:8001/index/redirect → 302 Found with Location header pointing to https://github.com/goinbox
curl http://127.0.0.1:8001/demo/demo → "demo before demo action demo after"
curl http://127.0.0.1:8001/g/123 → "demo before get action id = 123 demo after"
</code>All Destruct methods output their respective messages when the request handling finishes.
Feel free to use Gobox in your projects and report any issues for quick assistance.
360 Zhihui Cloud Developer
360 Zhihui Cloud is an enterprise open service platform that aims to "aggregate data value and empower an intelligent future," leveraging 360's extensive product and technology resources to deliver platform services to customers.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.