javascript - Rails and CORS: why am I only seeing the OPTIONS request? -
i having horrible time trying cors working in json api rails app.
i have event
model , associated controller. event
s belong registeredapplication
s.
# routes.rb rails.application.routes.draw root 'registered_applications#index' resources :registered_applications namespace :api, defaults: { format: :json } # option http verb match '/events', to: 'events#create', via: [:options] resources :events, only: [:create] end devise_for :users end
# events_controller.rb class api::eventscontroller < applicationcontroller skip_before_filter :verify_authenticity_token before_filter :cors_preflight_check after_filter :cors_set_access_control_headers # if preflight options request, short-circuit request, # return necessary headers , return empty text/plain. def cors_preflight_check if request.method == :options headers['access-control-allow-origin'] = '*' headers['access-control-allow-methods'] = 'post, get, options' headers['access-control-allow-headers'] = 'x-requested-with, x-prototype-version' headers['access-control-max-age'] = '1728000' render :text => '', :content_type => 'text/plain' end end # responses in controller, return cors access control headers. def cors_set_access_control_headers headers['access-control-allow-origin'] = '*' headers['access-control-allow-methods'] = 'post, get, options' headers['access-control-max-age'] = "1728000" end def create registered_application = registeredapplication.find_by(url: request.env['http_origin']) if registered_application.nil? render json: "unregistered application", status: :unprocessable_entity else event = registered_application.events.new(event_params) if event.save render json: @event, status: :created else render @event.errors, status: :unprocessable_entity end end end private def event_params params.permit(:name) end end
the javascript i'm using send new click events rails app:
$( document ).ready(function() { $( window ).click( function() { metrics.report("click"); }); }); var metrics = {}; metrics.report = function(eventname) { var event = { name: eventname }; var request = new xmlhttprequest(); request.open("post", "http://localhost:3000/api/events", true); request.setrequestheader('content-type', 'application/json'); request.send(json.stringify(event)); }
there 2 issues:
1) when make request via above javascript (from within web page) xmlhttprequest cannot load http://localhost:3000/api/events. request header field content-type not allowed access-control-allow-headers
error. rails api requires request in json don't know supposed that. if comment out setrequestheader()
line error goes away rails app doesn't receive initial http options
request.
2) on rails app side see options request second (post) request never occurs. thing in log:
started options "/api/events" ::1 @ 2015-08-30 12:54:17 -0400 processing api::eventscontroller#create json registeredapplication load (0.2ms) select "registered_applications".* "registered_applications" "registered_applications"."url" = $1 order created_at desc limit 1 [["url", "http://localhost:2222"]] unpermitted parameter: format (0.1ms) begin sql (0.4ms) insert "events" ("registered_application_id", "created_at", "updated_at") values ($1, $2, $3) returning "id" [["registered_application_id", 21], ["created_at", "2015-08-30 16:54:17.751257"], ["updated_at", "2015-08-30 16:54:17.751257"]] (0.4ms) commit completed 201 created in 11ms (views: 0.1ms | activerecord: 1.1ms)
am missing obvious?
i think need add headers['access-control-allow-headers'] = "content-type"
in cors_set_access_control_headers
function in server-side code.
my rails api requires request in json don't know supposed that. if comment out
setrequestheader()
line error goes away rails app doesn't receive initial http options request.
per cors spec, if send content-type
request header value that’s other application/x-www-form-urlencoded
, multipart/form-data
, or text/plain
, cors preflight options
request sent.
so, when send content-type
header value application/json
, triggers options
request. when drop setrequestheader()
line, no custom content-type
header sent (and no other custom “author” headers), in case, no cors preflight required, no options
request made.
Comments
Post a Comment