La autenticación básica HTTP no incluidos en la cabecera JSON? (Backbone.js al servidor Rails)
-
11-10-2019 - |
Pregunta
Estoy usando Backbone.js para crear un front-end JS puro para mis carriles de APP mediante una API JSON.
Los Backbone.js modelo de URL es similar al siguiente:
window.MedicationCollection = Backbone.Collection.extend({
model: Medication,
url: 'http://localhost:3000/medication_options'
});
ABM funciona bien con esto. Está enviando peticiones a un servidor con un "/ JSON aplicación" tipo de contenido.
Pero necesitaba para agregar autenticación para el API y mi rieles aplicación utilice Authlogic por lo que añade lo siguiente:
before_filter :require_user
def require_http_auth_user
return true if current_user
authenticate_or_request_with_http_basic do |email, password|
email = email.gsub("_at_", "@") if email.include?("_at_")
if @current_user = User.find_by_email(email)
@current_user.valid_password?(password)
else
false
end
end
end
Y un método CRUD típico de raíles se ve así:
def update
@medication_option = MedicationOption.find(params[:id])
if @medication_option.update_attributes(params[:medication_option])
flash[:notice] = "Successfully updated medication."
end
respond_with @medication_option
end
Así que en mi modelo Backbone.js añadí "nombre de usuario: contraseña" a la URL:
window.MedicationCollection = Backbone.Collection.extend({
model: Medication,
url: 'http://username:password@localhost:3000/medication_options'
});
La autenticación funciona bien con las credenciales apropiadas, pero por alguna razón todas las peticiones Backbone.js son interpretados por el servidor Rails como HTML en lugar de JSON.
Por alguna razón durante una autenticación HTTP básico, la cabecera JSON se pierde en la mezcla.
Así que si puedo añadir de forma explícita ".json" al final de la URL así:
window.MedicationCollection = Backbone.Collection.extend({
model: Medication,
url: 'http://username:password@localhost:3000/medication_options.json'
});
que puedo conseguir peticiones básicas llegar al trabajo.
Pero cuando lo haga CRUD no funciona, ya que añade la ID al final de la URL, por lo que los errores:
ActionController::RoutingError (No route matches "/medication_options.json/41516")
Así que no estoy seguro de dónde ir desde aquí.
Solución
Su .json siempre debe estar al final de la url para ser interpretado como JSON:
/medication_options/41516.json
Puede editar la URL Modelo, así como la dirección URL de colección si es necesario poner el JSON en el lugar correcto.
La raíz del problema es por eso que no se procesan como JSON en el primer lugar. Si está utilizando los carriles 3 tiene usted:
respond_to :js
o
respond_to :json
para que coincida con su respond_with y asegúrese de que su controlador acepta este tipo de formato (de lo contrario volvería carriles 406 de error por defecto)?
Otros consejos
Nunca he usado Document.js, sino en mirar a través de los documentos parece que se puede anular url
y devolver el resultado de una función en lugar de darle un valor de cadena literal. ¿Es posible añadir el .json
hasta el final de la cadena URL de esa manera?
intentar algo como esto:
_.extend(Medication,
{extension:'.json',
url:function() {
var base = getUrl(this.collection);
if (this.isNew()) return base + this.extension;
return (base + (base.charAt(base.length - 1) == '/' ? '' : '/')
+ this.id + this.extension);
}
});