Golang的json.decoder无法解码仅来自浏览器的请求。

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

Golang json.decoder fails to decode requests coming from the browser ONLY

问题

我的golang应用程序在浏览器中无法解码表单,但在使用curl和httpie时成功。

给定以下代码:

type Member struct {
    Username string `json:"username"`
    Email    string `json:"email"`
    Password string `json:"password"`
}

func Register(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
    var t Member
    json.NewDecoder(r.Body).Decode(&t)
    log.Println(t.Username)
    log.Println(t.Email)
    log.Println(t.Password)
    w.WriteHeader(204)
}

使用curl命令可以成功打印输出:

curl -H "Content-Type: application/json" -X POST -d '{"username":"cesco","email":"cesco@gmail.com","password":"password"}' http://localhost:5000/register

使用httpie命令也可以成功打印输出:

http -v -j --form POST localhost:5000/register username="cesco" email="cesco@gmail.com" password="sadsa"

但是以下方式无法成功打印输出:

<form id="register" action="register" method="post">
    <input type="text" name="username"><br>
    <input type="email" name="email"><br>
    <input type="password" name="password"><br>
    <input type="submit" value="Submit">
</form>

或者以下方式也无法成功打印输出:

var data = $('#register').serialize();
$.ajax({
    url: 'register',
    data: data,
    beforeSend: function (xhr) {
        xhr.setRequestHeader("Content-type", "*/*");
    },
    dataType: 'json',
    type: 'POST',
    async: false,
    success: function (data) {
        // callback method for further manipulations
    },
    error: function (data) {
        // if error occurred
    }
});

日志输出的顺序与问题中的顺序相同:

2016/02/09 13:56:12 cesco
2016/02/09 13:56:12 cesco@gmail.com
2016/02/09 13:56:12 password
2016/02/09 13:56:12 key: Accept value: [*/*]
2016/02/09 13:56:12 key: Content-Type value: [application/json]
2016/02/09 13:56:12 key: Content-Length value: [68]
2016/02/09 13:56:12 key: User-Agent value: [Mozilla/5.0 Gecko]
[13:56:12] 127.0.0.1 - - [09/Feb/2016:13:56:12 -0200] "POST /register HTTP/1.1" 204 0
2016/02/09 13:56:18 cesco
2016/02/09 13:56:18 cesco@gmail.com
2016/02/09 13:56:18 sadsa
2016/02/09 13:56:18 key: Accept-Encoding value: [gzip, deflate]
2016/02/09 13:56:18 key: Accept value: [application/json]
2016/02/09 13:56:18 key: User-Agent value: [HTTPie/0.8.0]
2016/02/09 13:56:18 key: Connection value: [keep-alive]
2016/02/09 13:56:18 key: Content-Type value: [application/json; charset=utf-8]
2016/02/09 13:56:18 key: Content-Length value: [70]
[13:56:18] 127.0.0.1 - - [09/Feb/2016:13:56:18 -0200] "POST /register HTTP/1.1" 204 0
[13:56:30] 127.0.0.1 - - [09/Feb/2016:13:56:30 -0200] "GET / HTTP/1.1" 200 747
2016/02/09 13:56:40
2016/02/09 13:56:40
2016/02/09 13:56:40
2016/02/09 13:56:40 key: User-Agent value: [Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.103 Safari/537.36]
2016/02/09 13:56:40 key: Content-Type value: [application/x-www-form-urlencoded]
2016/02/09 13:56:40 key: Referer value: [http://localhost:5000/]
2016/02/09 13:56:40 key: Accept-Language value: [en-US,en;q=0.8,pt;q=0.6,es;q=0.4]
2016/02/09 13:56:40 key: Connection value: [keep-alive]
2016/02/09 13:56:40 key: Content-Length value: [53]
2016/02/09 13:56:40 key: Cache-Control value: [max-age=0]
2016/02/09 13:56:40 key: Accept value: [text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8]
2016/02/09 13:56:40 key: Origin value: [http://localhost:5000]
2016/02/09 13:56:40 key: Upgrade-Insecure-Requests value: [1]
2016/02/09 13:56:40 key: Accept-Encoding value: [gzip, deflate]
[13:56:40] 127.0.0.1 - - [09/Feb/2016:13:56:40 -0200] "POST /register HTTP/1.1" 204 0
2016/02/09 13:56:59
2016/02/09 13:56:59
2016/02/09 13:56:59
2016/02/09 13:56:59 key: Content-Type value: [*/*]
2016/02/09 13:56:59 key: Referer value: [http://localhost:5000/]
2016/02/09 13:56:59 key: Connection value: [keep-alive]
2016/02/09 13:56:59 key: Content-Length value: [53]
2016/02/09 13:56:59 key: X-Requested-With value: [XMLHttpRequest]
2016/02/09 13:56:59 key: User-Agent value: [Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.103 Safari/537.36]
2016/02/09 13:56:59 key: Accept value: [application/json, text/javascript, */*; q=0.01]
2016/02/09 13:56:59 key: Origin value: [http://localhost:5000]
2016/02/09 13:56:59 key: Accept-Encoding value: [gzip, deflate]
2016/02/09 13:56:59 key: Accept-Language value: [en-US,en;q=0.8,pt;q=0.6,es;q=0.4]
[13:56:59] 127.0.0.1 - - [09/Feb/2016:13:56:59 -0200] "POST /register HTTP/1.1" 204 0
英文:

My golang app fails to decode forms coming from the browsers but succeed when using curl and httpie.

#Given this code:

    type Member struct {
Username string `json:&quot;username&quot;`
Email string `json:&quot;email&quot;`
Password string `json:&quot;password&quot;`
}
func Register(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
var t Member
json.NewDecoder(r.Body).Decode(&amp;t)
log.Println(t.Username)
log.Println(t.Email)
log.Println(t.Password)
w.WriteHeader(204)
}

#this prints!
curl -H "Content-Type: application/json" -X POST -d '{"username":"cesco","email":"cesco@gmail.com","password":"password"}' http://localhost:5000/register

#also this!

http -v -j  --form POST localhost:5000/register username=&quot;cesco&quot; email=&quot;cesco@gmail.com&quot; password=&quot;sadsa&quot;

#this does not

&lt;form id=&quot;register&quot; action=&quot;register&quot;  method=&quot;post&quot;&gt;
&lt;input type=&quot;text&quot; name=&quot;username&quot;&gt;&lt;br&gt;
&lt;input type=&quot;email&quot; name=&quot;email&quot;&gt;&lt;br&gt;
&lt;input type=&quot;password&quot; name=&quot;password&quot;&gt;&lt;br&gt;
&lt;input type=&quot;submit&quot; value=&quot;Submit&quot;&gt;
&lt;/form&gt;

#neither this

var data = $(&#39;#register&#39;).serialize();
$.ajax({
url: &#39;register&#39;, // php script to retern json encoded string
data: data,  // serialized data to send on server
beforeSend: function (xhr) {
xhr.setRequestHeader(&quot;Content-type&quot;, &quot;*/*&quot;);
},
dataType: &#39;json&#39;, // set recieving type - JSON in case of a question
type: &#39;POST&#39;, // set sending HTTP Request type
async: false,
success: function (data) { // callback method for further manipulations
},
error: function (data) { // if error occured
}
});

#Logs on the same order as the question

2016/02/09 13:56:12 cesco
2016/02/09 13:56:12 cesco@gmail.com
2016/02/09 13:56:12 password
2016/02/09 13:56:12 key: Accept value: [*/*]
2016/02/09 13:56:12 key: Content-Type value: [application/json]
2016/02/09 13:56:12 key: Content-Length value: [68]
2016/02/09 13:56:12 key: User-Agent value: [Mozilla/5.0 Gecko]
[13:56:12] 127.0.0.1 - - [09/Feb/2016:13:56:12 -0200] &quot;POST /register HTTP/1.1&quot; 204 0
2016/02/09 13:56:18 cesco
2016/02/09 13:56:18 cesco@gmail.com
2016/02/09 13:56:18 sadsa
2016/02/09 13:56:18 key: Accept-Encoding value: [gzip, deflate]
2016/02/09 13:56:18 key: Accept value: [application/json]
2016/02/09 13:56:18 key: User-Agent value: [HTTPie/0.8.0]
2016/02/09 13:56:18 key: Connection value: [keep-alive]
2016/02/09 13:56:18 key: Content-Type value: [application/json; charset=utf-8]
2016/02/09 13:56:18 key: Content-Length value: [70]
[13:56:18] 127.0.0.1 - - [09/Feb/2016:13:56:18 -0200] &quot;POST /register HTTP/1.1&quot; 204 0
[13:56:30] 127.0.0.1 - - [09/Feb/2016:13:56:30 -0200] &quot;GET / HTTP/1.1&quot; 200 747
2016/02/09 13:56:40 
2016/02/09 13:56:40 
2016/02/09 13:56:40 
2016/02/09 13:56:40 key: User-Agent value: [Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.103 Safari/537.36]
2016/02/09 13:56:40 key: Content-Type value: [application/x-www-form-urlencoded]
2016/02/09 13:56:40 key: Referer value: [http://localhost:5000/]
2016/02/09 13:56:40 key: Accept-Language value: [en-US,en;q=0.8,pt;q=0.6,es;q=0.4]
2016/02/09 13:56:40 key: Connection value: [keep-alive]
2016/02/09 13:56:40 key: Content-Length value: [53]
2016/02/09 13:56:40 key: Cache-Control value: [max-age=0]
2016/02/09 13:56:40 key: Accept value: [text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8]
2016/02/09 13:56:40 key: Origin value: [http://localhost:5000]
2016/02/09 13:56:40 key: Upgrade-Insecure-Requests value: [1]
2016/02/09 13:56:40 key: Accept-Encoding value: [gzip, deflate]
[13:56:40] 127.0.0.1 - - [09/Feb/2016:13:56:40 -0200] &quot;POST /register HTTP/1.1&quot; 204 0
2016/02/09 13:56:59 
2016/02/09 13:56:59 
2016/02/09 13:56:59 
2016/02/09 13:56:59 key: Content-Type value: [*/*]
2016/02/09 13:56:59 key: Referer value: [http://localhost:5000/]
2016/02/09 13:56:59 key: Connection value: [keep-alive]
2016/02/09 13:56:59 key: Content-Length value: [53]
2016/02/09 13:56:59 key: X-Requested-With value: [XMLHttpRequest]
2016/02/09 13:56:59 key: User-Agent value: [Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.103 Safari/537.36]
2016/02/09 13:56:59 key: Accept value: [application/json, text/javascript, */*; q=0.01]
2016/02/09 13:56:59 key: Origin value: [http://localhost:5000]
2016/02/09 13:56:59 key: Accept-Encoding value: [gzip, deflate]
2016/02/09 13:56:59 key: Accept-Language value: [en-US,en;q=0.8,pt;q=0.6,es;q=0.4]
[13:56:59] 127.0.0.1 - - [09/Feb/2016:13:56:59 -0200] &quot;POST /register HTTP/1.1&quot; 204 0

答案1

得分: 2

你的curl示例是使用Content-Type: application/json将json编码的请求体进行提交。浏览器不会将HTML表单自动编码为json。从日志中可以看到,你收到的是Content-Type: application/x-www-form-urlencoded

如果你想从表单中获取值,请使用Request.FormValueRequest.PostFormValue

英文:

Your curl example is posting a json encoded body with Content-Type: application/json. A browser isn't going to somehow encode an html form into json. As you can see in the logs, you're receiving Content-Type: application/x-www-form-urlencoded

If you want to get the values from a form, use Request.FormValue, or Request.PostFormValue

huangapple
  • 本文由 发表于 2016年2月10日 00:01:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/35296534.html
匿名

发表评论

匿名网友

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

确定