Rotaie che non ricaricano la sessione su un post Ajax

Sto riscontrando un problema molto strano con Rails e ajax che usano jQuery (anche se non penso sia specifico per jQuery).

L’applicazione My Rails utilizza lo store sessione cookie e ho un accesso molto semplice che imposta l’id utente nella sessione. Se user_id non è impostato nella sessione, reindirizza a una pagina di accesso. Questo funziona senza problemi. Anche le richieste di JQuery GET funzionano bene. Il problema è quando eseguo un POST jQuery – il browser invia il cookie di sessione ok (l’ho confermato con Firebug e ho scaricato request.cookies nel log) ma la sessione è vuota, cioè la sessione è {}.

Lo sto facendo nel mio application.js:

$(document).ajaxSend(function(e, xhr, options) { var token = $("meta[name='csrf-token']").attr('content'); xhr.setRequestHeader('X-CSRF-Token', token); }); 

e qui è il mio post di esempio:

 $.post('/test/1', { _method: 'delete' }, null, 'json'); 

che dovrebbe arrivare a questo metodo di controllo (_method: delete):

     def destroy respond_to do |format| format.json { render :json => { :destroyed => 'ok' }.to_json } end end 

    Guardando il log e utilizzando Firebug posso confermare che il valore del cookie corretto viene inviato nell’intestazione della richiesta quando si verifica il post di ajax, ma sembra che a un certo punto Rails perde questo valore e quindi perde la sessione, quindi reindirizza al login pagina e non arriva mai al metodo.

    Ho provato tutto quello che posso pensare per eseguire il debug di questo, ma mi viene in mente l’idea che questo potrebbe essere un bug in Rails. Sto usando Rails 3.0.4 e jQuery 1.5 se questo aiuta. Trovo molto strano che le richieste di posta e post regolari (cioè non-ajax) funzionino e che le richieste di ajax get funzionino senza problemi, sono solo i post ajax che non lo fanno.

    Qualsiasi aiuto nel tentativo di risolvere questo sarebbe molto apprezzato!

    Grazie molto,
    Dave

    Risponderò alla mia domanda mentre sono riuscito a capire cosa stava succedendo. Lo posterò qui nel caso sia utile a chiunque altro!

    Dopo aver esaminato ulteriormente, ho scoperto che il codice che doveva impostare l’intestazione della richiesta con il token CSRF, non lo era. Questo era il codice originale:

     $(document).ajaxSend(function(e, xhr, options) { var token = $("meta[name='csrf-token']").attr('content'); xhr.setRequestHeader('X-CSRF-Token', token); }); 

    Quello che stava succedendo era che questo codice non stava impostando l’intestazione, Rails stava ricevendo una richiesta Ajax, il token non corrispondeva e stava ripristinando la sessione. Questo è stato usato per generare un errore ActionController :: InvalidAuthenticityToken (suppongo che lo avrei rilevato prima se fosse stato sollevato un errore … vabbè), ma dal momento che Rails 3.0.4 ora resetta tranquillamente la sessione.

    Quindi per inviare il token nell’intestazione, devi farlo (molte grazie a questo meraviglioso post sul blog ):

     $.ajaxSetup({ beforeSend: function(xhr) { xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content')); } }); 

    E ora tutto funziona come dovrebbe. Che è bello

    Ho trovato un altro caso:

    hai impostato ‘csrf_meta_tag’ nel tuo file di layout dell’applicazione?

    nel mio caso, non ho impostato quel tag e ho incontrato lo stesso problema con il tuo.

    E dopo aver impostato il file csrf_meta_tag in app / views / layouts / application.html.erb, tutto funziona correttamente!

    Alla fine, grazie per avermi aiutato a trovare la causa principale! grazie mille ~

    Questo è ciò che l’ adattatore jQuery-Ujs rails ufficiale è per la serie 3.0. Devi ricordare di tenerlo aggiornato durante l’aggiornamento delle versioni di rails però.

    Per me, l’aggiornamento dalla 3.0.3 alla 3.0.8.rc4 significava anche recuperare manualmente il file src/rails.js dal repository collegato.

    Dal momento che Rails 3.1 ha finalmente fatto il passaggio a jQuery, le cose dovrebbero essere aggiornate automaticamente in futuro tramite la gem jquery-rails durante l’aggiornamento delle rotaie (e utilizzando la pipeline di asset integrata di 3.1)