对POST,PUT和PATCH等的Cors请求不起作用。只有GET

时间:2014-08-01 02:32:15

标签: ruby-on-rails api

我有一个rails应用程序,它有一个人们可以使用的API。不幸的是,api显然只允许我做GET请求而没有别的。我尝试了一个POST请求,您无需进行身份验证。

所有API控制器都使用从BaseController扩展的ApplicationController module Api module V1 class BaseController < ApplicationController respond_to :json before_action :default_json rescue_from ActiveRecord::RecordNotFound, :with => :record_not_found after_filter :cors_access protected # Give access to everyone from the api sub domain. def cors_access if request.subdomain == "api" headers['Access-Control-Allow-Origin'] = '*' headers['Access-Control-Request-Method'] = '*' end end end end end 。它看起来像这样:

api.sitename.com/api/v1/what/x/ever/y

现在核心网址是XMLHttpRequest cannot load http://api.writer.aisisplatform.com/api/v1/posts/16/comments/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9000' is therefore not allowed access.

我可以做好GET请求,但是当谈到POST我得到:

{{1}}

那么为什么我可以执行GET请求而不是POST请求呢?

3 个答案:

答案 0 :(得分:0)

尝试:

def cors_access
  if request.subdomain == "api"
    headers['Access-Control-Allow-Origin'] = '*'
    headers['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS'
    headers['Access-Control-Allow-Credentials'] = 'true'
    headers['Access-Control-Allow-Headers'] = 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type'
  end
end

ajax api的调用将是:

$.ajax('http://api.writer.aisisplatform.com/api/v1/posts/16/comments/', {
    xhrFields: { withCredentials: true },
    crossDomain: true,
    success: function(res) {
        console.log(res)
    },
    error: function (xhr, error) {
        console.log(xhr, error)
    }
})

如果您使用反向代理来提供请求,建议使用它,我认为在请求中没有多少负责的rails插入标头,所以我将向您展示在nginx中完成的示例:

location /api/ {
    add_header 'Access-Control-Allow-Origin' '*';
    add_header 'Access-Control-Allow-Credentials' 'true';
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
    add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';

    proxy_pass http://your_balancer;
}

通过这样做,你不需要在铁轨上做任何事情。

希望这对你有所帮助。

答案 1 :(得分:0)

<强>机架CORS

高度建议使用rack-CORS gem

#config/application.rb
config.middleware.use Rack::Cors do
    allow do
      origins '*'
      resource 'api/v1', :headers => :any, :methods => [:get, :post, :put, :patch]
    end
end

在控制器中手动使用CORS是一个配置地狱 - 你将更适合使用上述代码和放大器。宝石保持清洁。我们上面的工作非常好

good Railscast about this here

答案 2 :(得分:0)

为了使用主干,您需要进行同步调整,看起来像这样:

(function(Backbone) {
  var methods, _sync;

  _sync = Backbone.sync;

  methods = {
    beforeSend: function() {
      return this.trigger('sync:start', this);
    },
    complete: function() {
      return this.trigger('sync:stop', this);
    }
  };

  Backbone.sync = function(method, entity, options) {
    var sync;

    if (options == null) options = {};

    _.defaults(options, {
      beforeSend: _.bind(methods.beforeSend, entity),
      complete: _.bind(methods.complete, entity)
    });

    // add crossDomain
    if (!options.crossDomain) options.crossDomain = true;

    // add xhrFields
    if (!options.xhrFields) {
      options.xhrFields = {
        withCredentials: true
      };
    }

    sync = _sync(method, entity, options);

    if (!entity._fetch && method === 'read') return entity._fetch = sync;
  };
})(Backbone);

默认情况下,骨干网发出的所有请求都是GET类型,POST需要在fetch中发送一个options对象:

model = new Backbone.Model();
model.fetch({ url: 'http://api.com/uri', type: 'POST' })