Basic HTTP Authentication not including JSON in header? (Backbone.js to Rails server)
I'm using Backbone.js to create a pure JS front-end for my rails app using a JSON api.
The backbone.js model URL looks like this:
window.MedicationCollection = Backbone.Collection.extend({
model: Medication,
url: 'http://localhost:3000/medication_options'
});
CRUD works fine with this. It's sending requests to my server with an "application/JSON" content type.
But I needed to add authentication for the API and my rails app is using Authlogic so I added this:
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
And a typical CRUD method in rails looks like this:
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
So in my Backbone.js model I added "username:password" to the url:
window.MedicationCollection = Backbone.Collection.extend({
model: Medication,
url: 'http://username:password@localhost:3000/medication_options'
});
The authentication works fine with the appropriate credentials, but for some reason all of the Backbone.js requests are interpreted by the Rails server as HTML instead of JSON.
For some reason during an Basic HTTP authentication, the JSON header gets lost in the mix.
So if I explicitly add ".json" to the end of the URL like this:
window.MedicationCollection = Backbone.Collection.extend({
model: Medication,
url: 'http://username:password@localhost:3000/medication_options.json'
});
I can get basic GET requests to work.
But when I do CRUD it doesn't work because it appends the ID to the end of the URL, so it errors:
ActionController::RoutingError (No route matches "/medication_options.json/41516")
So I'm not sure where to go from here.
Your .json should always be at the end of the url to be interpreted as json:
/medication_options/41516.json
You can edit the Model url as well as the collection URL if needed to put the json at the right place.
The root problem is why it doesn't get processed as json in the first place. If you are using rails 3 do you have:
respond_to :js
or
respond_to :json
to match your respond_with and make sure your controller accepts this kind of format (otherwise rails would return 406 error by default)?
I've never used Document.js, but in looking through the docs it seems you can override url
and return the result of a function instead of giving it a literal string value. Could you add the .json
to the end of the url string that way?
Try something like this:
_.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);
}
});
精彩评论