Что происходит, когда исключение выдается из фильтра после завершения сервлета? - PullRequest
0 голосов
/ 20 февраля 2019

Я работаю над службой, в которой работает несколько REST API с использованием Java-сервлета.

Сервлет использует аннотации, предоставленные javax.ws.rs, для определения URL-адреса API, метода HTTP и т. Д. Поэтому один из них может выглядеть следующим образомследующим образом:

@Path("root")
@Service
public class MyClass {
    @Path("path")
    @Get
    @Produces("application/json; charset=UTF-8")
    public ResponseObject myAction() { ... }
}

У меня также есть фильтр, который из-за какой-то ошибки мог выдать исключение после выполнения сервлета.Таким образом, он ведет себя следующим образом:

public class MyFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
        chain.doFilter(request, response);
        throws new Exception();
    }
}

Файл web.xml содержит следующее определение: (не полное, только те, которые, на мой взгляд, могут иметь значение)

<servlet>
    <servlet-name>jersey-servlet</servlet-name>
    <servlet-class>
        com.sun.jersey.spi.spring.container.servlet.SpringServlet
    </servlet-class>
    <init-param>
        <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
        <param-value>true</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<filter>
    <filter-name>MyFilter</filter-name>
    <filter-class>myorg.MyFilter</filter-class>
</filter>

Когда я вызываю этот API с помощьюразные подходы, я получаю разные результаты.

  1. Используя клиент Джерси и получаю в виде строки

    WebResource resource = client.resource("https://my-service/root/path");
    ClientResponse response = resource.get(ClientResponse.class);
    String s = response.getEntity(String.class);
    

Это даст мне ошибку ниже:

Caused by: java.io.IOException: Premature EOF
at sun.net.www.http.ChunkedInputStream.readAheadBlocking(ChunkedInputStream.java:565)
at sun.net.www.http.ChunkedInputStream.readAhead(ChunkedInputStream.java:609)
at sun.net.www.http.ChunkedInputStream.read(ChunkedInputStream.java:696)
at java.io.FilterInputStream.read(FilterInputStream.java:133)
at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.read(HttpURLConnection.java:3393)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.Reader.read(Reader.java:140)
at com.sun.jersey.core.util.ReaderWriter.readFromAsString(ReaderWriter.java:171)
at com.sun.jersey.core.util.ReaderWriter.readFromAsString(ReaderWriter.java:157)
at com.sun.jersey.core.provider.AbstractMessageReaderWriterProvider.readFromAsString(AbstractMessageReaderWriterProvider.java:114)
at com.sun.jersey.core.impl.provider.entity.StringProvider.readFrom(StringProvider.java:73)
at com.sun.jersey.core.impl.provider.entity.StringProvider.readFrom(StringProvider.java:58)
at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:634)

Использование клиента Джерси, но десериализация ответа JSON в объект

WebResource resource = client.resource("https://my-service/root/path");
ClientResponse response = resource.get(ClientResponse.class);
ResponseObject result = response.getEntity(ResponseObject.class);

Это вернется успешно, и в результате ResponseObject будет содержать правильное содержимое.

Вызовите этот API с помощью HTTP-инструмента Почтальон.Это также вернет статус 200 и правильное тело ответа.

Вызов API с использованием базовой библиотеки .Net RestSharp

var restClient = new RestClient("https://my-service/");
var request = new RestRequest("/root/path", method);
var response = restClient.Execute(request);

Это не удастсясо следующей ошибкой:

The server returned an invalid or unrecognized response.
at System.Net.Http.HttpConnection.FillAsync()
at System.Net.Http.HttpConnection.ChunkedEncodingReadStream.ReadAsyncCore(Memory`1 buffer, CancellationToken cancellationToken)
at System.Net.Http.HttpConnection.HttpContentReadStream.Read(Byte[] buffer, Int32 offset, Int32 count)
at RestSharp.Extensions.MiscExtensions.ReadAsBytes(Stream input)
at RestSharp.Http.ProcessResponseStream(Stream webResponseStream, HttpResponse response)
at RestSharp.Http.ExtractResponseData(HttpResponse response, HttpWebResponse webResponse)
at RestSharp.Http.GetResponse(HttpWebRequest request)

Мой вопрос: Что случилось с моим HTTP-ответом в этом случае и почему разные клиенты вели себя по-разному?Я предполагаю, что когда MyClass.myAction завершен, сериализованный объект возврата ResponseObject уже был отправлен клиенту.Однако когда управление вернулось к MyFilter, возникла ошибка.Должно быть, это как-то повлияло на HTTP-ответ, но что?И почему это наблюдалось в некоторых случаях одним клиентом, но игнорировалось другими?

Мне довольно легко исправить саму ошибку - не создавать исключения в фильтре.Но я хочу больше узнать о том, что произошло внизу, и ценю любую помощь.

...