head、headers 與 response


ender 與 redirect_to 中談過,如果不想回應任何內容給客戶端,可以使用:

render :nothing => true

實際上也不是沒有回應任何內容,而是瀏覽器上看不到任何內容而已,瀏覽器還是會收到以下的標頭訊息:

Content-Type       text/html; charset=utf-8
X-Ua-Compatible    IE=Edge
Etag               "7215ee9c7d9dc229d2921a40e899ec5f"
Cache-Control      max-age=0, private, must-revalidate
X-Runtime          0.968123
Content-Length     1
Server             WEBrick/1.3.1 (Ruby/1.9.2/2011-07-09)
Date               Fri, 30 Dec 2011 02:32:57 GMT
Connection         Keep-Alive

如果你想明確地指定回應某些標頭訊息,可以使用head方法,例如:

def create
    @page = Page.new(params[:page])
    @page.save
    head :created, :location => bookmark_path(@page)
end

瀏覽器會收到狀態碼201 Created以及標頭訊息:

Location           http://localhost:3000/bookmarks/11
Content-Type       text/html; charset=utf-8
X-Ua-Compatible    IE=Edge
Etag               "7215ee9c7d9dc229d2921a40e899ec5f"
Cache-Control      max-age=0, private, must-revalidate
X-Runtime          0.685457
Content-Length     1
Server             WEBrick/1.3.1 (Ruby/1.9.2/2011-07-09)
Date               Fri, 30 Dec 2011 02:49:57 GMT
Connection         Keep-Alive
Set-Cookie         _bookmark_session=BAh7B0kiD3Nlc3Npb25faWQGOgZFRkkiJTlj...; path=/; HttpOnly

可以針對不同的情況予以回應:

return head(:method_not_allowed) unless request.post?
return head(:bad_request) unless valid_request?
render

如果你查看head方法的原始碼,可以看到使用了headers方法,並將回應本體設定為空白字串:

def head(status, options = {})
    options, status = status, nil if status.is_a?(Hash)
    status ||= options.delete(:status) || :ok
    location = options.delete(:location)

    options.each do |key, value|
       headers[key.to_s.dasherize.split('-').each { |v| v[0] = v[0].chr.upcase }.join('-')] = value.to_s
    end

    self.status = status
    self.location = url_for(location) if location
    self.content_type = Mime[formats.first] if formats
    self.response_body = " "
end

headers方法的傳回物件為Hash實例,它與response.headers傳回的是同一實例,用來設定回應標頭:

headers["Content-Type"] = "text/html; charset=big5"

response方法傳回的物件為ActionDispatch::Request實例,通常由Rails作處理,您幾乎不需要設定這個物件,因此如設定回應標頭的動作,建議使用headers方法,而不是使用response.headers方法。不過在必要時,你還是可以藉由response傳回物件的各個方法來處理回應,像是response.body(必須在render之後,才可以取得或改變回應本體)、response.charset、response.content_type等方法。

要注意的是,headers是用來取得或設定回應標頭,如果想取得請求標頭,必須使用request.headers方法。