2016-02-24 34 views
5

Sto lavorando con un framework Web (uPortal) che gestisce gli errori semplicemente lanciando un'eccezione e quindi sospendendo. Il framework funziona rendendo l'XML in HTML. Quando c'è un'eccezione, il browser riceve il contenuto reso fino all'elemento del modello XML che non funziona, quindi il browser si siede e attende un timeout. La teoria del nostro team è che il contenuto viene inviato prima che si verifichi l'errore, cosa che mi ha sorpreso. Altri framework con cui ho lavorato sembrano finire il rendering prima di inviare contenuti.Reindirizza la pagina Web dopo aver inviato alcuni contenuti

La mia domanda è, c'è un modo per reindirizzare il browser dopo che il contenuto è già stato inviato? In questo caso, siamo nel mezzo del rendering del contenuto di un tag <script>, ma l'errore potrebbe verificarsi potenzialmente ovunque nel codice HTML.

Il mio unico pensiero attuale è quella di iniettare un po 'di javascript nella parte superiore della pagina, e cercare di cambiare il comportamento del quadro a fallire rapidamente e chiudere la connessione e aggiungere </body> e </html> tag quando si verifica un errore. Quindi il javascript sopra menzionato verrebbe eseguito sul pageload e rileverà se il contenuto dell'intera pagina era presente e eseguirà un reindirizzamento sul lato client se non lo è. Forse potrebbe cercare uno speciale div nascosto in fondo alla pagina.

Esistono esempi di framework che risolvono questo problema in modo diverso o di persone che utilizzano framework simili che lavorano a questo problema?

risposta

0

Non so tale contesto, ma

in HTTP, ogni risposta ha una risposta-codice associato con esso. Poiché la pagina è già stata trasferita/resa a metà, il codice di stato (in genere "200") è stato già inviato (e ricevuto).

Non è possibile per il browser accettare un altro codice di risposta (come "301" per il reindirizzamento) per la stessa risposta! Inoltre, il server non è in grado di inviare un altro codice di risposta, poiché il codice di risposta originale era già stato commesso e inviato al client.

La descrizione dell'errore e della conoscenza del protocollo http implica che ci sia probabilmente qualche errore di implementazione nei componenti framework/server utilizzati, OPPURE è stato fatto deliberatamente, mettendo a rischio la situazione in cui ci si trova ...

0

per reindirizzare una pagina, è necessario impostare le informazioni di reindirizzamento nell'intestazione. ma è possibile scrivere intestazione volta che si avvia la scrittura di contenuti (potrebbe essere un colpo di testa è già ricevuta dal cliente nel momento in cui competere a scrivere tutto il documento)

Ma, lo si può fare in maniera diversa, come di seguito

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

Una risposta HTTP consiste di intestazioni e un contenuto di risposta facoltativo. Dopo aver iniziato a scrivere la risposta alla connessione del socket, non è possibile ripristinarlo. Nel tuo esempio: se si verifica un errore nel corso della generazione del contenuto, non è possibile aggiungere un'intestazione di reindirizzamento: la sezione dell'intestazione è già stata scritta.

L'istruzione riportata sopra non è completamente vera: in HTTP chunked transfer encoding la risposta viene inviata in blocchi separati. L'ultimo blocco può avere un trailer opzionale contenente i campi di intestazione dell'entità e in teoria un'intestazione di reindirizzamento. Ma se puoi usare questi meccanismi è una domanda diversa. Ad esempio un contenitore servlet può usare la codifica di trasferimento chunked ma non ti fornisce un'API per impostare il trailer.

Ma la scrittura non deve iniziare immediatamente: ad esempio HttpServletResponse mantiene un buffer per il contenuto della risposta. Se si impostano le intestazioni e si inizia a scrivere il contenuto, viene riempito solo il buffer e si può comunque ripristinare la risposta e ricominciare tutto da capo. Ma una volta che il buffer fuoriesce, la risposta viene scritta sulla connessione e lo HttpServletResponse è ora impegnato.

Un tale meccanismo consente di gestire gli errori durante la generazione del contenuto che si verificano quando la risposta non è ancora stata eseguita: basta resettare la risposta e inviare invece un messaggio di errore. Potresti esaminare il tuo framework se supporta un tale meccanismo. Ma ovviamente questa non è una soluzione per risposte più ampie.

Un altro modo per evitare errori durante la generazione del contenuto è semplicemente quello di assicurarsi che non possano accadere. Prima raccogli tutti i dati necessari per la risposta (ad esempio, effettuando chiamate al database non sicure), quindi in una seconda fase genera la risposta: il secondo passaggio dovrebbe non non riuscito (eccetto se hai errori nel codice).

Hai già menzionato un terzo modo per gestire un errore, facendo sì che il client disinfetti la risposta e intraprenda un'azione in caso di errori rilevati (ad esempio includendo uno script nella risposta HTML generata).

+0

In che modo altri framework risolvono questo problema? Come la primavera, per esempio? Non molla aspettare fino a quando le visualizzazioni non vengono visualizzate prima di scrivere sulla risposta? Oppure tutti i framework hanno questo problema? – xdhmoore

+0

@xdhmoore alla fine Spring si basa anche sulla tecnologia servlet e, per quanto ne so, segue la seconda strategia menzionata nella mia risposta. Questo https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc potrebbe essere di interesse, ma è principalmente su come inviare a una pagina di errore significativo e non su come evitare o recuperare da un'eccezione. – wero

+0

Spring ti consente di rilevare eccezioni dal livello vista/jsp? Dove sono confuso è che in questo framework stiamo vedendo il blocco della pagina all'eccezione dopo aver caricato tutto il contenuto precedente.Avevo pensato che altri framework come spring rendevano tutto prima di iniziare a restituire il contenuto (in modo che potessero restituire una pagina di errore in caso di eccezione), ma questo framework sembra iniziare a restituire il contenuto prima che venga eseguito il rendering, che mi sembra di fare la tua opzione 3 sopra l'unica scelta ... – xdhmoore

1

È necessario acquisire l'errore o acquisire l'output in un buffer. Se si riesce a gestire l'eccezione, probabilmente si può stampare un semplice tag script come

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

Se il browser capisce il doctype di essere qualcosa legato al HTML, eseguirà quel tag.

Se è possibile acquisire l'output in un buffer, quando si gestisce l'errore è possibile decidere di inviare un reindirizzamento HTTP al browser e distruggere il buffer di output fino a quel punto.

Come per altri frameowrks, in PHP, è possibile abilitare semplicemente il buffering dell'output con ob_start(), che non inizierà a inviare il contenuto fino a quando la richiesta non sarà completata.

0

L'unico modo affidabile per eseguire questa operazione è creare un oggetto proxy HttpServletResponse che memorizza nella cache la risposta. Dovresti fornire a uPortal questo proxy anziché l'effettivo HttpServletResponse e inviare l'output utilizzando la risposta reale solo quando l'elaborazione completa/invia il reindirizzamento se l'elaborazione non riesce.

È la limitazione della progettazione del protocollo HTTP che non è possibile inviare il reindirizzamento HTTP una volta avviato l'output.

Altri possibili modi si basano su reindirizzamenti HTML o Javascript, ma dal momento che si scrive che l'errore può verificarsi in qualsiasi momento, sarebbe difficile stamparlo in modo che i browser possano interpretarlo in modo affidabile come reindirizzamento.