2016-02-24 36 views
5

Pracuję z frameworkiem internetowym (uPortal), który obsługuje błędy, wyrzucając wyjątek, a następnie zawieszając. Struktura działa poprzez renderowanie XML do HTML. W przypadku wyjątku przeglądarka otrzymuje renderowaną treść do elementu szablonu XML, który się nie powiódł, a następnie przeglądarka po prostu siedzi i czeka na przekroczenie limitu czasu. Według naszej teorii treść jest wysyłana przed wystąpieniem błędu, co mnie zaskoczyło. Inne frameworki, nad którymi pracowałem, kończą renderowanie przed wysłaniem treści.Przekieruj stronę po wysłaniu zawartości

Moje pytanie brzmi, czy istnieje sposób przekierowania przeglądarki po przesłaniu zawartości? W takim przypadku jesteśmy w trakcie renderowania treści tagu <script>, ale błąd może wystąpić potencjalnie w dowolnym miejscu w html.

Moja jedyna obecna myśl polega na wstrzyknięciu niektórych javascriptów na górze strony i próbie zmiany zachowania struktury w celu szybkiego zamknięcia i zamknięcia połączenia oraz dodania tagów </body> i </html> w przypadku wystąpienia błędu. Następnie wspomniany wyżej javascript będzie działał na pageload i wykryje, czy cała zawartość strony była tam i czy przekierowuje klienta, jeśli nie. Być może mógłby znaleźć specjalny ukryty div na dole strony.

Czy istnieją przykłady frameworków rozwiązujących ten problem w różny sposób lub osób używających podobnych frameworków w odniesieniu do tego problemu?

Odpowiedz

0

nie wiem, te ramy, ale

http, każda odpowiedź jest odpowiedzią kod z nim związane. Ponieważ strona jest już w połowie przesłana/wyrenderowana, kod statusu (zwykle "200") został już wysłany (i odebrany).

Nie ma sposobu, aby przeglądarka zaakceptowała inny kod odpowiedzi (np. "301" dla przekierowania) dla tej samej odpowiedzi! Również serwer nie może wysłać kolejnego kodu odpowiedzi, ponieważ oryginalny kod odpowiedzi został już zatwierdzony jako i wysłany do klienta.

Twój opis błędu i wiedzy na temat protokołu http sugeruje, że prawdopodobnie wystąpił błąd implementacji w użytych komponentach szkieletowych/serwerowych, LUB został zrobiony celowo, ryzykując sytuację, w której jesteś teraz ...

0

do przekierowania strony, musisz ustawić przekierowanie informacji w nagłówku. ale można napisać nagłówek po rozpoczęciu pisania treści (może być nagłówek jest już odbierany przez klienta w momencie konkurować pisać cały dokument)

Ale można to zrobić w inny sposób jak poniżej

1.let document loading complete and record if you need to redirect the page while rendering 
2. add a unique request-id identifier for each page load 
3. invoke ajax call with request-id (may be rest call) to server asking if page needs to be redirected. 
4. if page needs to be redirected , do so, via javascript in browser at client end. 
0

Odpowiedź HTTP składa się z nagłówków i opcjonalnej treści odpowiedzi. Po rozpoczęciu pisania odpowiedzi na połączenie z gniazdem nie można go przywrócić. W twoim przykładzie: Jeśli napotkasz błąd w trakcie generowania treści, nie możesz dodać nagłówka przekierowania - sekcja nagłówka już została napisana.

Powyższe stwierdzenie nie jest do końca prawdziwe: w protokole HTTP chunked transfer encoding odpowiedź jest wysyłana w oddzielnych porcjach. Ostatni fragment może mieć opcjonalny zwiastun zawierający pola nagłówka podmiotu i teoretycznie nagłówek przekierowania. Ale jeśli możesz użyć tego mechanizmu, to jest inne pytanie. Na przykład kontener serwletu może wykorzystywać kodowane kodowanie transferowe, ale nie zapewnia interfejsu API do ustawiania zwiastuna.

Jednak pisanie nie może rozpocząć się natychmiast: Na przykład HttpServletResponse utrzymuje bufor dla zawartości odpowiedzi. Jeśli ustawisz nagłówki i zaczniesz zapisywać treść, tylko bufor zostanie wypełniony i nadal możesz zresetować odpowiedź i zacząć wszystko od nowa. Jednak po przepełnieniu bufora odpowiedź jest zapisywana w połączeniu, a HttpServletResponse jest teraz zatwierdzona.

Taki mechanizm daje sposób radzenia sobie z błędami podczas generowania treści, które występują, gdy odpowiedź nie jest jeszcze zatwierdzona: wystarczy zresetować odpowiedź i zamiast tego wysłać komunikat o błędzie. Możesz sprawdzić swoją strukturę, jeśli obsługuje ona taki mechanizm. Ale oczywiście nie jest to rozwiązanie dla większych odpowiedzi.

Drugi sposób na uniknięcie błędów podczas generowania treści to po prostu upewnienie się, że nie mogą się zdarzyć. Najpierw zebranie wszystkich danych potrzebnych do odpowiedzi (np. Wykonywanie niebezpiecznych połączeń z bazami danych), następnie w drugim kroku wygeneruj odpowiedź - drugi krok nie powinien być , a nie (chyba że masz błędy w kodzie).

Wspomniano już o trzecim sposobie rozwiązania problemu polegającego na oczyszczeniu odpowiedzi przez klienta i podjęciu pewnych działań, w których wykryto błędy (np. Poprzez uwzględnienie skryptu w wygenerowanej odpowiedzi HTML).

+0

W jaki sposób inne ramy rozwiązują ten problem? Na przykład Spring? Czy wiosna nie czeka, aż widoki zostaną wyświetlone przed zapisaniem odpowiedzi? A może wszystkie frameworki mają ten problem? – xdhmoore

+0

@xdhmoore na końcu Spring jest również oparty na technologii serwletów i, o ile wiem, po drugiej strategii wspomnianej w mojej odpowiedzi. To https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc może być interesujące, ale chodzi głównie o to, jak wysyłać na sensowną stronę błędu, a nie jak unikać lub wyjdź z wyjątku. – wero

+0

Czy wiosna pozwala wychwycić wyjątki z warstwy widoku/jsp? Tam, gdzie jestem zdezorientowany, jest to, że w tej strukturze widzimy, jak strona zamraża się na wyjątek po załadowaniu całej poprzedniej zawartości.Myślałem, że inne frameworki, takie jak wiosna, renderowały wszystko przed rozpoczęciem zwracania treści (aby mogły zwrócić stronę błędu w przypadku wyjątku), ale ta struktura wydaje się zaczynać powracającą treść przed zakończeniem renderowania, co wydaje mi się twoja opcja 3 powyżej jedynego wyboru ... – xdhmoore

1

Musisz przechwycić błąd lub przechwycić dane wyjściowe w buforze. Jeśli można obsłużyć wyjątek, prawdopodobnie można wydrukować prosty tag skryptu jak

<script> window.location.href = 'some_new_url';</script> 

Jeśli przeglądarka rozumie doctype być coś związanego z HTML, będzie wykonywał ten tag.

Jeśli możesz przechwycić dane wyjściowe w buforze, podczas obsługi błędu możesz zdecydować o wysłaniu przekierowania HTTP do przeglądarki i zniszczyć bufor wyjściowy do tego momentu.

Podobnie jak w przypadku innych frameowrksów, w PHP można po prostu włączyć buforowanie wyjściowe za pomocą ob_start(), które nie rozpocznie wysyłania zawartości, dopóki żądanie nie zostanie w pełni zakończone.

0

Jedynym niezawodnym sposobem, aby to zrobić, jest utworzenie obiektu proxy, który buforuje odpowiedź. Musisz podać uPortal to proxy zamiast rzeczywistego HttpServletResponse i wysyłać dane wyjściowe tylko za pomocą rzeczywistej odpowiedzi, gdy przetwarzanie zakończy/wyśle ​​przekierowanie, jeśli przetwarzanie nie powiedzie się.

Ograniczenie projektu protokołu HTTP uniemożliwia wysyłanie przekierowania HTTP po uruchomieniu wyjścia.

Inne możliwe sposoby polegać na przekierowaniach HTML lub JavaScript, ale ponieważ piszesz, że błąd może się zdarzyć w dowolnym momencie, byłoby to trudne do wydrukowania w taki sposób, aby przeglądarki mogły ją niezawodnie zinterpretować jako przekierowanie.