Important
The project is currently in BETA. Expect API changes and bugs.
Small framework designed for HTMX-style websites, heavily inspired by Gin.
- Based on HTTPRouter — a high-performance, zero-allocations router.
- High-performance (benchmarks).
- Middleware support with method/path based injection & automatic ordering.
- Static files with caching & checksums.
- Pre-parsed HTML page rendering.
- 0% AI (human slop only).
The project can be found here
// Custom struct to be stored in w3.Context as user's current session
type User struct {
Name, Token string
}
// Placeholders
var (
AuthHolders w3.W3AuthHolders[User]
IndexPage w3pages.Holder
)
func init() {
w3logs.Level = w3logs.LOG_DEBUG
// Use './www' as root for HTML & static filepaths.
// Refer to w3pages.UseFS(...) for serving from embeded filesystem
w3pages.SetFSDir("www")
// Parse './www/index.html' template and store it for later use in [IndexHandler]
IndexPage = w3pages.MustLoad("index.html")
}
func main() {
// Handle 100 concurrent requests
engine := w3.NewDefault(100)
// W3Csrf middleware will only inject for state-modifying methods (POST/PUT/etc.)
engine.Use(w3.W3Csrf(
func(ctx *w3.Context) string {
user, authenticated := ctx.Get(AuthHolders.Session)
if !authenticated {
return ""
}
return user.Token
},
))
// Use customized session authentication middleware
AuthHolders = engine.UseCustomized(&w3.W3SessionAuth[User]{
Cookie: "session",
Authenticator: UserAuthenticator,
Required: false,
IgnoreStaticFiles: true,
})
engine.GET("/", IndexHandler)
engine.
// Endpoint-specific middleware
Using(w3.W3MustLogIn()).
DELETE("/:value", EntityHandler)
// Serve './www/static/...' files at `/static/*filepath` endpoint
engine.STATIC("static")
err := engine.ListenAndServe(":8081")
if err != nil {
os.Stderr.WriteString(err.Error())
}
}
func UserAuthenticator(session_id string) (session User, passed bool) {
if session_id == "123" {
return User{Name: "Generic Name", Token: "abc"}, true
}
return User{}, false
}
func IndexHandler(ctx *w3.Context) {
ctx.SendHTML(http.StatusOK, IndexPage, nil)
}
func EntityHandler(ctx *w3.Context) {
value, _ := ctx.Get(AuthHolders.Session)
ctx.SendTextf(
http.StatusOK,
"Hello %s, authenticated as %#v with valid csrf token!",
ctx.Params.ByName("value"),
value,
)
}- Example projects demonstrate most of the functionality.
- For implementing your own middleware, refer to
w3ware*.gofiles; the most primitive middleware can be created withw3.FromHandler(...). - Respond to the client by using
ctx.SendXXXmethods. - Any variables that need to be passed between middleware use holders that are allocated using
w3store.Allocate.
Details can be found in the Go Documentation.
They were performed on projects found under the examples/ directory using the examples/benchmark.sh script.
With the following software & hardware:
| OS | Arch Linux x86_64 |
| Kernel | Linux 7.2.6-arch2-1 |
| CPU | Intel® Core™ i5-10300H (8) @ 4.0 GHz |
| Memory | DDR4 15.44 GiB @ 2933 MT/s |
Benchmark of a basic pure httprouter endpoint (no W3 library involved).
Running 20s test @ http://localhost:8081/example
4 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 1.94ms 1.91ms 21.27ms 86.07%
Req/Sec 56.39k 4.57k 70.73k 70.38%
4502095 requests in 20.08s, 562.45MB read
Requests/sec: 224254.39
Transfer/sec: 28.02MB
Result: 4,502,095 requests in 20 seconds (~56.39k requests / second).
Benchmark of a simple cookie-/header-authenticated endpoint with panic recovery & 200 max concurrent connections.
Running 20s test @ http://localhost:8081/example
4 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 2.20ms 2.25ms 31.69ms 86.06%
Req/Sec 52.62k 4.33k 71.91k 69.12%
4199157 requests in 20.07s, 592.68MB read
Requests/sec: 209231.46
Transfer/sec: 29.53MB
Result: 4,199,157 requests in 20 seconds (~52.62k requests / second).