Retrofit POST java.io.IOException: unexpected end of stream on Connection caused by java.io.EFOFException: \n not found:

问题描述 投票:1回答:1

我查看了所有与此相关的问题,但我还没有找到适合我的解决方案。

我使用的是 retrofit 2.8.1OkHttp 4.5.0.

我的服务界面如下

public interface MlApiService
{
    @POST
    @Multipart
    Call<List<PreprocessedDocument>> postDocument( @Url String apiUrl, @Part MultipartBody.Part document,
    @Part ( "document_id") RequestBody documentId );
}

而我建立的客户端是这样的 requestTimeoutInSeconds 设置为90秒。

public void init()
{
    GsonBuilder gson = new GsonBuilder();
    gson.registerTypeAdapter( new TypeToken<List<PreprocessedDocument>>() {}.getType(), new CustomResponseDeserializer() );

    HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor();
    logInterceptor.setLevel( HttpLoggingInterceptor.Level.HEADERS );

    OkHttpClient client = new OkHttpClient.Builder().retryOnConnectionFailure( true ).addInterceptor( logInterceptor )
        .readTimeout( requestTimeoutInSeconds, TimeUnit.SECONDS ).build();
    //Dummy Base URL must be provided. otherwise client won't get initialized
    Retrofit retrofit = new Retrofit.Builder().baseUrl( "http://thisIsJustDummyUrlForTheSakeOfAddingBaseUrl.com/" )
        .client( client ).addConverterFactory( GsonConverterFactory.create( gson.setLenient().create() ) ).build();
    mlApiService = retrofit.create( MlApiService.class );
}

请求到达服务器,就在服务器响应的时候,我得到了以下错误。

Caused by: java.io.IOException: unexpected end of stream on Connection{34.219.110.9:8085, proxy=DIRECT hostAddress=/34.219.110.9:8085 cipherSuite=none protocol=http/1.1}
    at okhttp3.internal.http1.Http1Codec.readResponseHeaders(Http1Codec.java:203)
    at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:88)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45)
Caused by: java.io.EOFException: \n not found: limit=0 content=…
    at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:227)
    at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:211)
    at okhttp3.internal.http1.Http1Codec.readResponseHeaders(Http1Codec.java:187)

到目前为止,我已经尝试了一些事情

  1. retryOnConnectionFailure(true)
  2. .addHeader("Connection", "close")
  3. .header("Accept-Encoding", "identity")

API在postman中工作正常,但当我从代码中尝试时却失败了。所以我尝试了postman发送的同样的头文件。还是没有结果。

一些观察。

  1. 有时能用 并不总是失败。(同一个文件在postman中总是工作)
  2. 对于其他文件,它总是工作(从来没有问题)。
  3. 请求到达服务器并处理请求,没有任何错误,也没有响应。当服务器完成处理并回复客户端后,我立即得到错误。

EDIT 1:我打的服务器是由gunicorn20.0.4支持的,使用Flask。我没有访问服务器代码的权限。而且我怀疑发送收到的响应是否有一些垃圾字符导致错误。我不知道如何在被 retrofitokhttp 读取之前记录原始响应。

EDIT 2:

我用verbose运行Curl命令,得到的结果是:

< HTTP1.1 100 继续

  • 服务器的回复为空
  • 连接#0到主机xx.xxx.xxx.9的连接被完好无损的curl。(52) 来自服务器的回复为空
java flask retrofit2 gunicorn okhttp
1个回答
2
投票

小故事

问题出在我所打的服务器上,它没有发送任何响应(完全没有。它没有发送任何响应(实际上什么都没有,没有标题,没有正文,什么都没有)。

长话短说

所以在翻阅了stackoverflow上所有相关的答案,其他好的网站,并尝试了那么多我在问题本身中提到的解决方案后,并没有解决我的问题。

在仔细阅读了堆栈跟踪之后,我看到了以下一行。

okhttp3.internal.http1.Http1Codec.readResponseHeaders(Http1Codec.java:203)

客户端(我的代码)正在尝试读取Response头,这时出现了以下错误 java.io.EOFException: \n not found: limit=0 content= 被抛出。

这给了我一个提示,问题可能出在服务器上,而不是客户端。所以我想我应该用不同的客户端试试,看看是否能看到原始响应。

我想到的第一个工具是 Curl (邮递员曾经给通用的 无法得到任何答复 而这并不是持续发生的)。) 我使用带有verbose选项的curl访问服务器,然后轰!我得到了如下的响应:"我是说,我的服务器是一个很好的服务器。我得到了以下的响应。

curl -v --location --request POST 'http://XX.XXX.XXX.9:8085/psc/document_upload' --form 'document=@/home/user376/Downloads/test-1.pdf' --form 'document_id=22004494_ae7f_4998_a1d8_73249bda9905'
Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying XX.XXX.XXX.9...
* Connected to XX.XXX.XXX.9 (XX.XXX.XXX.9) port 8085 (#0)
> POST /psc/document_upload HTTP/1.1
> Host: XX.XXX.XXX.9:8085
> User-Agent: curl/7.49.0
> Accept: */*
> Content-Length: 4684053
> Expect: 100-continue
> Content-Type: multipart/form-data; boundary=------------------------a8446c7eedb10689
> 
< HTTP/1.1 100 Continue
* Empty reply from server
* Connection #0 to host XX.XXX.XXX.9 left intact
curl: (52) Empty reply from server

这证实了问题出在服务器上,而不是客户端(Retrofit http)。

这个故事的寓意。 有时候你必须一个字一个字地读 stacktrace,即使它看起来不值得去看 :)


1
投票

你会得到一个没有状态线的空回复。这就是问题所在。HTTP-request通常会返回一个状态行(例如. HTTP/1.1 200 OK\r\n),其中包含状态代码,见 https:/www.ietf.orgrfcrfc2616.txt 第6.1章.这通常是一个服务器错误。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.