3 votes

Comment faire une fonction de forme générique pour les froms avec des interfeces avec gin (framework) et golang ?

Je veux créer une fonction pour traiter n'importe quel type de formulaire. Je veux qu'elle soit capable de traiter tous les types de données. J'essaie d'utiliser une interface pour réaliser cette tâche.

type Person struct {
    name        string 
    lastName    string
}

func HTMLForm(c *gin.Context) {
    var f Person
    c.ShouldBind(&f)
    c.JSON(http.StatusOK, f)
}

// with this function i get the correct info

// output: {"name":"john","lastName":"snow"}

func HTMLForm(c *gin.Context) {
    var f interface{}
    c.ShouldBind(&f)
    c.JSON(http.StatusOK, f)
}

// when i use the interface to make it usefull for any type of that
// i get null

// output: null

func HTMLForm(c *gin.Context) {
    var f interface{}
    ShouldBindJSON(f)
    c.JSON(http.StatusOK, f)
}

// output: null

Je veux obtenir, avec l'interface, le même résultat que celui que j'obtiens avec le type de données "Personne".

// Another example of how i am using f

type Login struct {
    User     string 
    Password string 
}

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

    router.POST("/loginForm", func(c *gin.Context) {
        var f interface{}

        if err := c.ShouldBind(&f); err != nil {
            c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
            return
        }

        c.JSON(http.StatusOK, f)
    })

    // Listen and serve on 0.0.0.0:8080
    router.Run(":8080")
}

// output: null

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Mise à jour

Je veux essayer de mieux expliquer mon problème. Peut-être que cette mise à jour sera plus claire.

// Golang code
package main

import (
    "net/http"

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

// Binding from JSON
type Login struct {
    User     string `form:"user" json:"user" xml:"user"  binding:"required"`
    Password string `form:"password" json:"password" xml:"password" binding:"required"`
}

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

    router.LoadHTMLGlob("templates/*")

    router.GET("/login", GetLogin)
    router.POST("/loginJSON", PostJSONForm)
    router.POST("/loginXML", PostXMLForm)
    router.POST("/loginForm", PostHTMLForm)

    /*
        sudo lsof -n -i :8080
        kill -9 <PID>
    */
    router.Run(":8080")
}

func GetLogin(c *gin.Context) {
    c.HTML(http.StatusOK, "login.tmpl", nil)
}

// Example for binding JSON ({"user": "manu", "password": "123"})
// curl -v -X POST http://localhost:8080/loginJSON -H 'content-type: application/json' '{ "user": "manu", "password"="123" }'
func PostJSONForm(c *gin.Context) {
    //var json Login
    var json interface{}
    //var form map[string]interface{}

    if err := c.ShouldBindJSON(&json); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }

    /*
        if json.User != "manu" || json.Password != "123" {
            c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
            return
        }
        c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
    */

    c.JSON(http.StatusOK, "json")
    c.JSON(http.StatusOK, json)
}

// Example for binding XML (
//  <?xml version="1.0" encoding="UTF-8"?>
//  <root>
//      <user>user</user>
//      <password>123</password>
//  </root>)
// curl -v -X POST http://localhost:8080/loginXML -H 'content-type: application/json' -d '{ "user": "manu", "password"="123" }'
func PostXMLForm(c *gin.Context) {
    //var xml Login
    var xml interface{}
    //var form map[string]interface{}

    if err := c.ShouldBindXML(&xml); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }

    /*
        if xml.User != "manu" || xml.Password != "123" {
            c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
            return
        }
        c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
    */

    c.JSON(http.StatusOK, "xml")
    c.JSON(http.StatusOK, xml)
}

// Example for binding a HTML form (user=manu&password=123)
// curl -v -X POST http://localhost:8080/loginForm -H 'content-type: application/json' -d '{ "user": "manu", "password":"123" }'
func PostHTMLForm(c *gin.Context) {
    //var form Login
    var form interface{}
    //var form map[string]interface{}

    // This will infer what binder to use depending on the content-type header.
    if err := c.ShouldBind(&form); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }

    /*
        if form.User != "manu" || form.Password != "123" {
            c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
            return
        }
        c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
    */

    c.JSON(http.StatusOK, "html")
    c.JSON(http.StatusOK, form)
}

//Template
<h1>Login</h1>
<form action="/loginForm" method="POST">
    <label>user:</label><br>
    <input type="text" name="user"><br>

    <label>password:</label><br>
    <input type="text" name="password"><br>

    <input type="submit">
</form>
  1. J'ai essayé toutes ces différentes variations. Une seule fonctionne, je vous explique plus bas.

  2. Cela fonctionne parfaitement si j'utilise "var form Login" au lieu de "var from interface{}". Mais j'ai besoin qu'il puisse fonctionner avec n'importe quel type de données, donc j'ai besoin qu'il fonctionne avec interface{}.

  3. J'ai eu une sortie "réussie", juste avec un des essais de l'interface{} :

$ curl -X POST http://localhost:8080/loginForm -H 'content-type : application/json' -d '{ "user" : "manu", "password" : "123" }''

output:"html"{"password":"123","user":"manu"}

  1. Mais lorsque je l'utilise dans un formulaire HTML, sur un navigateur, avec le modèle que j'ai posté, j'obtiens ce qui suit :

sortie : "html "null

  1. Je ne suis pas sûr que ce que j'obtiens (point 3) soit vraiment une sortie réussie. Quand j'utilise la var Login, ça marche bien, avec curl et brower, la sortie est inversée :

$ curl -X POST http://localhost:8080/loginForm -H 'content-type : application/json' -d '{ "user" : "manu", "password" : "123" }''

ouput:"html"{"user":"manu","password":"123"}

C'est la seule information que j'ai pu obtenir jusqu'à présent.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X