Модернизация POST java .io.IOException: неожиданное завершение потока в соединении, вызванное java .io.EOFException: \ n не найдено: - PullRequest
2 голосов
/ 25 апреля 2020

Я прошел через все вопросы, связанные с этим, и все же, я не нашел решения, которое работает для меня.

Я использую 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)

Несколько вещей, которые я пробовал до сих пор

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

API отлично работает с почтальоном, но не работает, когда я пытаюсь из кода. Поэтому я попробовал те же заголовки, присланные почтальоном. Все еще не повезло.

Несколько замечаний:

  1. Иногда это работает. Не всегда сбой. (Один и тот же файл всегда работает с почтальоном)
  2. Он всегда работает для других файлов (никогда не возникает проблема).
  3. Запрос достигает сервера и обрабатывает запрос без каких-либо ошибки и отвечает тоже. Я получаю сообщение об ошибке сразу после того, как сервер завершает обработку и отвечает клиенту.

РЕДАКТИРОВАТЬ 1: Сервер, на который я нажал, поддерживается gunicorn / 20.0.4 и использует Flask , У меня нет доступа к коду сервера. И я сомневаюсь, что в полученном ответе есть некоторые символы мусора, вызывающие ошибку. Я не знаю, как записать необработанный ответ перед чтением с помощью retrofit / okhttp.

EDIT 2:

Я выполнил команду Curl с подробным описанием, и это что я получил.

  • Пустой ответ от сервера
  • Соединение № 0 с хостом xx.xxx.xxx.9 левый нетронутый локон: (52) Пустой ответ с сервера

Ответы [ 2 ]

0 голосов
/ 27 апреля 2020

Короткая история

Проблема была с сервером, который я ударил. Он не отправлял никакого ответа (буквально ничего. Никаких заголовков, никакого тела, ничего).

Длинная история

Итак, после прохождения всех связанных ответов на stackoverflow, других хороших веб-сайтах и ​​опробования так много решений, которые я упомянул в самом вопросе, не решило мою проблему.

Внимательно прочитав трассировку стека, я наткнулся на следующую строку:

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

Клиент (мой код) пытается прочитать заголовок ответа, и именно тогда возникает ошибка java.io.EOFException: \n not found: limit=0 content=

Это дало мне подсказку, что проблема может быть с сервером, а не с клиентом. Поэтому я подумал, что мне следует попробовать с другим клиентом и посмотреть, смогу ли я увидеть необработанный ответ.

Первым инструментом, который мне пришёл в голову, был Curl (Почтальон раньше давал шаблон c Не удалось получить никакого ответа , и это не происходило последовательно). Я попал на сервер, используя curl с подробной опцией и boom! Я получил следующий ответ:

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).

Мораль истории: Прочитайте трассировку стека, даже если кажется, что не стоит заглядывать:)

0 голосов
/ 27 апреля 2020

Вы получаете пустой ответ без строки состояния. Это проблема. HTTP-запросы обычно возвращают строку состояния (например, HTTP/1.1 200 OK\r\n), которая содержит код состояния, см. https://www.ietf.org/rfc/rfc2616.txt главу 6.1. Обычно это ошибка сервера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...