Cambiando Request Payload a Form Data en Backbonejs

image

backbonejs sync

Me dispuse a crear una API bastante sencilla en un framework de tantos que existen, pero para mi sorpresa este no manejaba muy bien las peticiones PUT y DELETE, lo que provocaba que en mi prueba con Backbonejs y sus modelos no funcionaran bien.. Todo porque básicamente el framework que utilicé no permitían el uso de la transferencia de datos utilizando “Request Payload” y forzosamente solo podía utilizar “Form Data” y fue así como decidí investigar un poco y alterar los métodos originales para siempre utilizar POST.

Un poco de teoría

La diferencia entre request payload y form data esta en que request payload envía todo en formato json al servidor y el form data lo envía como un string de clave y valor unidos por un ampersand, quizás no haya mucha diferencia, pero muchos lenguajes se ponen sus moños y lo aplican diferente en cuanto a la recepción de información, más que todo porque el content type es diferente.

Un ejemplo de como se ven las peticiones en cada caso es el siguiente:

Utilizando Request Payload

POST /url_aqui HTTP/1.1
Content-Type: application/json
 
{ "foo" : "bar", "name" : "John" }

Utilizando Form Data

POST /url_aqui HTTP/1.1
Content-Type: application/x-www-form-urlencoded
 
foo=bar&name=John

Ahora, el método de sincronización de Backbonejs (sync) es el que gestiona las peticiones que se hacen vía ajax al servidor y en sí tiene tres argumentos, que son method, model y options, y específicamente el primer parámetro “method” es que se encarga de determinar el tipo de petición (create, update, delete y read) y gestionar el método que se utilizará (GET, PUT, POST o DELETE).

La idea entonces es que a través de método sync de los modelos de Backbonejs, se modificaran las peticiones de tipo “update” para que en lugar de utilizar PUT y enviar todo por Request Payload, se pueda utilizar POST y se envíe todo por Form Data.

Regresando al código
Pues bien, en realidad hacer el cambio fue bastante sencillo, aunque perdí un par de horas probando hasta dar con el hilo correcto y el código es el siguiente.

define(['backbone'], function(Backbone) {
    var baseSync = Backbone.Model.prototype.sync;
 
    var users = Backbone.Model.extend({
        urlRoot: 'http://localhost/api/users',
        sync: function (method, model, options) {
            if (method == 'update') {
                _.extend(options, {
                    beforeSend: function(xhr, settings) {
                        settings.data = Backbone.$.param(model.attributes);
                        settings.type = 'POST';
                    }
                });
            }
 
            baseSync.apply(this, arguments);
        },
    });
 
    return users;
});

Como verán, he reescrito el método sync del modelo y he modificado la petición “update”, donde internamente se configura el método beforeSend de ajax, luego se toman los atributos o parámetros enviados y se parsean para tener un string en el formato x-www-form-urlencoded en lugar de un objeto de json y al final se cambia el tipo de petición de PUT hacia POST.

Creo fielmente que este tipo de cosas no se deben de hacer, digo.. que me hubiese gustado más tener organizadas los métodos de acuerdo al tipo de petición (create = POST, read = GET, update = PUT, delete = DELETE), pero por una mala decisión en la elección de mi framework tuve que recurrir al parche. Para lo que sí serviría esta modificación sería por ejemplo para dejar de utilizar ajax y cambiarlo hacia localStorage.

(Creo que algo estoy olvidando) :S

Happy Coding!!

Co-fundador de Qbit Mexhico, usuario de linux, Developer en tecnologías web.. Nicaragüense, centro en basketball, primer centro en rugby y pintor los fines de semana. Ortögrafo y ambientalista psicológico (de escritorio).. ese soy yo!

Si te ha servido compártelo y difunde nuestro blog..

Facebook Twitter LinkedIn Google+ Flickr YouTube Skype 

Compartir en...Tweet about this on TwitterPin on Pinterest0Share on LinkedIn1Share on Google+0Share on Facebook1