Brian Roisentul
Brian Roisentul

Reputation: 4750

Getting Response code = 406. Response message = Not Acceptable error when parsing JSON

I've built an Rails app that is called by another one (Rails as well), using ActiveResource.

The situation is that I expose the info from the first app as JSON as follows:

App 1:

class PromotionsController < ApplicationController

  # GET /promotions
  # GET /promotions.xml
  def index
    @promotions = Promotion.all

    respond_to do |format|
      format.json  { render :json => @promotions }
    end
  end
end

And I receive it on the App 2, through an ActiveResource model, as follows:

class Promotion < ActiveResource::Base
  self.site = "app_1_url"
  self.element_name = "promotion"
end

When I want to read the data as JSON, doing the following, I get 406 Not Acceptable error message:

class PromotionsController < ApplicationController
  # GET /promotions
  # GET /promotions.xml
  def index
    @promotions = Promotion.all

    respond_to do |format|
      format.json { render :json => @promotions }
    end
  end
end

But, when I try to parse the info as XML (doing the same as the code shown above, except for changing "json" for "xml" everywhere) it works.

Any ideas?

Thanks.

Upvotes: 0

Views: 2924

Answers (2)

Dmitry Matveev
Dmitry Matveev

Reputation: 5376

In addition to CoryDanielson's answer.

Even when my application is using :xml format (which is as Cory noted set by default) I still had to include

self.format = :xml

in order to fix 406 error.

Upvotes: 1

Cory Danielson
Cory Danielson

Reputation: 14501

You have to change the format to JSON for the application that is receiving the data (App 2)

class Promotion < ActiveResource::Base
  #your code
  self.format = :json #XML is default
end

Here's how I went about figuring that out (for any googlers that end up here)

Step 1: researching the error code

Per Wikipedia:
406 Not Acceptable
The requested resource is only capable of generating content not acceptable according to the Accept headers sent in the request.
(Basically, the data you received is in a different language than you wanted)


Step 2: diagnosing the problem

Because a 400 level error code is a Client error code, I determined that the error must have been with App 2 (in this case, app 2 is the client requesting data from app 1). I saw that you were doing some formatting for JSON in app 1 and looked for similar code in App 2 and didn't see it, so I assumed the error was with App 2 having a different Content-Type header than App 1. The Content-Type basically tells applications/browsers what language each is speaking when they send/receive data. The value that you store in the Content-Type is the MIME Type and there are lots of them.

You said that the XML type worked but JSON wasn't, so I checked the rails ActiveResource API (used in App 2) looking for some headers or content-type method and saw a format method and property which matches what you used in the Action Controller for App 1. I also saw that the format is defaulted to XML if it is not supplied.

#Returns the current format, default is ActiveResource::Formats::XmlFormat.
def format
   read_inheritable_attribute(:format) || ActiveResource::Formats[:xml]
end

Step 3: fixin thangz

add this line to the class in app 2:

self.format = :json

I'm sure you could adjust the Content-Type header with the headers method as well, but the API didn't have sample code displaying how to do that. Adjusting the Content-Type with the headers method would kind of just be the 'harder' way to do it, and because adjusting the Content-Type is so common rails created format to streamline the process. I saw that the API has an example of adjusting the format attribute of the class that conveniently uses json and read that the format method/property "Sets the format that attributes are sent and received in from a mime type reference" aka sets the Content-Type HTTP Header.

Upvotes: 5

Related Questions