Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

README.md error errA := c.ShouldBindBodyWith(&objA, binding.Form) #3296

Open
ItisDL opened this issue Aug 25, 2022 · 2 comments
Open

README.md error errA := c.ShouldBindBodyWith(&objA, binding.Form) #3296

ItisDL opened this issue Aug 25, 2022 · 2 comments

Comments

@ItisDL
Copy link

ItisDL commented Aug 25, 2022

  • With issues:
    type formA struct {
    Foo string json:"foo" xml:"foo" binding:"required"
    }
    objA := formA{}
    c.ShouldBindBodyWith(&objA, binding.Form)
    cant use binding.Form
    should use binding.JSON maybe

Description

How to reproduce

package main

import (
	"context"
	"errors"
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
)

func Logger() gin.HandlerFunc {
	return func(c *gin.Context) {
		t := time.Now()

		c.Set("example", "12345")

		// before request
		c.Next()
		// after request
		latency := time.Since(t)
		log.Println(latency)
	}
}

func main() {
	r := gin.Default()

	// 中间件测试
	r.Use(Logger())

	r.StaticFS("/assets", http.Dir("assets"))
	r.GET("/local/file", func(c *gin.Context) {
		c.File("main.go")
	})
	r.POST("/test", func(c *gin.Context) {
		example := c.MustGet("example").(string)
		log.Println(example)

		type formA struct {
			Foo string `json:"foo" xml:"foo" binding:"required"`
		}

		type formB struct {
			Bar string `json:"bar" xml:"bar" binding:"required"`
		}
		objA := formA{}
		objB := formB{}
		// This reads c.Request.Body and stores the result into the context.
		if errA := c.ShouldBindBodyWith(&objA, binding.Form); errA == nil {
			c.String(http.StatusOK, `the body should be formA`)
		  // At this time, it reuses body stored in the context.
		  } else if errB := c.ShouldBindBodyWith(&objB, binding.JSON); errB == nil {
			c.String(http.StatusOK, `the body should be formB JSON`)
		  // And it can accepts other formats
		  } else if errB2 := c.ShouldBindBodyWith(&objB, binding.XML); errB2 == nil {
			c.String(http.StatusOK, `the body should be formB XML`)
		  }

		// c.Redirect(http.StatusFound, "/someDataFromReader")
	})
	r.GET("/long_async", func(c *gin.Context) {
		cCp := c.Copy()
		go func() {
			time.Sleep(5 * time.Second)
			log.Println("Done! in path " + cCp.Request.URL.Path)
		}()
	})
	r.GET("/someDataFromReader", func(c *gin.Context) {
		response, err := http.Get("https://raw.githubusercontent.com/gin-gonic/logo/master/color.png")
		if err != nil || response.StatusCode != http.StatusOK {
			c.Status(http.StatusServiceUnavailable)
			return
		}

		reader := response.Body
		defer reader.Close()
		contentLength := response.ContentLength
		contentType := response.Header.Get("Content-Type")

		extraHeaders := map[string]string{
			"Content-Disposition": `attachment; filename="gopher.png"`,
		}

		c.DataFromReader(http.StatusOK, contentLength, contentType, reader, extraHeaders)
	})
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"message": "pong",
		})
	})
	// gin.H is a shortcut for map[string]interface{}
	r.GET("/someJSON", func(c *gin.Context) {
		names := []string{"lena", "austin", "foo"}

		// Will output  :   while(1);["lena","austin","foo"]
		c.SecureJSON(http.StatusOK, names)
	})

	r.GET("/moreJSON", func(c *gin.Context) {
		// You also can use a struct
		var msg struct {
			Name    string `json:"user"`
			Message string
			Number  int
		}
		msg.Name = "Lena"
		msg.Message = "hey"
		msg.Number = 123
		// Note that msg.Name becomes "user" in the JSON
		// Will output  :   {"user": "Lena", "Message": "hey", "Number": 123}
		c.JSON(http.StatusOK, msg)
	})

	r.GET("/someXML", func(c *gin.Context) {
		c.XML(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK})
	})

	r.GET("/someYAML", func(c *gin.Context) {
		c.YAML(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK})
	})

	// 优雅启动或者关闭
	srv := &http.Server{
		Addr:           ":8080",
		Handler:        r,
		ReadTimeout:    10 * time.Second,
		WriteTimeout:   10 * time.Second,
		MaxHeaderBytes: 1 << 20, // 2 的 20次方
	}

	// 协程启动服务
	go func() {
		if err := srv.ListenAndServe(); err != nil && errors.Is(err, http.ErrServerClosed) {
			log.Printf("listen:%s\n", err)
		}
	}()

	quit := make(chan os.Signal)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit
	log.Println("Shutting down server...")

	// 延迟关闭
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	if err := srv.Shutdown(ctx); err != nil {
		log.Fatal("Server forced to shutdown:", err)
	}
	log.Println("Server exiting")
}

Expectations

cannot use binding.Form (variable of type binding.formBinding) as binding.BindingBody value in argument to c.ShouldBindBodyWith: binding.formBinding does not implement binding.BindingBody (missing method BindBody)

Actual result

```

Environment

  • go version:1.19
  • gin version (or commit ref):1.8.1
  • operating system:windows
@Gasoid
Copy link

Gasoid commented Sep 5, 2022

looks like it is a kind of typo in README.
obviously binding.Form doesn't have BindBody method and it doesn't implement BindingBody interface.

c.ShouldBindBodyWith(&objA, binding.Form)

@Gasoid
Copy link

Gasoid commented Sep 5, 2022

My PR: #3312
however I think it is possible to update README and delete this feature for binding.Form

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants