Go Fiber handler func error when function with dependecy injection - go

So I try to write code for handle func to router. But I get the error message like this "cannot use controller.UserController.FindAll (value of type func(_ controller.UserController, c *fiber.Ctx) error) as type func(*fiber.Ctx) error in argument to app.Get"
this the code.
package route
package route
import (
"go_fiber/controller"
"github.com/gofiber/fiber/v2"
)
func RouteInit(app *fiber.App) {
app.Get("/users", controller.UserController.FindAll ) //this line is error
}
package controller
package controller
import (
"go_fiber/model/web"
"go_fiber/service"
"github.com/gofiber/fiber/v2"
)
type UserController interface{
// Create(c *fiber.Ctx)
// Update(c *fiber.Ctx)
FindAll(c *fiber.Ctx) error
// FindById(c *fiber.Ctx)
// Delete(c *fiber.Ctx)
}
type UserControllerImpl struct {
UserService service.UserService
}
func NewUserController(UserService service.UserService) UserController {
return &UserControllerImpl{
UserService: UserService,
}
}
func (controller *UserControllerImpl) FindAll(c *fiber.Ctx) error {
userResponse := controller.UserService.FindAll(c)
webResponse := web.WebResponse{
Code: 200,
Status: "success",
Data: userResponse,
}
c.JSON(webResponse)
return nil
}
How to fix it?
EDIT
So this is solve. This code the solve code
package main
package main
import (
"go_fiber/app"
"go_fiber/controller"
"go_fiber/repository"
"go_fiber/route"
"go_fiber/service"
"github.com/gofiber/fiber/v2"
)
func main(){
db := app.NewDB()
app.CreateDatabase(db)
app := fiber.New()
userRepository := repository.NewUserRepository()
userService := service.NewUserService(userRepository, db)
userController := controller.NewUserController(userService)
route.RouteInit(app, userController)
app.Listen(":3000")
}
package route
package route
import (
"go_fiber/controller"
"github.com/gofiber/fiber/v2"
)
func RouteInit(app *fiber.App, userController controller.UserController) {
app.Get("/users", userController.FindAll)
}

Related

Why Fiber duplicate GET endpoint whith a HEAD endpoint

these is my api and i don't know what is the problem for that endpoints duplicated, i was trying if is something of config but there is not nothing about in their documentation
package main
import (
"aurora/routes"
"fmt"
"github.com/gofiber/fiber/v2"
)
func main() {
app := fiber.New(fiber.Config{
AppName: "Aurora Api V1",
})
routes.ServerRoutes(app)
app.Get("/AAAAAAAA", func(c *fiber.Ctx) error {
return c.JSON("hellow from login")
})
routesList := app.GetRoutes()
for i, route := range routesList {
fmt.Printf("%d - %d\n", i+1, route)
}
app.Listen(":3000")
}
package routes
import (
"aurora/routes/user"
"github.com/gofiber/fiber/v2"
)
func ServerRoutes(server *fiber.App) {
user.UserRoutes(server.Group("/user"))
}
package user
import "github.com/gofiber/fiber/v2"
func UserRoutes(router fiber.Router) {
router.Get("/login", func(c *fiber.Ctx) error {
return c.JSON("hellow from login")
})
router.Get("/logout", func(c *fiber.Ctx) error {
return c.JSON("hellow from logout")
})
router.Get("/signup", func(c *fiber.Ctx) error {
return c.JSON("hellow from signup")
})
}
i want that golang just map GET endpoints not HEAD endpoints, or there a reason for that?
I think HEAD method is used as default for GET routes in Fiber since it's nearly the same thing. Read more about HEAD method in MDN Docs.

How to return struct from golang error method

I am writing a simple rest api using echo framework for route handling. I am trying to maintain centralised error handling using middlewares. In the following code, in the error method implementation I want to return a struct so that I can use that info in custom error Handler
main.go
package main
import log "github.com/sirupsen/logrus"
import "github.com/labstack/echo"
import "net/http"
import "fmt"
func main(){
e := echo.New()
e.GET("process", PostHandler)
e.HTTPErrorHandler = customHTTPErrorHandler
log.Fatal(e.Start(":3000"))
}
func PostHandler(ctx echo.Context) error{
x:= 0;
if x != 0 {
return NewTypeError(1024, "Invalid arguments")
}
return ctx.JSON(http.StatusOK, "message")
}
func customHTTPErrorHandler(err error, c echo.Context) {
fmt.Println("Inside custom error")
fmt.Println(err);
}
error.go
package main
import "fmt"
type Error struct{
Message string
Internal int
}
func (e *Error)Error() string{
fmt.Println("Hello error")
return "error"
}
func NewTypeError( Internal int, Message string) *Error {
fmt.Println(Internal)
fmt.Println(Message)
return &Error{
Message,
Internal,
}
}
I want my output json response to be sent from custom error middleware like this.
{
code: "1024",
message: "Invalid Arguments"
}
Add c.JSON to customHTTPErrorHandler and add json tags to struct Error.
// main.go
package main
import (
"fmt"
"net/http"
"github.com/labstack/echo"
log "github.com/sirupsen/logrus"
)
func main() {
e := echo.New()
e.GET("process", PostHandler)
e.HTTPErrorHandler = customHTTPErrorHandler
log.Fatal(e.Start(":3000"))
}
func PostHandler(ctx echo.Context) error {
x := 0
if x == 0 {
return NewTypeError(http.StatusInternalServerError, 1024, "Invalid arguments")
}
return ctx.JSON(http.StatusOK, "message")
}
func customHTTPErrorHandler(err error, c echo.Context) {
fmt.Println("Inside custom error")
var rerr *Error
switch e := err.(type) {
case *Error:
rerr = e
case *echo.HTTPError:
// todo: improve error conversion
rerr = NewTypeError(e.Code, EchoHttpError, e.Error())
default:
rerr = NewTypeError(http.StatusInternalServerError, InternalError, e.Error())
}
c.JSON(rerr.Code, rerr)
}
// error.go
package main
import (
"fmt"
)
const (
EchoHttpError int = iota
InternalError
)
type Error struct {
Code int `json:"-"` // optional
Message string `json:"message"`
Internal int `json:"internal"`
}
func (e *Error) Error() string {
fmt.Println("Hello error")
return "error"
}
func NewTypeError(code int, internal int, message string) *Error {
fmt.Println(internal)
fmt.Println(message)
return &Error{
Code: code,
Message: message,
Internal: internal,
}
}
you should insert model on argument.
and u should make variable response, same with struct.
if u show code on response, u should add code on error struct.
func ToErrorResponse(err model.Error) *ErrorResponse {
errorResponse := &ErrorResponse{
code: err.Code,
message: err.Message,
}
return errorResponse
}
and call function.

How to set Routes Group in Go Fiber V2 from separated file?

I want to make seperate files for each sub main routes. I am using go 1.17
main.go
package main
import (
"rolling_glory_go/routes"
"github.com/gofiber/fiber/v2"
)
func main() {
app := fiber.New()
app.Get("/", func(c *fiber.Ctx) error {
err := c.SendString("Hello golang!")
return err
})
routes.R_login(app.Group("/login"))
routes.R_users(app.Group("/users"))
app.Listen(":3000")
}
I want to import routes from r_login.go and r_users.go so i could manage many routes from different files and not put many routes from single file in main.go. I got an error like this.
.\main.go:17:26: cannot use app.Group("/login") (type fiber.Router) as type *fiber.Group in argument to routes.R_login: need type assertion
.\main.go:18:26: cannot use app.Group("/users") (type fiber.Router) as type *fiber.Group in argument to routes.R_users: need type assertion
My Structure Folder
r_login.go
package routes
import "github.com/gofiber/fiber/v2"
func R_login(router *fiber.Group) {
router.Get("/", func(c *fiber.Ctx) error {
return c.SendString("respond with a resource")
})
}
r_users.go
package routes
import "github.com/gofiber/fiber/v2"
func R_users(router *fiber.Group) {
router.Get("/", func(c *fiber.Ctx) error {
return c.SendString("respond with a resource")
})
}
How to fix this ?
As you have app.Group("/login") which of type fiber.Router
, just modify R_login to have it accept this type.
package routes
import "github.com/gofiber/fiber/v2"
func R_login(router fiber.Router) {
router.Get("/", func(c *fiber.Ctx) error {
return c.SendString("respond with a resource")
})
}

How do I get the body that was sent? Using gin gonic

How do I get the body that was sent?
package main
import (
"fmt"
"github.com/gin-gonic/gin"
)
func main() {
fmt.Println("Hello, world!")
r := gin.Default()
r.POST("/", func(c *gin.Context) {
body := c.Request.Body
c.JSON(200,body);
})
r.Run(":8080");
}
I make a request via postman
{
"email": "test#gmail.com",
"password": "test"
}
and in response I get empty json {}
what to do?
You can bind the incoming request json as follows:
package main
import (
"github.com/gin-gonic/gin"
)
type LoginReq struct {
Email string
Password string
}
func main() {
r := gin.Default()
r.POST("/", func(c *gin.Context) {
var req LoginReq
c.BindJSON(&req)
c.JSON(200, req)
})
r.Run(":8080")
}
Remember this method gives 400 if there is a binding error. If you want to handle error yourself, try ShouldBindJSON which returns an error if any or nil.

Having trouble splitting go code in multiple files

I have two files main.go and group.go... it looks something like this
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
// Creates a gin router with default middlewares:
// logger and recovery (crash-free) middlewares
router := gin.Default()
v1 := router.Group("/v1")
{
v1.GET("/", func (c *gin.Context) {
c.JSON(http.StatusOK, "{'sup': 'dup'}")
})
groups := v1.Group("/groups")
{
groups.GET("/", groupIndex)
groups.GET("/:id", groupShow)
groups.POST("/", groupCreate)
groups.PUT("/:id", groupUpdate)
groups.DELETE("/:id", groupDelete)
}
}
// Listen and server on 0.0.0.0:8080
router.Run(":3000")
}
So the methods groupIndex, groupCreate, groupUpdate, etc are located in another file under routes/group.go
package main
import (
"strings"
"github.com/gin-gonic/gin"
)
func groupIndex(c *gin.Context) {
var group struct {
Name string
Description string
}
group.Name = "Famzz"
group.Description = "Jamzzz"
c.JSON(http.StatusOK, group)
}
func groupShow(c *gin.Context) {
c.JSON(http.StatusOK, "{'groupShow': 'someContent'}")
}
func groupCreate(c *gin.Context) {
c.JSON(http.StatusOK, "{'groupShow': 'someContent'}")
}
func groupUpdate(c *gin.Context) {
c.JSON(http.StatusOK, "{'groupUpdate': 'someContent'}")
}
func groupDelete(c *gin.Context) {
c.JSON(http.StatusOK, "{'groupDelete': 'someContent'}")
}
But when I try to compile I get the following error
stuff/main.go:21: undefined: groupIndex
stuff/main.go:23: undefined: groupShow
stuff/main.go:24: undefined: groupCreate
stuff/main.go:25: undefined: groupUpdate
stuff/main.go:26: undefined: groupDelete
I'm super new to go, but I thought if you put files in the same package, then they'll have access to each other. What am I doing wrong here?
There are two ways to fix this:
Move group.go to the same directory as main.go.
Import group.go as a package. Change the package declaration on group.go to:
package routes // or the name of your choice
Export the functions by starting them with a capital letter:
func GroupIndex(c *gin.Context) {
Import the package from main:
import "path/to/routes"
...
groups.GET("/", routes.GroupIndex)
The document How To Write Go Code explains this and more.

Resources