如何从gin中的前端获取数据?

时间:2018-11-10 15:08:54

标签: go go-gin

让我感到遗憾的是,我一直无法弄清楚如何从Gin框架的前端获取数据。在Django中,我得到了数据,所以:

user=request.data.get('user')
print(user)

一切都是简单易懂的。 我应该怎么用杜松子酒做呢?

user := c.Query("user")
user := c.Param("user")
user := c.Params.ByName("user")
user := c.PostForm("user")
println(user)//emptiness....

4 个答案:

答案 0 :(得分:1)

好吧,我想你应该读一本关于HTTP如何工作的书/ HOWTO,并花一些时间,因为它似乎是在试图消除手头的问题,而没有真正理解浏览器和后端之间发生了什么。服务。

这里的真正问题是,您似乎要意识到还有更多的运动部件,而前进的方式取决于您的前沿技术。

您没有完全告诉我们您的请求方式, 但从显示的征求意见中,您正在使用那种“ axios”的小气。 如果我设法正确搜索了该项目, 其自述文件states

  

默认情况下,axios将JavaScript对象序列化为JSON。要改为以application/x-www-form-urlencoded格式发送数据,可以使用以下选项之一。

这意味着两件事:

  1. 除非您以某种方式调整了焦虑的设置, axios.port被认为执行了HTTP POST请求 其Content-Type字段设置为application/json 及其有效载荷(如果愿意,也可以是“ body”) {user:this.user} JavaScript对象的JSON序列化。
  2. 因此尝试解析查询字符串是徒劳的。 尝试将请求解析为HTTP格式是没有用的。

相反,您应该将传入请求的主体解释为JSON格式。我不知道如何在“ go-gin”中做到这一点,但是在简单的Go语言中,这就像

func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
  defer req.Body.Close()

  var user User

  dec := json.NewDecoder(req.Body)
  err := dec.Decode(&user)
  if err != nil {
    rw.Header().Set("Content-Type", "text/plain; charset=UTF-8")
    rw.WriteHeader(http.StatusBadRequest)
    fmt.Fprintln(rw, "Error parsing request body: ", err)
    return
  }
}

理想情况下,您首先要检查传入请求的内容类型确实为application/json,如果不是,则立即用http.StatusBadRequest拒绝它。

一个工作代码的例子是

// VerifyContentTypeIsJSON makes sure the HTTP header of a server
// http.Request contains the Content-Type field and it indicates
// the request payload is JSON.
// The implementation is based on RFC 7231 (section 3.1.1.5) and RFC 8259.
func VerifyContentTypeIsJSON(header http.Header) error {
    var s string

    if values := header["Content-Type"]; len(values) > 0 {
        s = values[0]
    } else {
        return errors.New("missing Content-Type")
    }

    if s == "" {
        return errors.New("empty Content-Type")
    }

    if i := strings.IndexByte(s, ';'); i != -1 {
        s = strings.TrimSpace(s[:i])
    }

    if strings.ToLower(s) != "application/json" {
        return fmt.Errorf("unknown Content-Type: %v, must be application/json", s)
    }

    return nil
}

具有此功能,您将拥有类似的内容 defer req.Body.Close()之后并进行实际解析:

if err := VerifyContentTypeIsJSON(req.Header); err != nil {
  rw.Header().Set("Content-Type", "text/plain; charset=utf-8")
  rw.WriteHeader(http.StatusBadRequest)
  fmt.Fprintln(rw, err)
  return
}

(请注意,“ go-gin”可能与已经内置的功能类似,因此请检查此内容。)

User类型应为某种struct类型,以匹配要从请求中解组的JSON对象的形状。像这样:

type User struct {
  User string `json:"user"`
}

在这两个地方,我的示例都没有返回一个 给用户的错误,它使用纯文本的内容类型 (采用UTF-8编码)。可能可以,但可能不行。 假设您的客户可能希望使用JSON格式的文档 同意的形状。

或者您可以使用content negotiation,但我建议您先弄简单一些的事情。


要检查的文献


也许可以回答您有关问题的那一部分 为什么它在Django中“有效”。 我只能猜测,但是我认为它只是实现了很多魔术,这些魔术看着传入的请求并尝试猜测如何从中提取数据。

问题在于猜测可能确实适用于 一次性的脚本,但是当您要实现类似Web API的东西时(很多都不太正确地称为“ REST”,但是请不要离题),最好 对端点接受的内容非常明确 精确以及它们对请求的响应方式-合法和格式错误。

关于Go中的魔术,您可以阅读this

答案 1 :(得分:0)

在使用c.Request.ParseForm()之前,您需要先致电request.Form

here

  

对于所有请求,ParseForm都会从URL解析原始查询并更新r.Form

     

对于其他HTTP方法,或者当Content-Type不是application / x-www-form-urlencoded时,不读取请求主体,并且r.PostForm初始化为非空值。

答案 2 :(得分:0)

如果您期望请求中包含JSON正文,则可以使用gin来做到这一点。为要从主体中抓取的数据创建一个结构。使用json标签作为JSON密钥名称,除非您要将Go字段名称与它们完全匹配。然后在gin上下文中调用BindJSON方法。

例如:

type User struct {
    FirstName string `json:"first_name"`
    LastName  string `json:"last_name"`
    Login     string `json:"login"`
}

func (h *Handler) HandleUser(gctx *gin.Context) {
    user := new(User)
    err := gctx.BindJSON(user)
    if err != nil {
        text := fmt.Sprintf("Failed to read user data from request: %s", err)
        log.Error(text)
        gctx.JSON(http.StatusBadRequest, gin.H{"error": text})
        return
    }
    // do something with user
}

答案 3 :(得分:0)

服务器GIN无法处理来自axios的常规默认应用程序/ json请求!!!什么??? 请求应以application / x-www-form-urlencoded发送。 我在Vue项目中的决定: 使用vue-resource代替axios(axios.post => this。$ http.post)和选项 Vue.http.options.emulateJSON = true;在main.js中