2014-02-24 47 views
29

我试图在rails 4中构建一个API,并且在使用respond_to :json并尝试访问html版本时,导致rails返回500错误而不是406的问题。Rails 4 - 只响应JSON而不是HTML

这里有一个例子控制器,展示了这个问题:

class PostsController < ApplicationController 
    respond_to :json 

    def index 
    @posts = Post.all 
    end 
end 

我也有一个index JBuilder的视图通过JSON访问时的作品。如果我尝试访问没有JSON扩展名的路由,它会尝试加载HTML模板(不存在)并返回500错误,而不是仅呈现JSON或返回406错误。

这可能是什么原因造成的?欢呼任何帮助。

+0

可能重复:http://stackoverflow.com/questions/14579774/respond-to-only-json-in-rails?rq=1 – Josh

+0

我没有看到这一点,但我想知道为什么它不't只使用'respond_to:json'设置 –

+0

'respond_to:json'和'respond_with @ posts'正确响应* HTTP/1.1 406 Not Acceptable *在生产中给我。在开发中,你会得到一个“HTTP/1.1 500内部服务器错误”和一个“ActionController :: UnknownFormat” – Leito

回答

4

由于您使用的是before_filter,如果未定义格式的请求,您将有406不可接受。

实施例:

class SomeController < ApplicationController 
    respond_to :json 


    def show 
    @record = Record.find params[:id] 

    respond_with @record 
    end 
end 

另一种方法是添加一个的before_filter检查的格式并相应地作出反应。

例子:

class ApplicationController < ActionController::Base 
    before_filter :check_format 


    def check_format 
    render :nothing => true, :status => 406 unless params[:format] == 'json' 
    end 
end 

但我认为,你可以做到这一点:

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

进一步的信息: http://guides.rubyonrails.org/layouts_and_rendering.html

+1

我有这个问题是'respond_to:json'仍然允许html响应通过。无论请求的格式如何,我都希望所有响应都是JSON。 –

+0

您是否在视图上创建了json? –

+0

'params [:format] =='json''是不够的。当使用'Accept:application/json'头进行请求时,params [:format]是空的,但Rails仍然以JSON响应。 – ciastek

24

为了避免加载不存在的HTML模板,设置默认资源类型为config/routes.rb中的JSON:

resources :posts, :defaults => { :format => :json } 
+4

这并没有提供这个问题所暗示的约束条件。这个想法是,如果没有指定.json格式,轨道将不会在路线上匹配,并沿层次继续。 – Volte

27

我相信,有2个部分的位置:
1)仅适用于JSON 请求在轨
2)仅适用于JSON 回复在轨

1)配置应用程序控制器,以确保JSON请求

# app/controller/application_controller.rb 
before_action :ensure_json_request 

def ensure_json_request 
    return if request.format == :json 
    render :nothing => true, :status => 406 
end 

2)配置你的Rails API的路线,以确保JSON响应只有

# config/routes.rb 
MyApp::Application.routes.draw do 
    namespace :api, constraints: { format: 'json' } do 
    namespace :v1 do 
     resources :posts 
    end 
    end 
end 
+3

而不是'params [:format] ==“json”|| request.headers [“Accept”] =〜/ json /'你可以使用'request.format.symbol ==:json'。 – ciastek

+1

好的电话。更新为'request.format ==:json'作为'symbol'并不是每个这个[请求格式问题]都需要的(http:// stackoverflow。com/questions/15227145/get-content-type-of-request#answer-33768811) – csi

+1

而不是'render:nothing => true,:status => 406'你可以使用'head:not_acceptable' –

1

您可以通过过滤器,明确提出要求,以JSON之前有设置。

request.format = :json

2

你可以试试这个,因为我也面临这样的问题,现在它是通过使用该解决方案来解决。

class PostsController < ApplicationController 
    respond_to :json 

    def index 
    @posts = Post.all 
    render json: @posts 
    end 
end 
0
当您在JSON尝试响应

是怎么一回事,因为你只需要一些属性,我用这个

@my_model=Model.select(:attributeN, :attributeN......, attributeN) 
respond_to do |format| 
    format.json { 
    render json: @my_model 
    } 
end 
0

我建议你去尝试gem 'active_model_serializers'。它真的很棒,并保持清洁。

的ApplicationController:

class ApplicationController < ActionController::Base 
    protect_from_forgery with: :exception, if: Proc.new { |c| c.request.format != 'application/json' } 
    protect_from_forgery with: :null_session, if: Proc.new { |c| c.request.format == 'application/json' } 
end 

途径:

namespace :api, defaults: { format: :json } do 
    resource :posts 
end 

帖子控制器:

def index 
    render json: Post.all 
end 
11

在导轨4,您需要传递一个lambda来强制执行路由上的约束。

不幸的是,这是行不通的,因为它仍然会尝试投放(或者试图成为了)的HTML模板,因为该格式是一个可选的参数:

resources :posts, constraints: { format: 'json' } 

这不工作(使用拉姆达):

resources :posts, constraints: lambda { |req| req.format == :json } 

请参阅this section of the Rails guide中的第二个(最终)注释。

+0

这不会似乎与'范围'工作,但是'默认:{格式:'json'}'工作。 –

1

constraints不适用于POST请求,然后我尝试defaults它适用于所有。

namespace :api, :defaults => { :format => 'json' } do 
    namespace :v1 do 
     resources :users do 
     collection do 
      get 'profile' 
     end 
     end 
     post 'signup' => 'users#create' 
     post 'login' => 'user_sessions#create' 
    end 
end 
相关问题