Backend Development 8 min read

Introducing gobox: A Lightweight Go Framework for HTTP Request Handling

This article introduces gobox, a self‑developed lightweight Go framework that treats each module as a box, explains its HTTP request handling architecture, key components such as System, Router, SimpleRouter, ActionContext, Controller, demonstrates graceful‑restart support with gracehttp, and provides a complete runnable example with sample curl outputs.

360 Tech Engineering
360 Tech Engineering
360 Tech Engineering
Introducing gobox: A Lightweight Go Framework for HTTP Request Handling

Today we introduce gobox , a lightweight Go framework designed so that each independent module is a box ; the collection of boxes forms the gobox package, which can be imported using Go's pkg management mechanism. With Go's dep package manager, each box can be managed as a separate project.

The focus of this edition is the HTTP request handling framework within gobox.

HTTP Request Handling Architecture

Important Objects

System

The System implements Go's http.Handler interface; its ServeHTTP method contains the request processing framework.

Router

Defines and implements the MVC routing lookup process.

type Router interface {
    MapRouteItems(cls ...controller.Controller)
    DefineRouteItem(pattern string, cl controller.Controller, actionName string)
    FindRoute(path string) *Route
}

SimpleRouter

A concrete implementation of the Router interface that automatically maps controller and action names based on naming conventions.

Controller name rule: ([A-Z][A-Za-z0-9_]*)Controller$ (lower‑cased to obtain controllerName ).

Action name rule: ([A-Z][A-Za-z0-9_]*)Action$ (lower‑cased and stripped of before / after to obtain actionName ).

Automatic route lookup follows these steps:

Treat request_uri as /controller/action .

If the controller does not exist, default to index (configurable).

If the action does not exist, default to index (configurable).

Custom route lookup can use regular expressions; captured groups become additional string parameters passed to the action.

ActionContext and Controller

ActionContext Interface

type ActionContext interface {
    Request() *http.Request
    ResponseWriter() http.ResponseWriter
    ResponseBody() []byte
    SetResponseBody(body []byte)
    BeforeAction()
    AfterAction()
    Destruct()
}

Controller Interface

type Controller interface {
    NewActionContext(req *http.Request, respWriter http.ResponseWriter) ActionContext
}

BaseActionContext Struct

type BaseActionContext struct {
    Req        *http.Request
    RespWriter http.ResponseWriter
    RespBody   []byte
}

func (this *BaseActionContext) Request() *http.Request { return this.Req }
func (this *BaseActionContext) ResponseWriter() http.ResponseWriter { return this.RespWriter }
func (this *BaseActionContext) ResponseBody() []byte { return this.RespBody }
func (this *BaseActionContext) SetResponseBody(body []byte) { this.RespBody = body }
func (this *BaseActionContext) BeforeAction() { this.RespBody = append(this.RespBody, []byte(" index before ")...) }
func (this *BaseActionContext) AfterAction() { this.RespBody = append(this.RespBody, []byte(" index after ")...) }
func (this *BaseActionContext) Destruct() { println(" index destruct ") }

DemoActionContext (inherits BaseActionContext)

type DemoActionContext struct { *BaseActionContext }

func (this *DemoActionContext) BeforeAction() { this.RespBody = append(this.RespBody, []byte(" demo before ")...) }
func (this *DemoActionContext) AfterAction() { this.RespBody = append(this.RespBody, []byte(" demo after ")...) }
func (this *DemoActionContext) Destruct() { println(" demo destruct ") }

Graceful Restart Server (gracehttp)

Provides an HTTP server that supports zero‑downtime restarts.

gracehttp.ListenAndServe(":8001", sys)

Complete Example

The following Go program demonstrates how to wire the components together, define routes, and start the server.

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)
}

type DemoActionContext struct { *BaseActionContext }
func (this *DemoActionContext) BeforeAction() { this.RespBody = append(this.RespBody, []byte(" demo before ")...) }
func (this *DemoActionContext) AfterAction() { this.RespBody = append(this.RespBody, []byte(" demo after ")...) }
func (this *DemoActionContext) Destruct() { println(" demo destruct ") }

type DemoController struct {}
func (this *DemoController) NewActionContext(req *http.Request, respWriter http.ResponseWriter) ActionContext {
    return &DemoActionContext{&BaseActionContext{Req: req, RespWriter: respWriter}}
}
func (this *DemoController) DemoAction(context *DemoActionContext) {
    context.RespBody = append(context.RespBody, []byte(" demo action ")...)
}

type IndexController struct {}
func (this *IndexController) NewActionContext(req *http.Request, respWriter http.ResponseWriter) ActionContext {
    return &BaseActionContext{Req: req, RespWriter: respWriter}
}
func (this *IndexController) IndexAction(context *BaseActionContext) {
    context.RespBody = append(context.RespBody, []byte(" index action ")...)
}
func (this *IndexController) RedirectAction(context *BaseActionContext) {
    system.Redirect302("https://github.com/goinbox")
}
func (this *IndexController) GetAction(context *BaseActionContext, id string) {
    context.RespBody = append(context.RespBody, []byte(" get action id = "+id)...)
}

Sample Curl Requests and Outputs

curl http://127.0.0.1:8001/
# Output: index before  index action  index after 

curl http://127.0.0.1:8001/index/redirect -I
# HTTP/1.1 302 Found
# Content-Type: text/html; charset=utf-8
# Location: https://github.com/goinbox

curl http://127.0.0.1:8001/demo/demo
# Output: demo before  demo action  demo after

curl http://127.0.0.1:8001/g/123
# Output: demo before  get action id = 123 demo after

All Destruct calls print their respective messages, e.g., index destruct and demo destruct .

Feel free to try gobox, and report any issues for a quick response. Thank you!

backendmiddlewareGoRoutingHTTPGraceful Restartgobox
360 Tech Engineering
Written by

360 Tech Engineering

Official tech channel of 360, building the most professional technology aggregation platform for the brand.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.