I have the same issue in Chrome due to CORS (Cross-Origin resource sharing)
The browser will first send an OPTIONS request, then expect to return some HTTP headers that indicate which are allowed.
I solved this problem by doing some server-side settings. For both sides, Ruby and Node.js both work well.
Node.js (Thanks to the essay )
// Enables CORS var enableCORS = function(req, res, next) { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS'); res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With'); // intercept OPTIONS method if ('OPTIONS' == req.method) { res.send(200); }else{ next(); } }; // enable CORS! app.use(enableCORS);
Ruby (thanks essay )
class ApplicationController < ActionController::Base before_filter :cors_preflight_check after_filter :cors_set_access_control_headers # For all responses in this controller, return the CORS access control headers. def cors_set_access_control_headers headers['Access-Control-Allow-Origin'] = '*' headers['Access-Control-Allow-Methods'] = 'POST, GET, PUT, DELETE, OPTIONS' headers['Access-Control-Allow-Headers'] = 'Origin, Content-Type, Accept, Authorization, Token' headers['Access-Control-Max-Age'] = "1728000" end # If this is a preflight OPTIONS request, then short-circuit the # request, return only the necessary headers and return an empty # text/plain. def cors_preflight_check if request.method == 'OPTIONS' headers['Access-Control-Allow-Origin'] = '*' headers['Access-Control-Allow-Methods'] = 'POST, GET, PUT, DELETE, OPTIONS' headers['Access-Control-Allow-Headers'] = 'X-Requested-With, X-Prototype-Version, Token' headers['Access-Control-Max-Age'] = '1728000' render :text => '', :content_type => 'text/plain' end end end