2013-08-28 31 views
8

Znajduję się w sytuacji, w której moja aplikacja musi sprawdzić zawartość/dane/treść/ładunek żądania POST, nie zmieniając wyników kolejnych wywołań funkcji getParameter.Przeczytaj treść instrukcji POST HTTPServletRequest, a następnie wywołaj metodę getParameter w Tomcat.

Czytając ciało od InputStream:

Ciało można odczytać za pomocą InputStream od request.getInputStream lub BufferedReader od request.getReader.

parametry Reading Post:

żądania POST zazwyczaj zawierają parametry żądania w treści wniosku. Można je odzyskać za pomocą getParameter.

problem:

pierwszy getParameter połączenia wewnętrznie analizuje InputStream i wstawia wszystkie parametry do HashMap parametrów. Wymaga, aby inputStream nadal zawierał zawartość do parsowania. Zatem nie można sprawdzić zawartości i nadal mieć działające wywołanie getParameter.

Proponowany (ale nie wystarczający) Rozwiązanie

Tworzenie owijkę żądania że buforuje InputStream i zwraca cache dla getInputStream.

Widziałem to rozwiązanie zasugerowane w całym Internecie, ale nie działa, ponieważ getParameter w rzeczywistości nie wywołuje getInputStream, ale odnosi się do oryginalnego inputBuffer pochowany w obiekcie żądania. Próbowałem go, zarówno z Serwletu, jak i używając filtru. Jedyne rozwiązanie, jakie mogę wymyślić, to przepisanie funkcji getParameter, aby ręcznie parsować ręcznie buforowany strumień wejściowy. Ale to jest zły pomysł.

Czy ktoś ma jakąś alternatywę, która działa? (To jest Tomcat 5.5) Wydaje się, że powinien to być typowy przypadek użycia; Nie mogę uwierzyć, jakie to trudne.

+1

Odpowiedź na to pytanie nie jest rozwiązaniem. Zaimplementowałem go i nie udało się rozwiązać problemu. Od tego czasu czytałem źródło tomcat i zdałem sobie sprawę, że getParameter nie wywołuje metody getInputStream, jak napisałem powyżej, a zatem nie odczytałoby jej z buforowanej wersji strumienia. patrz http://grepcode.com/file/repo1.maven.org/maven2/tomcat/catalina/5.5.23/org/apache/catalina/connector/RequestFacade.java?av=f#342 Nie jestem pewnie, dlaczego ludzie uważają to za rozwiązanie. – rewolf

+0

Metoda 'getParameter' wywołaj' getInputStream'. Najpierw wywołaj 'getParameter' wywołaj' parseParameters', następnie 'parseParameters' wywołaj' readPostBody', następnie 'readPostBody' wywołaj' getInputStream'. – peakmuma

Odpowiedz

1

Zgodnie z sugestią @caskey, możliwym rozwiązaniem byłoby użycie odbicia, aby zastąpić inputBuffer odtwarzalnym buforem wejściowym. Ale nie skorzystałem z tego podejścia, ponieważ było to niegrzeczne.

Zamiast tego utworzyłem owijkę żądania w filtrze, która odczytuje strumień wejściowy do tablicy bajtów i zwraca nową InputStream, która wewnętrznie używa ByteArrayInputStream wokół tej tablicy dla wszystkich wywołań getInputStream.

Po odczytaniu strumienia wejściowego do tablicy bajtów utworzę mapę parametrów poprzez analizowanie ładunku. Połączyłem mapę parametrów superklasy, aby obsługiwać przypadki GET z parametrami zapytania. Zastąpiłem wszystkie metody getParameter *(), aby użyć tej mapy parametrów.

Użyłem apache.axis.utils.IOUtils.readFully do łatwego odczytu strumienia do tablicy bajtów. I obecnie używam javax.servlet.http.HttpUtils.parsePostData do parsowania danych do mapy parametrów. HttpUtils.parsePostData jest rzeczywiście przestarzałe, więc prawdopodobnie go zastąpię lepszą wersją, gdy ją znajdę.

Ale to działa, dziękuję!

1

(to raczej stary kocur, jestem przy założeniu upgrade do bardziej nowoczesnego jednego nie jest rozwiązaniem.)

Co chcesz zrobić będzie wymagać przechwycenia budowę betonowego HttpServletResponse obiektu zawijania bazowego Strumień wejściowy. Zawijanie tego strumienia wejściowego w strumieniu wejściowym typu push-back (lub jego odpowiedniku) jest konieczne.

Tomcat 5.5 jest tak stary, że nie mogę nawet pomyśleć, jak by to osiągnąć "normalnie", ale może mógłbyś napisać filtr, który używa odbicia, by dosięgnąć i zamienić obiekt InputStream wewnątrz konkretnego obiektu żądania.

+0

Tak. Jesteś świetnym pomysłem na refleksję. My też to wymyśliliśmy. Zdecydowałem się jednak na inne podejście - stworzenie opakowania żądania w filtrze obsługującym odtwarzanie strumienia wejściowego. Nadpisałem następnie metody getParameter *(), aby odczytać mapę utworzoną przez analizowanie strumienia wejściowego/ładunku. – rewolf

Powiązane problemy