rails ruby-on-rails-4 xmlhttprequest cors rails-routing http-method

ruby-on-rails-4 - rack cors ruby on rails



Rails responde con 404 en CORS Solicitud de Opciones de Preflight (7)

Estoy creando un conjunto de servicios usando Rails 4, que estoy consumiendo con una aplicación de navegador JavaScript. Los GETS de origen cruzado funcionan bien, pero mis POST fallan en la comprobación de OPCIONES previas a la verificación con un error 404. Al menos, creo que eso es lo que está pasando. Aquí están los errores tal como aparecen en la consola. Esto es Chrome 31.0.1650.63 en una Mac.

OPTIONS http://localhost:3000/confessor_requests 404 (Not Found) jquery-1.10.2.js:8706 OPTIONS http://localhost:3000/confessor_requests No ''Access-Control-Allow-Origin'' header is present on the requested resource. Origin ''http://localhost'' is therefore not allowed access. jquery-1.10.2.js:8706 XMLHttpRequest cannot load http://localhost:3000/confessor_requests. No ''Access-Control-Allow-Origin'' header is present on the requested resource. Origin ''http://localhost'' is therefore not allowed access. main.html:1

He buscado alto y bajo para obtener instrucciones sobre cómo habilitar CORS, y estoy perplejo. La recomendación habitual parece ser poner algo como esto en el controlador de aplicaciones, lo cual hice.

before_filter :cors_preflight_check after_filter :cors_set_access_control_headers def cors_set_access_control_headers headers[''Access-Control-Allow-Origin''] = ''*'' headers[''Access-Control-Allow-Methods''] = ''POST, PUT, GET, OPTIONS'' headers[''Access-Control-Allow-Headers''] = ''*'' headers[''Access-Control-Max-Age''] = "1728000" end def cors_preflight_check if request.method == :options headers[''Access-Control-Allow-Origin''] = ''*'' headers[''Access-Control-Allow-Methods''] = ''POST, PUT, GET, OPTIONS'' headers[''Access-Control-Allow-Headers''] = ''*'' headers[''Access-Control-Max-Age''] = ''1728000'' render :text => '''', :content_type => ''text/plain'' end end

Seguido por algún tipo de ruta en routes.rb que redireccionará a esta acción cuando entre una solicitud OPTIONS.

match "/*all" => "application#cors_preflight_check", :constraints => { :method => "OPTIONS" }

La directiva de "coincidencia" ya no funciona en Rails 4, así que jugué con ella, intentando que coincida con POSTS directamente, así:

post "/*all" => "application#cors_preflight_check", :constraints => { :method => :options }

Pero todavía no funciona. Como las solicitudes GET están funcionando, asumo que lo que me falta es la ruta correcta para la solicitud OPTIONS. Sin embargo, he intentado todas las rutas que puedo pensar, y nada parece permitir que pase la solicitud.

También intenté instalar cyu/rack-cors , y esto da el mismo resultado.

¿Alguien sabe lo que estoy haciendo mal?


Aquí hay una solución con la gema rack-cors , que dijiste que probaste. Como han mencionado otros, no proporcionó muchos detalles con respecto a qué marco de front-end está utilizando y cómo es la solicitud real. Por lo tanto, es posible que lo siguiente no se aplique a usted, pero espero que ayude a alguien.

En mi caso, la gema funcionó bien hasta que usé PUT (o PATCH o DELETE).

Si miras en la consola de desarrollo de tu navegador, mira los encabezados de las solicitudes y deberías tener una línea como esta:

Access-Control-Request-Method: PUT

Lo importante a tener en cuenta es que los methods que pasa al resource son para el Access-Control-Request-Method , no el método de solicitud que debe venir después del control previo al vuelo.

Tenga en cuenta que tengo :methods => [:get, :post, :options, :delete, :put, :patch] que incluirá todos los métodos que me interesan.

Por lo tanto, toda la sección de configuración debería tener el siguiente aspecto, para development.rb :

# This handles cross-origin resource sharing. # See: https://github.com/cyu/rack-cors config.middleware.insert_before 0, "Rack::Cors" do allow do # In development, we don''t care about the origin. origins ''*'' # Reminder: On the following line, the ''methods'' refer to the ''Access- # Control-Request-Method'', not the normal Request Method. resource ''*'', :headers => :any, :methods => [:get, :post, :options, :delete, :put, :patch], credentials: true end end


Me encontré con el mismo problema, y ​​actualmente estoy evaluando las siguientes rutas para cualquier posible problema de seguridad / rendimiento. Ellos resuelven el problema, pero ...

match ''/'', via: [:options], to: lambda {|env| [200, {''Content-Type'' => ''text/plain''}, ["OK/n"]]} match ''*unmatched'', via: [:options], to: lambda {|env| [200, {''Content-Type'' => ''text/plain''}, ["OK/n"]]}

A pesar de que ''match'' supuestamente no funciona en Rails 4, aparentemente funciona si lo restringes a un método específico.


No estoy seguro de qué framework de JavaScript está utilizando (o si lo está) ya que no dio más detalles sobre lo que está haciendo en el lado del cliente para conectarse a su API de Rails 4, pero pensé que agregaría mi respuesta en caso de que ayude a alguien.

Me encontré con el mismo problema cuando me conecté a una API de Rails 4 con la gema Devise desde una interfaz AngularJS (ambas se ejecutaban en puertos de host locales). Intenté iniciar sesión en el back-end utilizando una solicitud POST desde un formulario AngularJS pero seguí obteniendo un error 404 NO ENCONTRADO porque estaba enviando una solicitud de OPCIONES con verificación previa. Tomó más de 2 días descubrir cómo solucionar el problema.

Básicamente, debe configurar un servidor proxy para su interfaz (Angular, Backbone, lo que sea) con el fin de conectarse a su API para que su interfaz piense que la solicitud utiliza el mismo origen. Hay algunas soluciones sencillas para configurar Proxies usando GruntJS. Estoy usando Gulp para mi proyecto con Gulp-Connect y proxy-middleware con la siguiente configuración (basada en la solución que se encuentra here ):

var gulp = require(''gulp''), connect = require(''gulp-connect''); gulp.task(''devServer'', function() { connect.server({ root: ''./dist'', fallback: ''./dist/index.html'', port: 5000, livereload: true, middleware: function(connect, o) { return [ (function() { var url = require(''url''); var proxy = require(''proxy-middleware''); var options = url.parse(''http://localhost:3000/''); options.route = ''/api''; return proxy(options); })() ]; } }); });

¡Espero que esto ayude a alguien!


Sí, como otros han señalado que hay un GEM que quizás lo haga mejor. Pero como me gustó mucho el método señalado en la publicación del blog original con el código cors, encontré la solución Rails 4 si está usando ese código.

En tus routes.rb:

match ''*all'' => ''my_method_name#cor'', via: :options

En tu controlador my_method_name:

def cor # blank section for CORR render :text => '''' end

Mientras tengas eso más tu otro código:

before_filter :cors_preflight_check after_filter :cors_set_access_control_headers ...

Entonces deberías configurar Rails 4.


Se encontró con este problema con Rails 4 y Devise. Terminé usando la cyu/rack-cors Rack CORS middleware de Calvin Yu. Un gran article blog complementario.


Tal vez esta esencia puede ayudarlo: CORS in Rails 4 APIs

Agrega el método OPTIONS a la definición de ruta y agrega un filtro al controlador base API que responde directamente a las solicitudes OPTIONS con el encabezado correcto y establece los encabezados CORS correctos para todas las demás acciones también.


Trabajando en Rails 3.2.11.

pongo

match ''*path'', :controller => ''application'', :action => ''handle_options_request'', :constraints => {:method => ''OPTIONS''}

en mi archivo routes.rb. La clave era ponerlo como prioridad principal (en la parte superior del archivo routes.rb). Creó esa acción para que esté disponible al público :

def handle_options_request head(:ok) if request.request_method == "OPTIONS" end

Y un filtro en el controlador de la aplicación:

after_filter :set_access_control_headers def set_access_control_headers headers[''Access-Control-Allow-Origin''] = ''*'' headers[''Access-Control-Allow-Methods''] = ''GET, POST, PUT, DELETE'' end