Im trying to have custom error messages for gin validation & followed the advice in this thread: https://github.com/gin-gonic/gin/issues/430
Im trying the gin binding midddleware this way:
package main
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
type itemPostRequest struct {
Name string `json:"name" binding:"required"`
}
func main() {
router := gin.Default()
router.Use(func (c *gin.Context) {
c.Next()
fmt.Println(c.Errors)
})
router.POST("/item", gin.Bind(itemPostRequest{}), func (c *gin.Context) {
fmt.Println("Im inside handler")
req := c.MustGet(gin.BindKey).(*itemPostRequest)
fmt.Println(req)
c.JSON(http.StatusOK, gin.H{"success": true})
})
router.Run()
}
I send the request using Postman but although I have sent the correct request, it always say:
Key: 'itemPostRequest.Name' Error:Field validation for 'Name' failed on the 'required' tag
If I don't use the binding middleware:
router.POST("/item", func (c *gin.Context) {
...
It works but i want to be able to bind and return error before I go to the handler, just like the advice on the thread. Why is this not working? Thank you
thx to the comment, I realized I missed Content-Type application/json. I didn't realize this because I used c.ShouldBindWithJSON before and it didnt need this header.
Related
I'm using the gin framework and the following code works fine for me
import (
"github.com/gin-gonic/gin"
"net/http"
)
type RequestBody struct {
MyRequiredField string `json:"myRequiredField" binding:"required"`
}
func Handle(context *gin.Context) {
var requestBody RequestBody
err := context.ShouldBindJSON(&requestBody)
if err != nil {
context.JSON(http.StatusBadRequest, err.Error())
return
}
// ...
}
I would like to know how I can tell gin that the given struct must be the request body. It must not search for fields in the route parameters or queries.
So is there a way to be more explicit, e.g.
err := context.BindStructToRequestBody(&requestBody)
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.
I've started a small personal API as a learning exercise with Go and while trying to test it I found that the endpoint GET /find/{id} isn't triggered when doing such call in Postman.
Mux Router:
router.HandleFunc("/find/{id}", controller.Find).Methods("GET")
Controller method:
func Find(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id := vars["id"]
...
}
And the former call to the API:
localhost:8080/find/[cb&%AD%87"%8CV
Maybe it's something really simple that I can't really see?
I'm using Gorilla mux,
The implementation is similar, and you can read more about it in here
package HTTPServer
import (
"net/http"
"github.com/gorilla/mux"
)
type Route struct {
Name string
Method string
Pattern string
HandlerFunc http.HandlerFunc
}
type Routes []Route
var routes = Routes{
{"GetFirstForm", "GET", "/firstForm/{id}", GetFirstForm}{
//GetFirstForm getting first form by ECO id
func GetFirstForm(w http.ResponseWriter, r *http.Request) {
var vars = mux.Vars(r)
ecoID := vars["id"]
///your logic
}
I want to get the header data using gin package(golang) in the postman but I don't get any idea how to do it. I search it for google but not getting any answer. Can anyone help me to get the data from the postman header the data I want to get is shown in image.
Image:-
You can get the token header with c.Request.Header["Token"].
Here is a sample code.
package main
import (
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/test", func(c *gin.Context) {
c.JSON(200, gin.H{
"token_data": c.Request.Header["Token"],
})
})
r.Run() // listen and serve on 0.0.0.0:8080
}
Here is an example screenshot of postman.
I use this code and work well
func getProduct(c *gin.Context) {
token := strings.Split(c.Request.Header["Authorization"][0], " ")[1]
c.JSON(200, gin.H{"result": "get product", "token": token})
}
Here is the test data
GET http://localhost:8081/api/v2/product HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaWF0IjoxNTg4OTI4NzY0LCJleHAiOjE1ODg5MzM3NjR9.GrPK-7uEsfpdAYamoqaDFclYwTZ3LOlspoEXUORfSuY
Instead of accessing request object directly, gin provides a getter (easier to use and makes code cleaner). Based on #Shiva accepted answer:
package main
import (
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/test", func(c *gin.Context) {
c.JSON(200, gin.H{
// or c.GetHeader("Authorization")
"token_data": c.GetHeader("Token"),
})
})
r.Run() // listen and serve on 0.0.0.0:8080
}
I want to define a route
/user/{userid}/status
How can I define this kind of route and intercept the userid in handler. Something like this
r.GET("/user/{userid}/status", userStatus)
How can read the userid variable in my Go code in such case?
You may use userid := c.Param("userid"), like this working sample:
package main
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
router := gin.Default()
router.GET("/user/:userid/status", func(c *gin.Context) {
userid := c.Param("userid")
message := "userid is " + userid
c.String(http.StatusOK, message)
fmt.Println(message)
})
router.Run(":8080")
}