2

一段时间以来一直试图弄清楚这个有什么问题。我正在使用 HttpClient.execute 向我的服务器 api 发出带有 json 正文的发布请求。在普通 wifi 和大多数 3g 下工作正常,但特别是在具有 AT&T 数据计划并且它在 3g 上的手机上,当我尝试执行请求时,我收到了一个 HttpResponseException,状态码为 422。对 422 做了一些研究,它说它是由于到:

“422 Unprocessable Entity (WebDAV) (RFC 4918),请求格式正确,但由于语义错误而无法遵循。”

所以我猜测请求的发出方式出了点问题,但我在形成请求时做同样的事情,无论我是在 wifi 还是 3g 上。关于可能导致此错误的任何想法?

编辑:看起来我的服务器正在使用伪造保护来捕捉帖子。关闭它,错误停止,但api没有通过。挖得更深一点,打印出服务器实际接收到的内容,比较了 wifi 的开启和关闭,发现了两个不同之处。首先,3g 上的 body 是空的,好像它被阻止发送。其次,标头更改了正在发送的内容类型:

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

鉴于我正在像这样设置连接,我期待“应用程序/json”:

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

任何想法为什么当我转移到 3g 时情况会发生变化?

更新:运行 tcpdump,看起来我从 android 发送的内容在 wifi 和 3g 之间完全相同,所以似乎是提供者正在更改我的数据。除了 HTTPS 之外,还有其他建议的策略吗?

4

1 回答 1

7

解决了!

旧代码:

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

新代码:

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

看起来很像使用 ByteArrayEntity 而不是 StringEntity,因为我的帖子的正文使其适用于 3g。不确定为什么在使用 StringEntity 时 wifi 和 3g 之间的 tcpdump 看起来完全一样,但它似乎已经解决了这个问题,所以我没有抱怨。

于 2012-07-13T19:30:43.830 回答