gofiber / fiber

⚡️ Express inspired web framework written in Go
https://gofiber.io
MIT License
33.81k stars 1.67k forks source link

🤗 [Question]: Don't have fuc get value param in post request with Content-Type: application/json #2078

Closed Nghiait123456 closed 2 years ago

Nghiait123456 commented 2 years ago

Question Description

i have reques to server:

curl --location --request POST 'http://localhost:3000' \
--header 'Content-Type: application/json' \
--data-raw '{
    "name":"json",
    "pass1": "111111"
}'

I want get value of name, pass, i don't find any function support. If in fast http, it's is same PostArgs().Peek() in Fiber, i only one way:

type User struct {
    Name interface{} `json:"name" xml:"name" form:"name"`
    Pass interface{} `json:"pass" xml:"pass" form:"pass"`
}

user  := User{}
if err := c.BodyParser(&persons); err != nil {
    fmt.Println(fmt.Sprintf("have error %s", err.Error()))
} else {
    fmt.Printf("success %v %v %v \n", persons, reflect.TypeOf(persons.Name), reflect.TypeOf(persons.Pass))
    return c.JSON(persons)
}

please help me this problem?

Code Snippet (optional)

No response

Checklist:

welcome[bot] commented 2 years ago

Thanks for opening your first issue here! 🎉 Be sure to follow the issue template! If you need help or want to chat with us, join us on Discord https://gofiber.io/discord

ReneWerner87 commented 2 years ago
package main

import (
    "fmt"
    "log"
    "reflect"

    "github.com/gofiber/fiber/v2"
)

type User struct {
    Name interface{} `json:"name" xml:"name" form:"name"`
    Pass interface{} `json:"pass" xml:"pass" form:"pass"`
}

func main() {
    app := fiber.New()

    app.Post("/", func(ctx *fiber.Ctx) error {

                //  it prefer queryParam over formParam
        fmt.Println("form-param: pass", ctx.FormValue("pass"))
        fmt.Println("query-param: pass", ctx.Query("pass"))
                // internal it is using PostArgs().Peek() -> but this is only working with content-type  application/x-www-form-urlencoded
        fmt.Println("form-param: name", ctx.FormValue("name")) 
        user := User{}
        if err := ctx.BodyParser(&user); err != nil {
            fmt.Println(fmt.Sprintf("have error %s", err.Error()))
            return err
        }

        fmt.Printf("success %v %v %v \n", user, reflect.TypeOf(user.Name), reflect.TypeOf(user.Pass))
        return ctx.JSON(user)
    })

    log.Fatal(app.Listen(":3000"))
}

lets check my code

output for your curl request

form-param: pass 333
query-param: pass 333
form-param: name 
query-param: name 
success {json <nil>} string <nil> 
Nghiait123456 commented 2 years ago

@ReneWerner87 oh, it's my code, it run success, but it's not way i want

I want only get "pass" or "name", i don't want create struct. In fastHttp, this fc is : "PostArgs().Peek()" But Fiber don't Have fc mapping to PostArgs() of FastHttp

ReneWerner87 commented 2 years ago

have you seen

ctx.FormValue("name")

internal it uses PostArgs().Peek()

ReneWerner87 commented 2 years ago

https://github.com/gofiber/fiber/blob/012a2b16a5a391f76701431027224d69897e7fb2/ctx.go#L549 -> https://github.com/valyala/fasthttp/blob/2f1e949d91d0ba1817afd80d7c981fafe7154774/server.go#L1097-L1114

Nghiait123456 commented 2 years ago

@ReneWerner87 oh, some thing went wrong, this code not run succes with application json:

ctx.FormValue("pass") not work with application json:

try

curl --location --request POST 'http://localhost:3000' \
--header 'Content-Type: application/json' \
--data-raw '{
    "name":"json",
    "pass": "3333333333333333"
}'
package main

import (
    "fmt"
    "log"
    "reflect"

    "github.com/gofiber/fiber/v2"
)

type User struct {
    Name interface{} `json:"name" xml:"name" form:"name"`
    Pass interface{} `json:"pass" xml:"pass" form:"pass"`
}

func main() {
    app := fiber.New()

    app.Post("/", func(ctx *fiber.Ctx) error {

                //  it prefer queryParam over formParam
        fmt.Println("form-param: pass", ctx.FormValue("pass"))
        fmt.Println("query-param: pass", ctx.Query("pass"))
                // internal it is using PostArgs().Peek() -> but this is only working with content-type  application/x-www-form-urlencoded
        fmt.Println("form-param: name", ctx.FormValue("name")) 
        user := User{}
        if err := ctx.BodyParser(&user); err != nil {
            fmt.Println(fmt.Sprintf("have error %s", err.Error()))
            return err
        }

        fmt.Printf("success %v %v %v \n", user, reflect.TypeOf(user.Name), reflect.TypeOf(user.Pass))
        return ctx.JSON(user)
    })

    log.Fatal(app.Listen(":3000"))
}

it not work with code of you

my device: ubuntu server v18, go 1.18

ReneWerner87 commented 2 years ago

It's only working with application/x-www-form-urlencoded

ReneWerner87 commented 2 years ago

PostArgs().Peek() and formValue will not work with json form data

Nghiait123456 commented 2 years ago

@ReneWerner87 it's my problem in first Q/A i don't find fc work on application - json

i don't want create new struct and pass to body ctx.BodyParser(), i only want get one param please suggest me ?

ReneWerner87 commented 2 years ago

unfortunately not possible without parsing the json you can not get the individual values for this structure

Nghiait123456 commented 2 years ago

thank you @ReneWerner87