Я работаю над службой, в которой работает несколько 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 с помощьюразные подходы, я получаю разные результаты.
Используя клиент Джерси и получаю в виде строки
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-ответ, но что?И почему это наблюдалось в некоторых случаях одним клиентом, но игнорировалось другими?
Мне довольно легко исправить саму ошибку - не создавать исключения в фильтре.Но я хочу больше узнать о том, что произошло внизу, и ценю любую помощь.