【发布时间】:2017-02-12 05:44:23
【问题描述】:
我正在尝试使用 Android 中的 HttpURLConnection 对象进行 HTTP GET。
更新
我尝试连接到不同的服务器。这也托管在 Cloud 9 (c9.io) 中,并且还返回一个 json 响应。这次我没有收到 301 重定向,但我收到了服务器应该发送的实际响应。
由于这意味着问题发生在服务器内部,因此我重新组织了以下部分,以便重点阅读与服务器相关的信息。 Android 相关信息已移至问题末尾。
我在哪里连接:
- Cloud9 上的开发服务器
- 使用 Laravel Framework 5.2(由于项目依赖项不受支持,我们目前无法升级到 5.3)
- 服务器应返回 JSON 答案
- 如果我通过浏览器连接到同一个 URL,我会得到正确的响应(JSON 字符串。必需的 HTTP 标头和“200”HTTP 响应代码)
我从哪里连接
- Android 手机(一加 3,Android 6.0)
- 编译SDK版本:23
- 使用构建工具:“23.0.3”
- 使用 Min SDK 版本:19
- 使用目标 SDK 版本:22
- 我正在使用 HttpURLConnection 对象进行连接,使用 HTTP 方法“GET”
Android 上的 HTTP 响应
当我运行我的代码时,我会从服务器获得以下结果:
HTTP 响应代码是 301,但消息是 null。
- 新的 URL 完全相同,但使用的是 HTTPS。似乎服务器以某种方式强制 SSL/TSL 加密。从浏览器访问 HTTP 时不会发生这种情况。
HTTP 标头(在 Android 上):
- 日期 => 2016 年 10 月 4 日星期二 05:56:26 GMT
- location => https://domain.com/route/(我修改了这个位)
- 内容长度 => 382
- 内容类型 => 文本/html; charset=iso-8859-1
- X-BACKEND => 应用代理
- X-Android-Selected-Protocol => http/1.1
- X-Android-Sent-Millis => 1475560583894
- X-Android-Received-Millis => 1475560585637
- X-Android-Response-Source => 网络 301
- null => HTTP/1.1 301
其他数据
- 由于服务器似乎希望 Android 使用 HTTPS,我尝试修改代码以使用 HTTPS (HttpsURLConnection)。这可能会也可能不会解决 this 问题,但我无法检查它,因为我收到了一个恼人的
SSL handshake failed错误。另外,我不需要对此应用程序进行加密,因此我不愿意解决随之而来的问题。 - 这一切都在 AsyncTask 对象中运行(因为当您尝试在主线程上使用网络连接时,Android 会变得喜怒无常)。
- 设置新服务器(在 Cloud 9 之外且没有任何 SSL/TSL)可能是一种选择,但我不愿意这样做,因为这会非常耗时。
- 我尝试使用完全相同的代码连接到另一个 Cloud 9 服务器(它也返回一个 json 响应),并且一切正常。这表明问题是由 HTPP 301 错误引起的。
我将尝试与您分享您回答我的问题可能需要的任何其他信息!
原生 Android 东西(在 UPDATE 上移动,见上文)
响应内容似乎是一个不完整 JSON:
{ 'status':'ERROR'
注意我没有忘记结束 } 字符,这就是响应实际包含的内容。这是在工作流程中(对我而言)未知的地方注入的。当我捕获 HTTP 响应(在我的 PC 上使用 Charles,它被设置为我手机 Wi-Fi 连接的代理)时,它的内容(如预期的那样)是一个简单的 HTML,告诉您重定向(HTPP 代码 301)到新路由.
不存在无效的 JSON 代码(上图),但存在 有效的 HTML。
这表明无效的 JSON 出现在我的代码内部某处(而不是在服务器或传输中)。但是我的应用程序上没有生成 JSON 字符串的代码,更不用说将其注入我正在处理的响应中了。
HttpURLConnection 的代码
this.setURL(ruta); //gets correct url
HttpURLConnection cxn = (HttpURLConnection) this.getURL().openConnection(); //init
cxn.setRequestMethod("GET"); //use HTTP GET verb
cxn.setUseCaches(false); //no cache
cxn.setRequestProperty("Cache-Control", "no-cache"); //even less cache
cxn.setDoOutput(false); //only true in POST/PUT requests
cxn.setRequestProperty("Connection","keep-alive");
cxn.setRequestProperty("DNT", "1"); //TEMP
cxn.setInstanceFollowRedirects(true); //should follow redirects
cxn.setRequestProperty( "charset", "utf-8");
读取结果的代码
int status_code = cxn.getResponseCode();
InputStream responseStream = new BufferedInputStream(cxn.getInputStream());
BufferedReader responseStreamReader = new BufferedReader(new InputStreamReader(responseStream));
String line = "";
StringBuilder stringBuilder = new StringBuilder();
while ((line = responseStreamReader.readLine()) != null) {
stringBuilder.append(line).append("\n");
}
responseStreamReader.close();
String response = stringBuilder.toString();
cxn.disconnect();
【问题讨论】:
-
"Content-Type", "application/x-www-form-urlencoded");????对于 GET 请求?我建议也删除所有其他请求属性。 -
在接收正确数据时遇到问题,我希望您发布阅读它的代码。但你没有。
-
刚刚添加了代码,问题结束。仍然(正如我在上一次更新中解释的那样)我可以从其他服务器接收正确的数据。 @greenapps
-
@greenapps 你对 content-type 属性是正确的。我添加了它,因为它出现在浏览器发送的标题上,但我再次检查它并不存在(我可能读错了)。我删除了它。可悲的是,这并没有解决任何问题
-
GET 和
doOutput(false)和Connection: keep-alive是默认值。不要编写无意义的代码。
标签: java android json laravel http-status-code-301