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

net/http: assume POST has Content-Type: application/x-www-form-urlencoded if missing (IE) #5412

Closed
gopherbot opened this issue May 6, 2013 · 6 comments

Comments

@gopherbot
Copy link

by lawrence@a4support.com:

This is the same Issue as on
https://code.google.com/p/googleappengine/issues/detail?id=9270
(i'm not sure where should I report this, thus placing to both)

This is very annoying bug and I'm not sure it's originates from IE or GAE, but I hope
GAE have some ways to work around in case it's IE's nonsense.

first of all, my partial code:

func subscribeHandle(httpResponse http.ResponseWriter, httpRequest *http.Request) {
    inputJson := httpRequest.FormValue("json")
    // debug the input
    appContext.Debugf("inputJson: %s", inputJson)
    appContext.Debugf("Body: %s", httpRequest.Body)
}

The request body as sent from browsers:
json=%7B%22email%22%3A%22user%40example.com%22%2C%22newsletter%22%3A%22imapbuilder%22%7D

The GAE log trace for Chrome:
2013-05-06 10:03:00.494
inputJson:
{"email":"user@example.com","newsletter":"imapbuilder"}
D 2013-05-06 10:03:00.494
Body: &{%!s(*bytes.Reader=&{[106 115 111 110 61 37 55 66 37 50 50 101 109 97 105
108 37 50 50 37 51 65 37 50 50 117 115 101 114 37 52 48 101 120 97 109 112 108 101 46 99
111 109 37 50 50 37 50 67 37 50 50 110 101 119 115 108 101 116 116 101 114 37 50 50 37
51 65 37 50 50 105 109 97 112 98 117 105 108 100 101 114 37 50 50 37 55 68] 88 -1})
%!s(bool=false)}

The GAE log trace for IE:
2013-05-06 10:02:37.121
inputJson: 
D 2013-05-06 10:02:37.121
Body: &{%!s(*bytes.Reader=&{[106 115 111 110 61 37 55 66 37 50 50 101 109 97 105
108 37 50 50 37 51 65 37 50 50 117 115 101 114 37 52 48 101 120 97 109 112 108 101 46 99
111 109 37 50 50 37 50 67 37 50 50 110 101 119 115 108 101 116 116 101 114 37 50 50 37
51 65 37 50 50 105 109 97 112 98 117 105 108 100 101 114 37 50 50 37 55 68] 0 -1})
%!s(bool=false)}

So...the httpRequest.FormValue is completely empty for IE's request, while from the
httpRequest.Body the bytes are almost all there except there's a small difference the
second last value (88 vs 0).. I think it's the content length.

Any idea how we can solve this? Otherwise IE's AJAX POST will never work with GAE as GAE
can't read any of the data.
@gopherbot
Copy link
Author

Comment 1 by lawrence@a4support.com:

I've done a work around without understanding what's actually happening, but that fixes
the problem of IE:
inputJson := httpRequest.FormValue("json")
if inputJson == "" {
    // probably request from IE as inputJson is empty
    body, _ := ioutil.ReadAll(httpRequest.Body)
    postField, _ := url.ParseQuery(fmt.Sprintf("%s", body)) // works for IE only
    inputJson = postField["json"][0]
}

@bradfitz
Copy link
Contributor

Comment 2:

Can you download Wireshark and record your network traffic while sending the AJAX POST? 
I want to see what headers you're actually sending to App Engine.
Please attach the pcap file here.

Labels changed: removed priority-triage.

Owner changed to @bradfitz.

Status changed to WaitingForReply.

@gopherbot
Copy link
Author

Comment 3 by lawrence@a4support.com:

I did it using some other tool and here are the http headers from IE:
POST /_api/subscribe HTTP/1.1
Accept: */*
Origin: http://www.example.com
Accept-Language: en-US
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0; MALC)
Host: myapp.appspot.com
Content-Length: 92
DNT: 1
Connection: Keep-Alive
Cache-Control: no-cache
Compared with Chrome:
Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Content-Length:92
Content-type:application/x-www-form-urlencoded
Host:myapp.appspot.com
Origin:http://www.example.com
Referer:http://www.example.com/download-draft1-rc1.php
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.31 (KHTML, like Gecko)
Chrome/26.0.1410.64 Safari/537.31
I think the main difference is IE is unable to send the
Content-type:application/x-www-form-urlencoded header. This problem is specific to the
use of window.XDomainRequest object... which I have to use it anyway as my AJAX works
cross domain.
By now I have already modified the way my app works, I'm no longer using name/value
pairs, instead I just send raw json in the POST BODY and on the server I read the POST
request body directly and decode the JSON object.

@rsc
Copy link
Contributor

rsc commented Jul 30, 2013

Comment 4:

This seems awful. Is it for an old IE that we can ignore?

Labels changed: added go1.2maybe.

Status changed to Thinking.

@bradfitz
Copy link
Contributor

Comment 5:

For now, let's just say that servers wanting to deal with IE can add to their handler
before parsing the body:
  if req.Header.Get("Content-Type") == "" {
      req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  }

Status changed to Unfortunate.

@gopherbot
Copy link
Author

Comment 6 by lawrence@a4support.com:

That's all right, my solution now is just POST the JSON directly as string and skip
using the x-www-form-urlencoded header for all request.
Simply read from httpRequest.Body is enough

@rsc rsc added this to the Go1.2 milestone Apr 14, 2015
@rsc rsc removed the go1.2maybe label Apr 14, 2015
@golang golang locked and limited conversation to collaborators Jun 24, 2016
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants