ใช้งานร่วมกับ Fiber
ประยุกต์ใช้กับ Fiber
go get github.com/gofiber/fiber/v2
- main.go
- models.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"))
}
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 เพิ่ม
go get golang.org/x/crypto/bcrypt
go get github.com/golang-jwt/jwt/v4
- main.go
- models.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"))
}
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"})
}