2015-10-19 27 views
8

Sto usando espresso 4.13.3 (l'ultima) e codice seguente:Perché POST reindirizza a GET e PUT reindirizza a PUT?

var express = require('express') 

var app = express() 

app.get('/test', function (req, res, next) { 
    res.send('hello!') 
}) 

app.post('/test', function (req, res, next) { 
    res.redirect('/test') 
}) 

app.put('/test', function (req, res, next) { 
    res.redirect('/test') 
}) 

app.listen(5001) 

// GET /test -> 'hello!' 
// POST /test -> 'hello!' 
// PUT /test -> ERR_TOO_MANY_REDIRECTS 

POST reindirizza da ottenere, ma PUT reindirizza a PUT. È possibile effettuare il reindirizzamento PUT su GET (come per il POST)?

risposta

7

Prima di immergersi nei dettagli, di seguito è un modo di come si potrebbe risolvere il problema:

app.put('/test', function(req, res, next) { 
    res.redirect(303, '/test') // Notice the 303 parameter 
}) 

Per impostazione predefinita Express utilizza il codice HTTP 302 per il reindirizzamento. Secondo il HTTP specification, questo impedisce le richieste POST/PUT da essere reindirizzato come richieste/PUT POST e spiega che cosa avete osservato nel codice:

Se il codice 302 di stato ricevuto in risposta ad una richiesta diversa da GET o HEAD, il programma utente NON DEVE reindirizzare automaticamente la richiesta a meno che non possa essere confermata dall'utente, poiché questo potrebbe cambiare le condizioni in cui è stata emessa la richiesta.

D'altra parte, se si utilizza un reindirizzamento 303, la richiesta/PUT POST è permesso di essere reindirizzati come una richiesta POST/PUT come spiegato in this great SO answer:

303: Redirect per non definito ragionare. In genere, 'Operazione ha completata, continua altrove.' I clienti che effettuano richieste successive per la risorsa non devono utilizzare il nuovo URI. I client devono seguire il reindirizzamento per le richieste POST/PUT/DELETE.

+0

Ma perché esprimere reindirizza PUT -> PUT e POST -> GET? POST/PUT dovrebbe essere reindirizzato "ugualmente" giusto? Sembra che express usi automaticamente 303 per POST e 302 per PUT? – user606521

+2

@ user606521 La specifica HTTP 1.1 più recente consente in particolare un reindirizzamento 302 per modificare un POST a un GET. (Vedi la citazione pertinente dalla RFC nella mia risposta.) La specifica non consente altre trasformazioni oltre la specifica modifica POST-to-GET, quindi PUT rimane PUT. Questo è per ragioni storiche; Ad esempio, i browser hanno implementato le specifiche originali errate e le specifiche sono cambiate per consentire questo errore. – apsillers

1

Il modo di mettere è corretto, si sta reindirizzando la richiesta in un'altra posizione, ma il metodo http è lo stesso. E questo è il motivo per cui sta tentando di accedere nuovamente a put. (Non sta modificando il metodo http.)

Perché post reindirizza a get

Ecco answer.

8

In primo luogo, cerchiamo di capire che cosa res.redirect does:

res.redirect ([stato,] percorso)

reindirizza all'URL derivato dal percorso specificato, con codice di stato HTTP specificato stato. Se non si specifica lo stato, il codice di stato viene impostato su "302" Trovato ".

Se guardiamo alla HTTP 1.1 spec for a 302 response, vediamo

Nota: Per ragioni storiche, un agente utente può cambiare il metodo di richiesta da POST a GET per la successiva richiesta.Se il comportamento di non è desiderato, è possibile utilizzare il codice di stato 307 (temporaneo reindirizzamento) .

Una richiesta di 307 manterrà il verbo HTTP in tutti i casi, ma non è ciò che si desidera. Vuoi che il verbo cambi in GET. In questo caso, si desidera un 303:

303 vedi altri

Il 303 (vedi altri) codice di stato indica che il server è reindirizzare l'utente agente a una risorsa diversa, come indicato dal a URI nel campo dell'intestazione Location, che è destinato a fornire una risposta indiretta alla richiesta originale . Un agente utente può eseguire una richiesta di recupero con targeting URI (una richiesta GET o HEAD se utilizzando HTTP), che potrebbe anche essere reindirizzato e presentare l'eventuale risultato come risposta alla richiesta originale.

Una risposta 303 richiederà al client (a condizione che comprenda HTTP 1.1) di eseguire una richiesta GET sulla risorsa specificata. Quindi, inserisci semplicemente un codice di stato 303 nei tuoi reindirizzamenti:

res.redirect(303, '/test')