2014-02-24 53 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 
相關問題