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

Architecture Diagram
Architecture Diagram

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!

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

middlewareroutingHTTPgraceful 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

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.