私はこれに関連するすべての質問を通過しました、しかし、私は私のために働く解決策を見つけていません。
retrofit 2.8.1
とOkHttp 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)
これまでに試したことはほとんどありません
APIはpostmanからは正常に動作しますが、コードから試行すると失敗します。だから私は郵便配達人によって送信された同じヘッダーを試しました。まだ運がない。
いくつかの観察:
編集1:ヒットしたサーバーはgunicorn/20.0.4に支えられており、Flaskを使用しています。サーバーコードにアクセスできません。また、受信した送信応答に、エラーの原因となる文字化けがあるとは思いません。 retrofit/okhttpで読み取られる前に生の応答をログに記録する方法がわかりません。
編集2:
私はCurlコマンドを冗長で実行しましたが、これは私が得たものです。
<HTTP/1.1 100続行
- サーバーからの空の応答
- ホストxx.xxx.xxx.9への接続#0はそのままのカールを残しました:(52)サーバーからの空の応答
問題は私が打ったサーバーにありました。応答を送信していませんでした(文字通り何もありません。ヘッダーも、本文も、何もありません)。
したがって、stackoverflow、他の優れたWebサイトで関連するすべての回答を調べ、質問自体で述べた非常に多くの解決策を試しても、問題は解決しませんでした。
スタックトレースを注意深く読んだ後、次の行に出くわしました。
okhttp3.internal.http1.Http1Codec.readResponseHeaders(Http1Codec.Java:203)
クライアント(私のコード)はResponseヘッダーを読み取ろうとしていますが、これはエラーJava.io.EOFException: \n not found: limit=0 content=
がスローされます。
これにより、クライアントではなくサーバーに問題がある可能性があることがわかりました。だから私は別のクライアントを試してみて、生の応答を見ることができるかどうかを確認する必要があると思いました。
私の頭に浮かんだ最初のツールはCurl
でした(Postmanは一般的に応答を取得できませんでしたでしたが、これは一貫して発生しませんでした)。 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)ではなくサーバーにあることが確認されました。
物語の教訓:時々スタックトレースを読む必要があるように見えない場合でも、ワード単位で読む必要があります:)
ステータス行のない空の返信が返されます。これが問題です。 HTTPリクエストは通常、ステータス行を返します(例:HTTP/1.1 200 OK\r\n
)、ステータスコードが含まれます https://www.ietf.org/rfc/rfc2616.txt 6.1章を参照してください。これは通常、サーバーエラーです。