1

I'm trying to send custom headers to rails api, but I keep getting this stupid options!

ActionController::RoutingError (No route matches [OPTIONS] "/api/v1/surveys")

I've enabled headers I want to send in APIs application_controller.rb, at least I think I did, by having the following code in it:

before_filter :allow_cross_domain

private
def allow_cross_domain
  headers['Access-Control-Allow-Origin'] = '*'
  headers['Access-Control-Allow-Methods'] = 'POST, GET, PUT, DELETE, OPTIONS'
  headers['Access-Control-Allow-Headers'] = 'X-User-Token, X-User-Email, Origin, Content-Type, Accept, Authorization, Token'
end

And I'm trying to send X-User-Token and X-User-Email headers.

So on my client side I make the following call:

$.ajax({
  headers: {
    'Accept': 'application/json',
    'Content-type': 'application/x-www-form-urlencoded',
    'X-User-Email': 'my@email.com',
    'X-User-Token': 'fj4402SDgsGDS42'
  },
  url: Host.address + '/api/v1/surveys',
  type: 'GET',
}).done(function(response){});

And I've also tried beforeSend:

$.ajax({
  url: Host.address + '/api/v1/surveys',
  type: 'GET',
  beforeSend: function(xhr) {
    xhr.setRequestHeader('Accept','application/json');
    xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
    xhr.setRequestHeader('X-User-Email', 'my@email.com');
    xhr.setRequestHeader('X-User-Token', 'fj4402SDgsGDS42');
  },
}).done(function(response){}

It only breaks if I send X-User-Email or X-User-Token. When I send Accept and Content-type headers only, it works as it's suppose to.

Does anybody have any idea what might be causing this issue?

EDIT:
I haven't mentioned I'm using Devise for user authentication.
Adding the routes for survey (I guess you don't need all of them :)

Rails.application.routes.draw do
  devise_for :users, skip: [:registration, :sessions]

  namespace :api, as: false do
    namespace :v1, as: false do
      resources :responses, only: [:index, :new, :create]  
      resources :surveys, only: [:index, :create, :show]
    end
  end
end
    surveys GET    /api/v1/surveys(.:format)                api/v1/surveys#index
            POST   /api/v1/surveys(.:format)                api/v1/surveys#create
     survey GET    /api/v1/surveys/:id(.:format)            api/v1/surveys#show

Error I get in browser console is:

OPTIONS http://localhost:3003/api/v1/surveys

XMLHttpRequest cannot load http://localhost:3003/api/v1/surveys. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 404.

antonpot
  • 41
  • 9

2 Answers2

0

Try setting your custom headers in your application.rb file.

config.action_dispatch.default_headers = {
    'Access-Control-Allow-Origin' => 'YOUR_URL',
    'Access-Control-Request-Method' => %w{GET POST OPTIONS}.join(",")
  } 

In your app/controllers/api/v1/application_controller.rb file set your headers like so

before_filter :allow_cross_domain

def allow_cross_domain
    headers['Access-Control-Allow-Origin'] = '*' 
    headers['Access-Control-Expose-Headers'] = 'ETag'
    headers['Access-Control-Allow-Methods'] = 'GET, POST, PATCH, PUT, DELETE, OPTIONS, HEAD'
    headers['Access-Control-Allow-Headers'] = '*,x-requested-with,Content-Type,If-Modified-Since,If-None-Match'
    headers['Access-Control-Max-Age'] = '86400'
end 

Finally inside of your app/controllers/api/v1/controller_your_are_accessing_from_browser.rb call:

before_filter :allow_cross_domain 

Check out 3.8 Configuring Action Dispatch in the rails guide. Also check the console logs in your browser to see the errors you are getting from the above request.

coletrain
  • 2,809
  • 35
  • 43
  • I've tryed that just now. I set up default headers in `application.rb` file, and I have added them just as I have them in `#allow_cross_domain`. Still no luck. – antonpot Nov 25 '15 at 18:34
  • @antonpot I have updated my answer above. Also I have added generic headers to the allow_cross_domain method for testing purposes – coletrain Nov 25 '15 at 19:20
  • Thanks for taking the time. I'm not sure what do you want me to do with `before_filter :allow_cross_domain`. Where do you want me to put it? What I have tried is, to config default headers in `application.rb` and modified `application_controller.rb` as you suggested. It saddly still returnes the same error. – antonpot Nov 25 '15 at 19:59
  • @antonpot I have updated my answer above in which shows you where to add the following to your current code base. If the above does not work we can simply chat via stackoverflow to prevent long comments. – coletrain Nov 25 '15 at 20:21
  • It hasn't worked with this solution either. I decided to use query params instead. – antonpot Nov 27 '15 at 09:20
0

You could try adding :options to your routes:

namespace :api, as: false do
  namespace :v1, as: false do
    resources :responses, only: [:index, :new, :create] 
    match 'surveys' => "surveys#index", via: [:get, :options] 
    resources :surveys, only: [:index, :create, :show]
  end
end
ehoffmann
  • 788
  • 1
  • 7
  • 15
  • @antonpot did you try the solution above? – ehoffmann Nov 25 '15 at 20:26
  • Thank you for taking a look. The solution works, but it's not idile, and I'm not sure I'll be able to use it. It still doesn't cooperate with my authentincation, because headers are changed to `'HTTP_X_USER_EMAIL'` as explained [here](http://stackoverflow.com/questions/2311883/authorization-header-in-ruby-on-rails-accessed-with-key-http-authorization-inste). Besides, I still have many calls where I need to add headers, so I'd have to match OPTIONS for each of them. – antonpot Nov 26 '15 at 11:31
  • Yes you have to match `OPTIONS` for each of them or use [rackcors](https://github.com/cyu/rack-cors) instead. You could also take a look [here](https://gist.github.com/dhoelzgen/cd7126b8652229d32eb4). – ehoffmann Nov 26 '15 at 12:10
  • Thanks. I wasn't familiar with rack-cors, and it seems I the gem might come in usefull. :) – antonpot Nov 26 '15 at 12:16
  • @antonpot please upvote or mark the answer as correct if it helpful. – ehoffmann Dec 01 '15 at 15:34