Тело HttpServletRequest пусто, когда война развернута в AWS
Я вижу несоответствие в поведении моего кода при работе на моей локальной машине по сравнению с AWS Elastic Beanstalk. Код для получения уведомления от Google Glass.
Фрагмент кода выглядит следующим образом:
public class NotifyServlet extends HttpServlet implements WeiboConstants{
private static final Logger LOG = Logger.getLogger(NotifyServlet.class.getSimpleName());
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Respond with OK and status 200 in a timely fashion to prevent redelivery
response.setContentType("text/html");
Writer writer = response.getWriter();
writer.append("OK");
writer.close();
LOG.info("perpare reading");
BufferedReader notificationReader =
new BufferedReader(new InputStreamReader(request.getInputStream()));
String notificationString = "";
LOG.info("begin reading ");
// Count the lines as a very basic way to prevent Denial of Service attacks
int lines = 0;
while (notificationReader.ready()) {
LOG.info("reading");
notificationString += notificationReader.readLine();
lines++;
// No notification would ever be this long. Something is very wrong.
if (lines > 1000) {
throw new IOException("Attempted to parse notification payload that was unexpectedly long.");
}
}
LOG.info("got raw notification " + notificationString);
JsonFactory jsonFactory = new JacksonFactory();
Сервер Google будет делать POST, который регистрируется отдельно:
Subscription subscription = MirrorClient.insertSubscription(credential, "https://mirrornotifications.appspot.com/forward?url=http://foo.elasticbeanstalk.com/notify", userId,
"timeline");
При тестировании на моей локальной машине я запускал mvn jetty: запустить и изменить foo
в приведенном выше коде my ip address:8080
,
Я могу получить уведомление от Google:
{"collection": "timeline", "itemId": "5cbf8f54-822d-4a8e-9a9f-508687bbb9e2", "operation": "INSERT", "userToken": "105242333117256730066", "userActions": [{"type": "LAUNCH"}]}
Но когда я упаковал войну (mvn war:war) и развернул ее в AWS, из журнала я вижу, что она была успешно зарегистрирована в Google, и я получаю POST от Google на / уведомить, но похоже на тело пусто, как показано в следующем журнале:
Dec 06, 2013 5:01:55 AM com.google.glassware.NotifyServlet doPost
INFO: perpare reading
Dec 06, 2013 5:01:55 AM com.google.glassware.NotifyServlet doPost
INFO: begin reading
Dec 06, 2013 5:01:55 AM com.google.glassware.NotifyServlet doPost
INFO: got raw notification
Dec 06, 2013 5:01:55 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [notify] in context with path [] threw exception
java.lang.IllegalArgumentException: no JSON input found
Как я могу отлаживать дальше?
ОБНОВИТЬ
Я развернул тот же файл war на сервере под управлением Jetty вместо Tomcat, и он работает нормально, кажется, что это особая проблема Tomcat?
1 ответ
Для дальнейшей отладки вы можете попытаться опубликовать уведомление прямо на http://foo.elasticbeanstalk.com/notify
Если это приводит к тому же поведению, я бы поближе BufferedReader.ready()
как условие цикла.
ready()
это неблокирующий метод. Это означает, что если по какой-то причине BufferedReader
не готов немедленно вернуть данные, тогда метод немедленно вернет false, и цикл будет полностью пропущен.
Тогда следующим шагом в отладке будет закомментировать ready()
и идти прямо с блокировкой readLine()
чтобы подтвердить, что ваш сервлет получает полезную нагрузку.
Обновить
Кажется, что у Jetty и Tomcat есть разные реализации для BufferedReader.ready().
Вот связанный вопрос переполнения стека, который я нашел после дальнейших исследований: BufferedReader ready method