如何从杜松子酒的前端获取数据?
How get DATA from frontend in 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....
在从 request.Form
使用它之前,您需要先调用 c.Request.ParseForm()
说 here:
For all requests, ParseForm parses the raw query from the URL and updates r.Form
For other HTTP methods, or when the Content-Type is not application/x-www-form-urlencoded, the request Body is not read, and r.PostForm is initialized to a non-nil, empty value.
好吧,我想说你应该获取一些 book/HOWTO 有关 HTTP 工作原理的知识,并花一些时间研究它,因为看起来你试图 bash 解决手头的问题,但并未真正理解您的浏览器和后端服务之间发生了什么。
这里真正的问题是你似乎意识到了更多的活动部分,要走的路取决于你的前端做什么。
您没有确切地告诉我们您是如何执行您的请求的,
但是从征求的评论来看,您正在使用 "axios" 小东西。
如果我设法 google 正确地完成了该项目,
它的自述文件 states:
By default, axios serializes JavaScript objects to JSON. To send data in the application/x-www-form-urlencoded
format instead, you can use one of the following options.
这意味着两件事:
- 除非你以某种方式调整了 axios 的设置,否则
axios.post
,应该执行 HTTP POST 请求
其 Content-Type
字段设置为 application/json
它的有效载荷(或者 "body" 如果你愿意的话)是
该 {user:this.user}
JavaScript 对象的 JSON 序列化。
- 因此,尝试解析查询字符串是徒劳的。
尝试将请求解析为 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"`
}
None 我的示例在两个地方返回了一个
用户错误,它使用了纯文本的内容类型
(采用 UTF-8 编码)。这可能没问题,但也可能不是。
比方说,您的客户可能期望 JSON 格式的文档
一些商定的形状。
或者你可以使用 content negotiation,但我建议先把简单的事情弄清楚。
要检查的文献:
HTTP POST
请求 explained at MDN.
- URL's query string.
- XHR explained at MDN — 另请参阅那里的链接。
- "Writing Web Applications in Go",
和一般 this。
也许可以回答你关于
为什么它在 Django 中 "just worked"。
我只能猜测,但我认为它只是实现了大量的魔法,它会查看传入的请求并尝试猜测如何从中提取数据。
问题是猜测可能确实适用于
一次性脚本,但是当你要实现类似 web API 的东西时(很多人不太正确地称呼 "REST",但我们不要离题)最好
非常明确地说明您的端点接受什么
准确地以及他们如何准确地对请求做出反应——包括合法的和格式不正确的。
关于围棋的魔法,你可以看看this。
如果您希望请求中有一个 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
}
服务器 GIN 无法处理来自 axios 的例程默认 application/json 请求!!!什么???
请求应作为 application/x-www-form-urlencoded 发送。
我在 Vue 项目中的决定:
使用 vue-resource 而不是带有选项的 axios (axios.post=>this.$http.post)
Vue.http.options.emulateJSON = 真;在 main.js
遗憾的是,我一直无法弄清楚如何在 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....
在从 request.Form
c.Request.ParseForm()
说 here:
For all requests, ParseForm parses the raw query from the URL and updates r.Form
For other HTTP methods, or when the Content-Type is not application/x-www-form-urlencoded, the request Body is not read, and r.PostForm is initialized to a non-nil, empty value.
好吧,我想说你应该获取一些 book/HOWTO 有关 HTTP 工作原理的知识,并花一些时间研究它,因为看起来你试图 bash 解决手头的问题,但并未真正理解您的浏览器和后端服务之间发生了什么。
这里真正的问题是你似乎意识到了更多的活动部分,要走的路取决于你的前端做什么。
您没有确切地告诉我们您是如何执行您的请求的, 但是从征求的评论来看,您正在使用 "axios" 小东西。 如果我设法 google 正确地完成了该项目, 它的自述文件 states:
By default, axios serializes JavaScript objects to JSON. To send data in the
application/x-www-form-urlencoded
format instead, you can use one of the following options.
这意味着两件事:
- 除非你以某种方式调整了 axios 的设置,否则
axios.post
,应该执行 HTTP POST 请求 其Content-Type
字段设置为application/json
它的有效载荷(或者 "body" 如果你愿意的话)是 该{user:this.user}
JavaScript 对象的 JSON 序列化。 - 因此,尝试解析查询字符串是徒劳的。 尝试将请求解析为 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"`
}
None 我的示例在两个地方返回了一个 用户错误,它使用了纯文本的内容类型 (采用 UTF-8 编码)。这可能没问题,但也可能不是。 比方说,您的客户可能期望 JSON 格式的文档 一些商定的形状。
或者你可以使用 content negotiation,但我建议先把简单的事情弄清楚。
要检查的文献:
HTTP POST
请求 explained at MDN.- URL's query string.
- XHR explained at MDN — 另请参阅那里的链接。
- "Writing Web Applications in Go", 和一般 this。
也许可以回答你关于 为什么它在 Django 中 "just worked"。 我只能猜测,但我认为它只是实现了大量的魔法,它会查看传入的请求并尝试猜测如何从中提取数据。
问题是猜测可能确实适用于 一次性脚本,但是当你要实现类似 web API 的东西时(很多人不太正确地称呼 "REST",但我们不要离题)最好 非常明确地说明您的端点接受什么 准确地以及他们如何准确地对请求做出反应——包括合法的和格式不正确的。
关于围棋的魔法,你可以看看this。
如果您希望请求中有一个 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
}
服务器 GIN 无法处理来自 axios 的例程默认 application/json 请求!!!什么??? 请求应作为 application/x-www-form-urlencoded 发送。 我在 Vue 项目中的决定: 使用 vue-resource 而不是带有选项的 axios (axios.post=>this.$http.post) Vue.http.options.emulateJSON = 真;在 main.js