【问题标题】:Android EOFException when using HttpURLConnection headers使用 HttpURLConnection 标头时出现 Android EOFException
【发布时间】:2013-10-28 17:35:46
【问题描述】:

我使用自定义授权标头签署我的 http 请求:

String key="client="+USER+",hash="+sha1(STR, API_KEY)+",timestamp="+t.toString();

如果有人对 sha1 方法感兴趣:http://pastebin.com/HRFXQ4Bk 密钥字符串用作标题:

URL url = new URL(sb.toString());

HttpURLConnection conn = null;  
conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Authorization", key);
conn.setRequestMethod("GET");

InputStreamReader in = new InputStreamReader(conn.getInputStream());

当我尝试获取响应时,出现以下错误:

10-28 18:25:40.111: E/error(6855): java.io.EOFException 10-28 18:25:40.111:E/错误(6855):在 libcore.io.Streams.readAsciiLine(Streams.java:203) 10-28 18:25:40.111: E/错误(6855):在 libcore.net.http.HttpEngine.readResponseHeaders(HttpEngine.java:579) 10-28 18:25:40.111:E/错误(6855):在 libcore.net.http.HttpEngine.readResponse(HttpEngine.java:827) 10-28 18:25:40.111:E/错误(6855):在 libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:283) 10-28 18:25:40.111:E/错误(6855):在 libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:177)

在我的服务器上,此请求未记录任何访问。但是,当我删除 auth 标头时,会根据服务器日志建立与我的服务器的连接。

那么 auth 标头是如何影响请求的呢?为什么使用header时没有连接?


顺便说一句,像

这样的标题
conn.setRequestProperty("Authorization", "FOOBAR");

有效,但是由于授权标头不符合要求而被拒绝:

10-29 08:12:07.235: E/error(23663): java.net.ConnectException: 失败 连接到 api.myserver.net(端口 1337): 连接失败:ECONNREFUSED(连接被拒绝)10-29 08:12:07.235: E/错误(23663):在 libcore.io.IoBridge.connect(IoBridge.java:114) 10-29 08:12:07.235:E/错误(23663):在 java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192) 10-29 08:12:07.235:E/错误(23663):在 java.net.PlainSocketImpl.connect(PlainSocketImpl.java:459)

我的网络服务要求标头具有以下格式

match(/client=([^,]*),hash=([^,]*),timestamp=([^,]*)/);

所以这个异常不同于最初的异常。当我删除标头并禁用我的网络服务上的授权时,连接按预期工作。所以问题似乎出在自定义授权标头上。有什么想法吗?

【问题讨论】:

  • 您应该使用java.net.Authenticator, 而不是自己滚动。
  • @EJP 我只想设置一个标题并且不提示用户输入凭据

标签: java android


【解决方案1】:

根据question,看起来某些版本的 Android 可能存在问题。

尝试将conn.setRequestProperty("Connection", "close") 添加到您的请求中。

【讨论】:

  • 老鼠,希望能做到。在仔细查看libcore.io.Streams 类之后,我的第二个猜测是您需要在标题末尾附加一个换行符(readAsciiLine 方法的文档指出“如果流抛出 java.io.EOFException在下一个换行符之前用尽”)。希望对您有所帮助。
  • hm 很好,但是错误仍然存​​在。我在标题末尾尝试了\n,没有成功。
  • 奇数。似乎任何受到攻击的 Web 服务都会返回一个未正确解析的响应标头。我会尝试进入HttpEngine.readResponseHeaders 看看响应是什么样的。抱歉,我无法提供更多帮助。
  • +1 感谢信息。这是我自己的休息网络服务。它需要特定的标头,否则将返回 403 状态。我更新了我的问题
  • 这对我来说是在一个通常可以正常工作的应用程序中完成的。该问题仅在模拟器中运行时出现。 API 级别设置为 23,Android 版本设置为 Marshmellow(免责声明:我对 Android 几乎一无所知,而且我不喜欢 mashmellows。我什至不知道如何正确拼写它们)
【解决方案2】:

首先,检查您的 URL 是否包含意外的换行符('\n' 或 '\r\n'),如果有,读取响应时会出现 EOFException。换行将中继 HTTP 包,服务器认为客户端有更多数据要发送,所以没有响应。每次读取响应的尝试都会立即获得 EOF。

确保您的请求有效后,请尝试其他人提供的解决方案。

【讨论】:

    【解决方案3】:

    当我将 Android 应用程序的后端从 Asp 更改为 PHP 时,我开始看到这个问题。

    我解决了这个问题,在我的 PHP 页面上添加了以下行:

    header("Connection: close");
    

    【讨论】:

      【解决方案4】:

      这可能只是因为在这种情况下您的服务器响应不完全正确。

      我的服务器使用的是 python SimpleHTTPServer,我错误地认为我需要做的所有事情都表明成功:

      self.send_response(200)
      

      这会发送初始响应标头行、服务器和日期标头,但会使流处于您也可以发送其他标头的状态。 HTTP 需要在标头后添加一个新行以指示它们已完成。当您尝试使用 HttpURLConnection 获取结果正文 InputStream 或响应代码等时,如果这条新行不存在,那么它会抛出 EOFException (这实际上是合理的,考虑一下)。一些 HTTP 客户端确实接受了简短的响应并报告了成功结果代码,这导致我可能不公平地指责 HttpURLConnection。

      我更改了我的服务器来执行此操作:

      self.send_response(200)
      self.send_header("Content-Length", "0")
      self.end_headers()
      

      该代码不再出现 EOFException。 “连接:关闭”解决方案可能会在某些可能解决此问题的服务器上触发某些行为(例如,确保在关闭之前响应有效)但python SimpleHTTPServer 的情况并非如此,根本原因结果是我的错。

      注意:Android pre-Froyo (2.2) 上存在一些与保持连接相关的错误,但我认为这不是其中之一。

      【讨论】:

      • 感谢 Ben Silver 在接受的答案中的评论让我明白了这一点。我认为也值得发布答案,因为很容易错过 cmets。
      猜你喜欢
      • 2012-09-01
      • 2013-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-21
      • 1970-01-01
      • 2013-01-26
      • 1970-01-01
      相关资源
      最近更新 更多