L'authentification HTTP de base ne comprenant pas JSON en-tête? (Backbone.js au serveur Rails)
-
11-10-2019 - |
Question
J'utilise Backbone.js pour créer un pur JS frontal pour mes rails application à l'aide d'un api JSON.
L'URL modèle de Backbone.js ressemble à ceci:
window.MedicationCollection = Backbone.Collection.extend({
model: Medication,
url: 'http://localhost:3000/medication_options'
});
CRUD fonctionne très bien avec cela. Il est l'envoi de requêtes à mon serveur avec une « application / JSON » type de contenu.
Mais je besoin d'ajouter l'authentification pour l'API et mon application utilise des rails Authlogic donc j'ajouté ceci:
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
Et une méthode CRUD typique dans des rails ressemble à ceci:
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
Donc, dans mon modèle, je Backbone.js ajouté "nom d'utilisateur: mot de passe" à l'url:
window.MedicationCollection = Backbone.Collection.extend({
model: Medication,
url: 'http://username:password@localhost:3000/medication_options'
});
L'authentification fonctionne très bien avec les informations d'identification appropriées, mais pour une raison quelconque toutes les demandes Backbone.js sont interprétées par le serveur Rails en HTML au lieu de JSON.
Pour une raison quelconque au cours d'une base authentification HTTP, l'en-tête JSON se perd dans le mélange.
Donc, si j'ajouter explicitement « .json » à la fin de l'URL comme ceci:
window.MedicationCollection = Backbone.Collection.extend({
model: Medication,
url: 'http://username:password@localhost:3000/medication_options.json'
});
Je peux recevoir des demandes GET de base au travail.
Mais quand je fais CRUD cela ne fonctionne pas parce qu'il ajoute l'ID à la fin de l'URL, il des erreurs:
ActionController::RoutingError (No route matches "/medication_options.json/41516")
Je ne suis pas sûr où aller d'ici.
La solution
Votre .json doit toujours être à la fin de l'URL pour être interprété comme JSON:
/medication_options/41516.json
Vous pouvez modifier l'URL modèle ainsi que l'URL de collecte si nécessaire pour mettre le JSON au bon endroit.
Le problème de la racine est pourquoi il ne soit pas traité comme JSON en premier lieu. Si vous utilisez des rails 3 avez-vous:
respond_to :js
ou
respond_to :json
pour correspondre à votre respond_with et assurez-vous que votre contrôleur accepte ce genre de format (rails autrement retour 406 erreur par défaut)?
Autres conseils
Je ne l'ai jamais utilisé Document.js, mais en regardant à travers les documents, il semble que vous pouvez remplacer url
et retourner le résultat d'une fonction au lieu de lui donner une valeur de chaîne littérale. Pourriez-vous ajouter le .json
à la fin de la chaîne url de cette façon?
Essayez quelque chose comme ceci:
_.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);
}
});