The App struct is the core of a Fuego application. It manages routing, middleware, server lifecycle, and configuration.
Creating an App
import " github.com/abdul-hamid-achik/fuego/pkg/fuego "
// Basic app with defaults
app := fuego . New ()
// App with options
app := fuego . New (
fuego . WithAppDir ( "routes" ),
fuego . WithStaticDir ( "public" ),
)
When using file-based routing (the default), you typically don’t need to manually register routes. The app.Scan() and app.Mount() methods handle this automatically.
App Methods
Register HTTP route handlers for different methods. Get app . Get ( pattern string , handler HandlerFunc )
Register a GET route handler. app . Get ( "/users" , func ( c * fuego . Context ) error {
return c . JSON ( 200 , users )
})
Post app . Post ( pattern string , handler HandlerFunc )
Register a POST route handler. app . Post ( "/users" , func ( c * fuego . Context ) error {
var user User
if err := c . Bind ( & user ); err != nil {
return fuego . BadRequest ( "invalid body" )
}
return c . JSON ( 201 , user )
})
Put app . Put ( pattern string , handler HandlerFunc )
Register a PUT route handler for full resource updates. Patch app . Patch ( pattern string , handler HandlerFunc )
Register a PATCH route handler for partial updates. Delete app . Delete ( pattern string , handler HandlerFunc )
Register a DELETE route handler. app . Delete ( "/users/{id}" , func ( c * fuego . Context ) error {
id := c . Param ( "id" )
// Delete user...
return c . NoContent ()
})
Head app . Head ( pattern string , handler HandlerFunc )
Register a HEAD route handler. Options app . Options ( pattern string , handler HandlerFunc )
Register an OPTIONS route handler. RegisterRoute app . RegisterRoute ( method , pattern string , handler HandlerFunc )
Register a route with any HTTP method. app . RegisterRoute ( "CUSTOM" , "/webhook" , handler )
Add middleware to the application. Use app . Use ( mw MiddlewareFunc )
Add global middleware that applies to all routes. app . Use ( fuego . Logger ())
app . Use ( fuego . Recover ())
app . Use ( fuego . CORS ())
Middleware is executed in the order it’s added. Add logging first to capture all requests.
Group app . Group ( pattern string , fn func ( g * RouteGroup ))
Create a route group with shared middleware and path prefix. app . Group ( "/api" , func ( api * fuego . RouteGroup ) {
api . Use ( authMiddleware )
api . Get ( "/users" , listUsers )
api . Post ( "/users" , createUser )
// Nested group
api . Group ( "/admin" , func ( admin * fuego . RouteGroup ) {
admin . Use ( adminOnlyMiddleware )
admin . Get ( "/stats" , getStats )
})
})
Serve static files from a directory. Static app . Static ( path string , dir string )
Serve static files from the specified directory. // Serve files from ./static at /static/*
app . Static ( "/static" , "static" )
// Serve files from ./public at /assets/*
app . Static ( "/assets" , "public" )
The static file server does not list directories. Requests to directories without an index file return 404.
Control the HTTP server. Listen app . Listen ( addr ... string ) error
Start the HTTP server. If no address is provided, uses :3000 or the PORT environment variable. // Default port 3000
app . Listen ()
// Custom port
app . Listen ( ":8080" )
// Custom host and port
app . Listen ( "127.0.0.1:8080" )
Listen blocks until the server is stopped. Use Shutdown for graceful shutdown.
Shutdown app . Shutdown ( ctx context . Context ) error
Gracefully shutdown the server, waiting for active connections to complete. // Graceful shutdown with timeout
ctx , cancel := context . WithTimeout ( context . Background (), 30 * time . Second )
defer cancel ()
if err := app . Shutdown ( ctx ); err != nil {
log . Fatal ( "Shutdown error:" , err )
}
Addr Get the address the server is listening on. go app . Listen ( ":0" ) // Random available port
time . Sleep ( 100 * time . Millisecond )
fmt . Println ( "Listening on" , app . Addr ())
ServeHTTP app . ServeHTTP ( w http . ResponseWriter , r * http . Request )
Implement http.Handler interface. Useful for testing or embedding in other servers. // Use with http.ListenAndServe
http . ListenAndServe ( ":8080" , app )
// Use with httptest
req := httptest . NewRequest ( "GET" , "/" , nil )
rec := httptest . NewRecorder ()
app . ServeHTTP ( rec , req )
Access and modify app configuration. Config Get the application configuration. cfg := app . Config ()
fmt . Println ( "App directory:" , cfg . AppDir )
Router Get the underlying Chi router for advanced routing needs. router := app . Router ()
router . Mount ( "/legacy" , legacyHandler )
RouteTree app . RouteTree () * RouteTree
Get the scanned route tree (after calling Scan). Scan Scan the app directory for routes, middleware, pages, and proxy. if err := app . Scan (); err != nil {
log . Fatal ( "Scan error:" , err )
}
Mount Mount all scanned routes to the router. Call after Scan. app . Scan ()
app . Mount ()
app . Listen ()
Control the request logger. SetLogger app . SetLogger ( config RequestLoggerConfig )
Configure the request logger with custom settings. app . SetLogger ( fuego . RequestLoggerConfig {
Level : fuego . LogLevelInfo ,
ShowIP : true ,
ShowUserAgent : true ,
SkipPaths : [] string { "/health" , "/metrics" },
})
EnableLogger Enable the request logger (enabled by default). DisableLogger Disable the request logger. if os . Getenv ( "GO_ENV" ) == "test" {
app . DisableLogger ()
}
Configure request interception. SetProxy app . SetProxy ( proxy ProxyFunc , config * ProxyConfig ) error
Set a proxy function for request interception. app . SetProxy ( func ( c * fuego . Context ) ( * fuego . ProxyResult , error ) {
if c . Header ( "X-API-Key" ) == "" {
return fuego . ResponseJSON ( 401 , `{"error":"unauthorized"}` ), nil
}
return fuego . Continue (), nil
}, & fuego . ProxyConfig {
Matchers : [] string { "/api/*" },
Excludes : [] string { "/api/health" },
})
HasProxy Check if a proxy is configured.
RouteGroup
Route groups allow you to organize routes with shared middleware and path prefixes.
type RouteGroup struct {
router chi . Router
pattern string
}
RouteGroup Methods
Method Description g.Use(mw)Add middleware to this group g.Get(pattern, handler)Register GET route g.Post(pattern, handler)Register POST route g.Put(pattern, handler)Register PUT route g.Patch(pattern, handler)Register PATCH route g.Delete(pattern, handler)Register DELETE route g.Group(pattern, fn)Create nested group
Example
app . Group ( "/api/v1" , func ( v1 * fuego . RouteGroup ) {
v1 . Use ( fuego . Logger ())
v1 . Group ( "/users" , func ( users * fuego . RouteGroup ) {
users . Get ( "/" , listUsers ) // GET /api/v1/users
users . Post ( "/" , createUser ) // POST /api/v1/users
users . Get ( "/{id}" , getUser ) // GET /api/v1/users/{id}
users . Put ( "/{id}" , updateUser ) // PUT /api/v1/users/{id}
users . Delete ( "/{id}" , deleteUser ) // DELETE /api/v1/users/{id}
})
v1 . Group ( "/posts" , func ( posts * fuego . RouteGroup ) {
posts . Get ( "/" , listPosts )
posts . Post ( "/" , createPost )
})
})
Complete Example
package main
import (
" context "
" log "
" os "
" os/signal "
" syscall "
" time "
" github.com/abdul-hamid-achik/fuego/pkg/fuego "
)
func main () {
app := fuego . New (
fuego . WithAppDir ( "app" ),
fuego . WithStaticDir ( "static" ),
)
// Global middleware
app . Use ( fuego . Logger ())
app . Use ( fuego . Recover ())
app . Use ( fuego . RequestID ())
app . Use ( fuego . CORS ())
// Serve static files
app . Static ( "/static" , "static" )
// API routes
app . Group ( "/api" , func ( api * fuego . RouteGroup ) {
api . Get ( "/health" , func ( c * fuego . Context ) error {
return c . JSON ( 200 , map [ string ] string { "status" : "ok" })
})
})
// Graceful shutdown
go func () {
sigChan := make ( chan os . Signal , 1 )
signal . Notify ( sigChan , syscall . SIGINT , syscall . SIGTERM )
<- sigChan
ctx , cancel := context . WithTimeout ( context . Background (), 30 * time . Second )
defer cancel ()
if err := app . Shutdown ( ctx ); err != nil {
log . Fatal ( "Shutdown error:" , err )
}
}()
// Start server
log . Println ( "Starting server on :3000" )
if err := app . Listen ( ":3000" ); err != nil {
log . Fatal ( err )
}
}
Next Steps