Developing APIs in Go is often straightforward, but the simplicity of Go’s net/http
module can sometimes feel too basic. While Go enthusiasts love the raw, unopinionated approach, it can be nice to have a bit of structure to streamline API development.
That’s where Onion comes in. Onion is a lightweight wrapper for Go’s net/http
module. It doesn’t try to be a full-fledged framework; instead, it’s designed to make Go’s HTTP module a little more intuitive and fun to work with by adding a few quality-of-life features like routing, middleware, and response utilities.
Why a Wrapper, Not a Framework?
Onion isn’t about dictating how you should structure your application or providing a one-size-fits-all solution like larger frameworks (e.g., Gin or Echo). Instead, it enhances the net/http
module, letting you:
- Simplify route definitions.
- Add reusable middleware.
- Handle JSON and path parameters more conveniently.
- Keep your code lightweight and close to Go’s idioms.
In short, Onion stays true to Go’s philosophy of simplicity while helping you reduce boilerplate code.
Code Walkthrough: Building an API with Onion
Let’s see how Onion works by building a simple books API. We’ll stick to a basic structure with two files: main.go
for setup and books.go
for route handling.
main.go
This file initializes the Onion app, adds middleware, maps routes, and starts the server.
package main
import (
"fmt"
"github.com/saeedalam/Onion"
"example/books"
)
func main() {
// Create a new Onion app
app := onion.New()
// Map routes from the books module
app.MapRoutes(books.Routes)
// Custom 404 handler
app.NotFoundHandler(func(c *onion.Context) {
c.String(404, "Oops! Page not found.")
})
// Start the server on port 8080
app.Run(":8080")
}
books.go
This file defines routes and handlers for managing books.
package books
import (
"net/http"
"github.com/saeedalam/Onion"
)
var books = []map[string]string{
{"id": "1", "title": "The Go Programming Language", "author": "Alan Donovan"},
{"id": "2", "title": "Go in Action", "author": "William Kennedy"},
}
// GetBooks handles GET /books and returns a list of books
func GetBooks(c *onion.Context) {
c.JSON(http.StatusOK, books)
}
// GetBookByID handles GET /books/:id and returns a specific book by ID
func GetBookByID(c *onion.Context) {
id := c.Param("id")
for _, book := range books {
if book["id"] == id {
c.JSON(http.StatusOK, book)
return
}
}
c.String(http.StatusNotFound, "Book not found")
}
// Routes is a slice of routes for the books module
var Routes = []onion.Route{
{Method: "GET", Pattern: "/books", Handler: GetBooks},
{Method: "GET", Pattern: "/books/:id", Handler: GetBookByID},
}
Running the API
With the above files, you can run your application:
go run main.go
Access the endpoints:
-
GET /books
– Returns a list of all books. -
GET /books/1
– Returns the book with ID 1. -
GET /books/:id
– Returns a 404 if the book doesn’t exist.
Why Use Onion?
Onion keeps it simple:
-
Lightweight: No heavy dependencies or over-engineering—just a neat wrapper around
net/http
. -
Intuitive: If you know
net/http
, you already know Onion. It doesn’t hide Go’s native features. - Convenient: Reduces boilerplate for routing, middleware, and responses.
Want to Make It Better?
Onion is just the beginning. It’s a fun project to make HTTP development with Go a little more enjoyable. There’s room for improvement, and if you’re interested in contributing, here are some ideas:
- Add JSON body parsing.
- Enhance middleware with features like short-circuiting.
- Support more advanced route matching.
Visit the Onion GitHub repository to check out the code, file an issue, or contribute a pull request. Together, we can make Onion even neater!
Onion is not about replacing frameworks; it’s about making Go’s net/http
a little more pleasant to work with. If you’re starting with Go or building a quick prototype, give Onion a try. It’s a lightweight wrapper that helps you stay productive while keeping the codebase simple.
Source link
lol