在render.Bind中清空http.Request.Body。

huangapple go评论125阅读模式
英文:

Chi empty http.Request.Body in render.Bind

问题

我正在使用github.com/pressly/chi构建这个简单的程序,我尝试从http.Request.Body解码一些JSON:

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "net/http"
  6. "github.com/pressly/chi"
  7. "github.com/pressly/chi/render"
  8. )
  9. type Test struct {
  10. Name string `json:"name"`
  11. }
  12. func (p *Test) Bind(r *http.Request) error {
  13. err := json.NewDecoder(r.Body).Decode(p)
  14. if err != nil {
  15. return err
  16. }
  17. return nil
  18. }
  19. func main() {
  20. r := chi.NewRouter()
  21. r.Post("/products", func(w http.ResponseWriter, r *http.Request) {
  22. var p Test
  23. // err := render.Bind(r, &p)
  24. err := json.NewDecoder(r.Body).Decode(&p)
  25. if err != nil {
  26. panic(err)
  27. }
  28. fmt.Println(p)
  29. })
  30. http.ListenAndServe(":8080", r)
  31. }

当我不使用render.Bind()(来自"github.com/pressly/chi/render")时,它按预期工作。

然而,当我取消注释err := render.Bind(r, &p)这一行,并注释掉err := json.NewDecoder(r.Body).Decode(&p)这一行时,它会出现EOF的panic错误:

2017/06/20 22:26:39 http: panic serving 127.0.0.1:39696: EOF

因此,json.Decode()失败了。

我是否做错了什么,或者在调用render.Bind()之前,http.Request.Body已经在其他地方被读取了?

英文:

I am using github.com/pressly/chi to build this simple program where I try to decode some JSON from the http.Request.Body:

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "net/http"
  6. "github.com/pressly/chi"
  7. "github.com/pressly/chi/render"
  8. )
  9. type Test struct {
  10. Name string `json:"name"`
  11. }
  12. func (p *Test) Bind(r *http.Request) error {
  13. err := json.NewDecoder(r.Body).Decode(p)
  14. if err != nil {
  15. return err
  16. }
  17. return nil
  18. }
  19. func main() {
  20. r := chi.NewRouter()
  21. r.Post("/products", func(w http.ResponseWriter, r *http.Request) {
  22. var p Test
  23. // err := render.Bind(r, &p)
  24. err := json.NewDecoder(r.Body).Decode(&p)
  25. if err != nil {
  26. panic(err)
  27. }
  28. fmt.Println(p)
  29. })
  30. http.ListenAndServe(":8080", r)
  31. }

When I don't use render.Bind() (from "github.com/pressly/chi/render"), it works as expected.

However, when I uncomment the line err := render.Bind(r, &p) and I comment the line err := json.NewDecoder(r.Body).Decode(&p), it panics with EOF :
> 2017/06/20 22:26:39 http: panic serving 127.0.0.1:39696: EOF

and thus the json.Decode() fails.

Am I doing something wrong or is the http.Request.Body is already read somewhere else before render.Bind() is called?

答案1

得分: 4

render.Bind的目的是执行解码并执行Bind(r)以进行解码后的操作。

例如:

  1. type Test struct {
  2. Name string `json:"name"`
  3. }
  4. func (p *Test) Bind(r *http.Request) error {
  5. // 此时,`chi`已经完成了解码
  6. p.Name = p.Name + " after decode"
  7. return nil
  8. }

如果您只需要进行JSON解码,而不需要对解码后的值进行其他操作,请使用以下方法之一:

  1. // 使用标准包的JSON解码器
  2. err := json.NewDecoder(r.Body).Decode(&p)

或者

  1. // 使用chi的DecodeJSON包装方法
  2. err := render.DecodeJSON(r.Body, &p)
英文:

render.Bind's purpose is to perform decode and execute Bind(r) to do post decode operations.

For eg.:

  1. type Test struct {
  2. Name string `json:"name"`
  3. }
  4. func (p *Test) Bind(r *http.Request) error {
  5. // At this point, Decode is already done by `chi`
  6. p.Name = p.Name + " after decode"
  7. return nil
  8. }

If you have to do only JSON decode no other actions needs to be done after decode with respect to decoded values. Just use:

  1. // Use Directly JSON decoder of std pkg
  2. err := json.NewDecoder(r.Body).Decode(&p)

OR

  1. // Use wrapper method from chi DecodeJSON
  2. err := render.DecodeJSON(r.Body, &p)

huangapple
  • 本文由 发表于 2017年6月21日 05:40:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/44663496.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定