web-dev-qa-db-fra.com

Comment obtenir le JSON du corps d'une demande en cours

Je suis un débutant avec Go, mais pour l'instant je l'aime beaucoup.

J'ai un problème que je n'arrive pas à comprendre. Je migre une API de Node to Go et il y a ce journal où je dois capturer le corps d'un POST TEL QUEL et enregistrez-le dans une colonne de type jsonb dans une base de données Postgresql.

Cela signifie que je ne peux pas utiliser un struct ou quelque chose de prédéterminé.

Le POST est fait avec le corps brut Content-Type: application/json Comme ceci:

{
    "debug": false,
    "order_id_gea": 326064,
    "increment_id_gea": 200436102,
    "date": "2017-05-18T01:44:44+00:00",
    "total_amount": 10000.00,
    "currency": "MXN",
    "payment_method": "Referencia bancaria",
    "reference": "857374",
    "buyer": {
        "buyer_id_gea": 1234,
        "full_name": "Juan Perez Martinez",
        "email": "[email protected]",
        "phone": "5512341234"
    },
    "products": [
        {
            "sku":"PEP16114",
            "price": 10000.00,
            "currency": "MXN",
            "student": {
                "school_id_gea": 172,
                "grade_id_gea": 119,
                "level_id_gea": 36,
                "name": "Benancio",
                "last_name": "Perez",
                "second_last_name": "Garcia",
                "email": "[email protected]"
            }
        }
    ]
}

On Node + Hapi est assez simple:

const payload = request.payload

puis je peux accéder au JSON à partir de payload.

J'utilise Go avec Echo, donc context est un wrapper où je peux trouver Request() *http.Request.

J'ai essayé ce qui suit, mais à chaque fois le résultat est vide ou une erreur car il est vide:

var v interface{}
err := json.NewDecoder(context.Request().Body).Decode(&v)
if err != nil {
    return result, err
}
fmt.Println(v)

Résultat: EOF

-

m := echo.Map{}
if err := context.Bind(&m); err != nil {
    return result, err
}
fmt.Println(m)

Code de résultat 400, message EOF

-

body, error := ioutil.ReadAll(context.Request().Body)
if error != nil {
    return result, error
}
fmt.Println(body)

Résultat []

-

Qu'est-ce que je manque et/ou fais de mal? Merci!

6
transistor

TIL que http.Response.Body Est un tampon, ce qui signifie qu'une fois lu, il ne peut plus être lu.

C'est comme un jet d'eau, vous pouvez le voir et le mesurer en passant mais une fois qu'il est parti, il est parti.

Cependant, sachant cela, il existe une solution de contournement, vous devez "attraper" le corps et le restaurer:

// Read the Body content
var bodyBytes []byte
if context.Request().Body != nil {
    bodyBytes, _ = ioutil.ReadAll(context.Request().Body)
}

// Restore the io.ReadCloser to its original state
context.Request().Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))

// Continue to use the Body, like Binding it to a struct:
order := new(models.GeaOrder)
error := context.Bind(order)

Maintenant, vous pouvez utiliser context.Request().Body ailleurs.

Sources:

http://grokbase.com/t/gg/golang-nuts/12adq8a2ys/go-nuts-re-reading-http-response-body-or-any-reader

https://medium.com/@xoen/golang-read-from-an-io-readwriter-without-loosing-its-content-2c6911805361

14
transistor