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!
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