Skip to main content
โšก Calmops

Fiber Framework: High-Performance Web Development

Fiber Framework: High-Performance Web Development

Introduction

Fiber is the fastest web framework for Go, inspired by Express.js. It’s designed for high-performance applications with minimal memory footprint. This guide covers building ultra-fast web applications with Fiber.

Core Concepts

Why Fiber?

  • Speed: Fastest web framework for Go
  • Familiar API: Similar to Express.js
  • Low Memory: Minimal allocations
  • Middleware: Extensive middleware ecosystem
  • Validation: Built-in validation support

Good: Basic Fiber Setup

Creating a Fiber Application

package main

import (
	"github.com/gofiber/fiber/v2"
	"github.com/gofiber/fiber/v2/middleware/logger"
	"github.com/gofiber/fiber/v2/middleware/recover"
)

// โœ… GOOD: Basic Fiber application
func main() {
	app := fiber.New()

	// Middleware
	app.Use(logger.New())
	app.Use(recover.New())

	// Routes
	app.Get("/", handleHome)
	app.Get("/users/:id", handleGetUser)
	app.Post("/users", handleCreateUser)

	// Start server
	app.Listen(":8080")
}

func handleHome(c *fiber.Ctx) error {
	return c.JSON(fiber.Map{
		"message": "Welcome to Fiber",
	})
}

func handleGetUser(c *fiber.Ctx) error {
	id := c.Params("id")
	return c.JSON(fiber.Map{
		"id": id,
	})
}

func handleCreateUser(c *fiber.Ctx) error {
	user := struct {
		Name  string `json:"name"`
		Email string `json:"email"`
	}{}

	if err := c.BodyParser(&user); err != nil {
		return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
			"error": err.Error(),
		})
	}

	return c.Status(fiber.StatusCreated).JSON(user)
}

Route Groups

package main

import (
	"github.com/gofiber/fiber/v2"
)

// โœ… GOOD: Route grouping in Fiber
func setupRoutes(app *fiber.App) {
	// API v1
	v1 := app.Group("/api/v1")
	{
		v1.Get("/health", handleHealth)
		v1.Get("/users", handleListUsers)
		v1.Post("/users", handleCreateUser)
	}

	// Protected routes
	protected := app.Group("/api/v1")
	protected.Use(authMiddleware())
	{
		protected.Get("/profile", handleProfile)
		protected.Put("/profile", handleUpdateProfile)
	}

	// Admin routes
	admin := app.Group("/admin")
	admin.Use(authMiddleware(), adminMiddleware())
	{
		admin.Get("/stats", handleStats)
		admin.Delete("/users/:id", handleDeleteUser)
	}
}

func handleHealth(c *fiber.Ctx) error {
	return c.JSON(fiber.Map{"status": "ok"})
}

func handleListUsers(c *fiber.Ctx) error {
	return c.JSON([]string{})
}

func handleCreateUser(c *fiber.Ctx) error {
	return c.Status(fiber.StatusCreated).JSON(fiber.Map{"created": true})
}

func handleProfile(c *fiber.Ctx) error {
	return c.JSON(fiber.Map{"profile": "data"})
}

func handleUpdateProfile(c *fiber.Ctx) error {
	return c.JSON(fiber.Map{"updated": true})
}

func handleStats(c *fiber.Ctx) error {
	return c.JSON(fiber.Map{"stats": "data"})
}

func handleDeleteUser(c *fiber.Ctx) error {
	return c.JSON(fiber.Map{"deleted": true})
}

func authMiddleware() fiber.Handler {
	return func(c *fiber.Ctx) error {
		token := c.Get("Authorization")
		if token == "" {
			return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
				"error": "Unauthorized",
			})
		}
		return c.Next()
	}
}

func adminMiddleware() fiber.Handler {
	return func(c *fiber.Ctx) error {
		// Check admin role
		return c.Next()
	}
}

Good: Middleware

Creating Fiber Middleware

package main

import (
	"github.com/gofiber/fiber/v2"
	"log"
	"time"
)

// โœ… GOOD: Logging middleware
func loggingMiddleware(c *fiber.Ctx) error {
	start := time.Now()

	err := c.Next()

	duration := time.Since(start)
	log.Printf("%s %s %d %v",
		c.Method(),
		c.Path(),
		c.Response().StatusCode(),
		duration,
	)

	return err
}

// โœ… GOOD: Rate limiting middleware
func rateLimitMiddleware(c *fiber.Ctx) error {
	// Implement rate limiting
	return c.Next()
}

// โœ… GOOD: CORS middleware
func corsMiddleware(c *fiber.Ctx) error {
	c.Set("Access-Control-Allow-Origin", "*")
	c.Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE")
	c.Set("Access-Control-Allow-Headers", "Content-Type")

	if c.Method() == "OPTIONS" {
		return c.SendStatus(fiber.StatusNoContent)
	}

	return c.Next()
}

// โœ… GOOD: Error handling middleware
func errorHandlingMiddleware(c *fiber.Ctx) error {
	defer func() {
		if err := recover(); err != nil {
			log.Printf("Panic: %v", err)
			c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
				"error": "Internal server error",
			})
		}
	}()
	return c.Next()
}

Good: Request Handling

Binding and Validation

package main

import (
	"github.com/gofiber/fiber/v2"
)

// โœ… GOOD: Struct with validation tags
type User struct {
	Name  string `json:"name" validate:"required,min=3,max=50"`
	Email string `json:"email" validate:"required,email"`
	Age   int    `json:"age" validate:"min=0,max=150"`
}

// โœ… GOOD: Parse JSON body
func handleCreateUserWithValidation(c *fiber.Ctx) error {
	user := new(User)

	if err := c.BodyParser(user); err != nil {
		return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
			"error": "Invalid request",
		})
	}

	return c.Status(fiber.StatusCreated).JSON(user)
}

// โœ… GOOD: Extract query parameters
func handleSearch(c *fiber.Ctx) error {
	query := c.Query("q")
	limit := c.Query("limit", "10")

	return c.JSON(fiber.Map{
		"query": query,
		"limit": limit,
	})
}

// โœ… GOOD: Extract path parameters
func handleGetByID(c *fiber.Ctx) error {
	id := c.Params("id")
	return c.JSON(fiber.Map{
		"id": id,
	})
}

// โœ… GOOD: Set response headers
func handleWithHeaders(c *fiber.Ctx) error {
	c.Set("X-Custom-Header", "value")
	return c.JSON(fiber.Map{"message": "ok"})
}

// โœ… GOOD: Set cookies
func handleCookies(c *fiber.Ctx) error {
	c.Cookie(&fiber.Cookie{
		Name:     "session",
		Value:    "abc123",
		Expires:  time.Now().Add(24 * time.Hour),
		HTTPOnly: true,
	})
	return c.JSON(fiber.Map{"message": "cookie set"})
}

Advanced Patterns

Custom Error Handler

package main

import (
	"github.com/gofiber/fiber/v2"
)

// โœ… GOOD: Custom error handler
type ErrorResponse struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
	Details string `json:"details,omitempty"`
}

func customErrorHandler(c *fiber.Ctx, err error) error {
	code := fiber.StatusInternalServerError
	message := "Internal server error"

	if e, ok := err.(*fiber.Error); ok {
		code = e.Code
		message = e.Message
	}

	return c.Status(code).JSON(ErrorResponse{
		Code:    code,
		Message: message,
	})
}

// โœ… GOOD: Using custom error handler
func setupErrorHandling(app *fiber.App) {
	app.Use(func(c *fiber.Ctx) error {
		return c.Next()
	})
}

File Upload

package main

import (
	"github.com/gofiber/fiber/v2"
)

// โœ… GOOD: Handle file upload
func handleFileUpload(c *fiber.Ctx) error {
	file, err := c.FormFile("file")
	if err != nil {
		return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
			"error": "No file provided",
		})
	}

	// Save file
	if err := c.SaveFile(file, "./uploads/"+file.Filename); err != nil {
		return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
			"error": "Upload failed",
		})
	}

	return c.JSON(fiber.Map{
		"filename": file.Filename,
		"size":     file.Size,
	})
}

Performance Optimization

Efficient Request Handling

package main

import (
	"github.com/gofiber/fiber/v2"
)

// โœ… GOOD: Reuse buffers for performance
func handleLargeResponse(c *fiber.Ctx) error {
	// Fiber automatically manages buffers efficiently
	return c.JSON(fiber.Map{
		"data": "large response",
	})
}

// โœ… GOOD: Stream large files
func handleStreamFile(c *fiber.Ctx) error {
	return c.SendFile("./large-file.bin")
}

// โœ… GOOD: Use connection pooling
func setupDatabase(app *fiber.App) {
	// Configure connection pooling
}

Best Practices

1. Use Middleware for Cross-Cutting Concerns

// โœ… GOOD: Middleware for logging, auth, etc.
app.Use(loggingMiddleware)
app.Use(authMiddleware())

// โŒ BAD: Repeating logic in handlers
func handler(c *fiber.Ctx) error {
	// Log
	// Check auth
	// Do work
}

2. Validate Input

// โœ… GOOD: Use validation tags
type Request struct {
	Email string `json:"email" validate:"required,email"`
	Age   int    `json:"age" validate:"min=0,max=150"`
}

// โŒ BAD: Manual validation
type BadRequest struct {
	Email string
	Age   int
}

3. Handle Errors Consistently

// โœ… GOOD: Consistent error responses
return c.Status(fiber.StatusBadRequest).JSON(ErrorResponse{
	Code:    fiber.StatusBadRequest,
	Message: "Invalid input",
})

// โŒ BAD: Inconsistent error handling
return c.SendString("Error")

Resources

Summary

Fiber is the fastest web framework for Go, perfect for high-performance applications. Use route groups for organization, middleware for cross-cutting concerns, and proper validation for robust applications. Fiber’s speed and low memory footprint make it ideal for building scalable web services.

Comments