keyboard_tabSkip to content
listGoAPI Essential

ใช้งานร่วมกับ Fiber

สารบัญ

ประยุกต์ใช้กับ Fiber

bash
go get github.com/gofiber/fiber/v2

main.go

go
package main

import (
  "fmt"
  "github.com/gofiber/fiber/v2"
  "gorm.io/driver/postgres"
  "gorm.io/gorm"
  "gorm.io/gorm/logger"
  "log"
  "os"
  "time"
)

const (
  host     = "localhost"  // or the Docker service name if running in another container
  port     = 5432         // default PostgreSQL port
  user     = "myuser"     // as defined in docker-compose.yml
  password = "mypassword" // as defined in docker-compose.yml
  dbname   = "mydatabase" // as defined in docker-compose.yml
)

func main() {
  // Configure your PostgreSQL database details here
  dsn := fmt.Sprintf("host=%s port=%d user=%s "+
    "password=%s dbname=%s sslmode=disable",
    host, port, user, password, dbname)

  // New logger for detailed SQL logging
  newLogger := logger.New(
    log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
    logger.Config{
      SlowThreshold: time.Second, // Slow SQL threshold
      LogLevel:      logger.Info, // Log level
      Colorful:      true,        // Enable color
    },
  )

  db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{
    Logger: newLogger,
  })

  if err != nil {
    panic("failed to connect to database")
  }

  // Migrate the schema
  db.AutoMigrate(&Book{})

  // Setup Fiber
  app := fiber.New()

  // CRUD routes
  app.Get("/books", func(c *fiber.Ctx) error {
    return getBooks(db, c)
  })
  app.Get("/books/:id", func(c *fiber.Ctx) error {
    return getBook(db, c)
  })
  app.Post("/books", func(c *fiber.Ctx) error {
    return createBook(db, c)
  })
  app.Put("/books/:id", func(c *fiber.Ctx) error {
    return updateBook(db, c)
  })
  app.Delete("/books/:id", func(c *fiber.Ctx) error {
    return deleteBook(db, c)
  })

  // Start server
  log.Fatal(app.Listen(":8000"))
}

models.go

go
package main

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

type Book struct {
  gorm.Model
  Name        string `json:"name"`
  Author      string `json:"author"`
  Description string `json:"description"`
}

// getBooks retrieves all books
func getBooks(db *gorm.DB, c *fiber.Ctx) error {
  var books []Book
  db.Find(&books)
  return c.JSON(books)
}

// getBook retrieves a book by id
func getBook(db *gorm.DB, c *fiber.Ctx) error {
  id := c.Params("id")
  var book Book
  db.First(&book, id)
  return c.JSON(book)
}

// createBook creates a new book
func createBook(db *gorm.DB, c *fiber.Ctx) error {
  book := new(Book)
  if err := c.BodyParser(book); err != nil {
    return err
  }
  db.Create(&book)
  return c.JSON(book)
}

// updateBook updates a book by id
func updateBook(db *gorm.DB, c *fiber.Ctx) error {
  id := c.Params("id")
  book := new(Book)
  db.First(&book, id)
  if err := c.BodyParser(book); err != nil {
    return err
  }
  db.Save(&book)
  return c.JSON(book)
}

// deleteBook deletes a book by id
func deleteBook(db *gorm.DB, c *fiber.Ctx) error {
  id := c.Params("id")
  db.Delete(&Book{}, id)
  return c.SendString("Book successfully deleted")
}

อันนี้ก็จะเป็น CRUD ฉบับสมบูรณ์ (ที่สามารถประยุกต์ใช้กับของจริงได้)

Middleware กับ User

Note

  • ทำการเพิ่ม Table User ขึ้นมา ผ่าน Gorm (เก็บ email unique, password แบบ hash)
  • Login แล้วเก็บ JWT Token ไว้

ทำการลง package เพิ่ม

bash
go get golang.org/x/crypto/bcrypt
go get github.com/golang-jwt/jwt/v4

main.go

go
package main

import (
  "fmt"
  "github.com/gofiber/fiber/v2"
  "gorm.io/driver/postgres"
  "gorm.io/gorm"
  "gorm.io/gorm/logger"
  "github.com/golang-jwt/jwt/v4"
  "log"
  "os"
  "time"
)

func authRequired(c *fiber.Ctx) error {
  cookie := c.Cookies("jwt")

  token, err := jwt.ParseWithClaims(cookie, &jwt.StandardClaims{}, func(token *jwt.Token) (interface{}, error) {
      return jwtSecretKey, nil
  })

  if err != nil || !token.Valid {
      return c.SendStatus(fiber.StatusUnauthorized)
  }

  return c.Next()
}

func main() {
  // Code GORM เหมือนเดิม

  // add For prevent auth
  app.Use("/books", authRequired)

  // CRUD routes = API Set book ตัวเดิม

  app.Post("/register", func(c *fiber.Ctx) error {
    return createUser(db, c)
  })

  app.Post("/login", func(c *fiber.Ctx) error {
    return loginUser(db, c)
  })

  // Start server
  log.Fatal(app.Listen(":8000"))
}

models.go

go
package main

import (
  "github.com/gofiber/fiber/v2"
  "github.com/golang-jwt/jwt/v4"
  "golang.org/x/crypto/bcrypt"
  "gorm.io/gorm"
  "time"
)

type User struct {
  gorm.Model
  Email    string `gorm:"unique"`
  Password string
}


// createUser handles user registration
func createUser(db *gorm.DB, c *fiber.Ctx) error {
  user := new(User)
  if err := c.BodyParser(user); err != nil {
    return err
  }

  // Encrypt the password
  hashedPassword, err := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost)
  if err != nil {
    return err
  }
  user.Password = string(hashedPassword)

  // Create user
  db.Create(user)
  return c.JSON(user)
}


// loginUser handles user login
func loginUser(db *gorm.DB, c *fiber.Ctx) error {
  var input User
  var user User

  if err := c.BodyParser(&input); err != nil {
    return err
  }

  // Find user by email
  db.Where("email = ?", input.Email).First(&user)

  // Check password
  if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(input.Password)); err != nil {
    return c.SendStatus(fiber.StatusUnauthorized)
  }

  // Create JWT token
  token := jwt.New(jwt.SigningMethodHS256)
  claims := token.Claims.(jwt.MapClaims)
  claims["user_id"] = user.ID
  claims["exp"] = time.Now().Add(time.Hour * 72).Unix()

  t, err := token.SignedString(jwtSecretKey)
  if err != nil {
    return c.SendStatus(fiber.StatusInternalServerError)
  }

  // Set cookie
  c.Cookie(&fiber.Cookie{
    Name:     "jwt",
    Value:    t,
    Expires:  time.Now().Add(time.Hour * 72),
    HTTPOnly: true,
  })

  return c.JSON(fiber.Map{"message": "success"})
}