Search code examples
androidjsonhttp-post3gantiforgerytoken

Android: HttpPost content type header and body different between wifi and 3g


Been trying to figure out what's wrong with this one for a while. I'm making a post request with HttpClient.execute with a json body to my server api. Works fine under normal wifi and most 3g, but specifically on phones with AT&T dataplans and it's on 3g, I'm getting back a HttpResponseException when I try to execute the request, status code 422. Did some research on 422 and it says it's due to:

"422 Unprocessable Entity (WebDAV) (RFC 4918 ), The request was well-formed but was unable to be followed due to semantic errors."

So I'm guessing something is going wrong in how the request goes out, but I'm doing the same thing in forming the request, whether I'm on wifi or 3g. Any ideas on what might be causing this error?

Edit: Looked like my server was catching the post with the forgery protection. Turned it off and the error stopped, but the api didn't go through. Dug a little deeper and printed out what was actually getting received by the server, did a comparison between wifi on and off, noticed two differences. First, the body was empty on 3g, seems like it somehow got blocked from being sent. Second, the header changed the content type being sent:

wifi: "HTTP_CONTENT_TYPE"=>"application/json" att 3g: "HTTP_CONTENT_TYPE"=>"text/plain; charset=ISO-8859-1,application/json"

I'm expecting "application/json" given that I'm setting up my connection like this:

StringEntity se = new StringEntity(json.toString());
se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));

Any ideas why things are changing when I move over to 3g?

Update: Ran a tcpdump and looks like what I'm sending from the android is exactly the same between wifi and 3g, so it seems that it's the provider that's making a change to my data. Any other proposed strategies other than HTTPS?


Solution

  • Solved!

    Old Code:

        mPost = new HttpPost(ur);
        StringEntity se = new StringEntity(json.toString());
        se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
        mPost.setEntity(se);
    

    New Code:

        mPost = new HttpPost(ur);
        ByteArrayEntity baEntity = new ByteArrayEntity(json.toString().getBytes("UTF8"));
        baEntity.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
        mPost.setEntity(baEntity);
    

    Pretty much looks like using ByteArrayEntity instead of StringEntity as my post's body makes it work on 3g. Not sure exactly why this is given the tcpdump between wifi and 3g looked exactly the same while using StringEntity, but it seems to have fixed the problem so I'm not complaining.