2
votes

I can use GET, but I cannot use POST from axios, sending data to my gin-gonic golang server. It works perfectly in Postman. When I shoot over the request with Axios, I get nothing in return.

When I go into the gin-gonic server, it shows that it returned a 500 error. Upon further inspection, I see that none of the post variables had been accessed by gin.

When I have used Postman, the server returns the array as specified. I have a feeling that it might have to do with headers, but I truly am stumped. I have encountered this problem about 6 months ago and never figured it out. Now I remember why I didn't continue with axios and nuxt :).

Here is the golang gin-gonic server route.

func initServer() {
    router := gin.Default()
    config := cors.DefaultConfig()
    config.AddAllowHeaders("*",)
    config.AllowAllOrigins = true
    config.AllowMethods = []string{"POST", "GET"}
    router.Use(cors.New(config))
    v1 := router.Group("/api/v1/stripe")
    {
        v1.POST("/pay", BuyProduct)
        v1.POST("/card", UpdateCard)
        v1.GET("/products", GetAllProducts)
        v1.GET("/products/id/:productId", GetProduct)
        v1.GET("/products/types/:typeId", GetProductType)
        v1.GET("/products/types", GetAllProductTypes)
    }

    // You can get individual args with normal indexing.
    serverAddress := "127.0.0.1:8080"
    if len(os.Args) > 1 {
        arg := os.Args[1]
        serverAddress = fmt.Sprintf("127.0.0.1:%v", arg)
    }

    router.Run(serverAddress)
}

Here is the receiver function that processes the router calls when the endpoint is hit

func BuyProduct(c *gin.Context) {

    postUserID := c.PostForm("userId")
    postProductId := c.PostForm("productId")
    token := c.PostForm("token")

    userId, err := strconv.Atoi(postUserID)
    if err != nil {
    panic(err)
    }
    productId, err := strconv.Atoi(postProductId)
    if err != nil {
        panic(err)
    }

    custy := user.InitCustomer(int64(userId), token)
    custy.GetStripeCustomerData()
    custy.SelectProduct(products.NewProduct(int64(productId)))
    custy.Purchase()

    c.JSON(200, gin.H{"status": 200,
        "product": custy.Product,
        "user": *custy.Saver.User,
        "subscriptions": *custy.Subscriptions,
        "ch": custy.Logs,
    })

    return
}

Here is my axios (nuxt) code.

async purchaseSubscription() {
    const paid = await 
    this.$axios.$post('http://localhost:8080/api/v1/stripe/pay', { data: { 
        userId: "121",
        productId: this.productId,
    }, query: {  } })
    this.paid = paid
},

Here is the error I get in the gin-gonic server in go

2018/10/09 00:12:34 [Recovery] 2018/10/09 - 00:12:34 panic recovered:
POST /api/v1/stripe/pay HTTP/1.1
Host: localhost:8080
Accept: application/json, text/plain, /
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cache-Control: no-cache
Connection: keep-alive
Content-Length: 52
Content-Type: application/json;charset=UTF-8
Dnt: 1
Origin: http://localhost:3000
Pragma: no-cache
Referer: http://localhost:3000/
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36
strconv.Atoi: parsing "": invalid syntax
/usr/local/go/src/runtime/panic.go:502 (0x102aca8)
gopanic: reflectcall(nil, unsafe.Pointer(d.fn), deferArgs(d), uint32(d.siz), uint32(d.siz))
/Users/joealai/go/src/sovrin-mind-stripe/sm-stripe.go:150 (0x15f9ee5)
BuyProduct: panic(err)
[GIN] 2018/10/09 - 00:12:34 | 500 | 1.079498ms | 127.0.0.1 | POST /api/v1/stripe/pay

2

2 Answers

3
votes

I think the problem is not with gin or not gin, it's just with your call. Notice that you're accessing to the c.PostForm values but in your axios call you're not sending a form values, you're sending a json, so in your variables the value is empty. If you're using Postman I suppose you're doing well sending a PostForm, but not in your axios. My recommendation is to still sending a Post (also add a content-type: application-json header) and c.Bind the body to a struct or a map[string]interface{} and then cast to your specific types in your handler.

1
votes

There is no JSON POST Retrieval built into gin-gonic, and from what I understand, in Go's basic Web Server Package. Instead, we need to use c.GetRawData(), and then unmarshal the results into a struct! Since the c.GetRawData() includes data: { userId: 121, productId: 12, token: tok_visa }, the struct must also contain the data json field as well. I hope this helps someone else! Thanks @Carles

type Buy struct {
    Data struct {
        User    int64 `json:"userId" binding:"required"`
        Product int64 `json:"productId" binding:"required"`
        Token   string `json:"token"`
    } `json:"data"`
}

func BuyProduct(c *gin.Context) {

    a := Buy{}
    b, err := c.GetRawData()
    if err != nil {
        panic(err)
    }
    json2.Unmarshal(b, &a)
    userId := a.Data.User
    productId := a.Data.Product

    token := a.Data.Token