Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #7623 (reopened defect)

Opened 1 year ago

Last modified 3 months ago

[BUG] respond_to problems with safari (and maybe other browsers)

Reported by: Bounga Assigned to: core
Priority: normal Milestone: 2.1
Component: ActionPack Version: edge
Severity: major Keywords: respond_to safari
Cc: tomafro, ernesto.jimenez

Description

I was playing with REST and respond_to and found a bug. I can't tell if it's a safari or rails bugs but maybe you can tell me more about the issue :

# projects_controller.rb

def close

respond_to do |format|

if Project.find(params[:id]).update_attribute(:closed, true)

flash[:notice] = "Project was successfully closed." format.xml { head :ok }

else

flash[:notice] = "Error while closing project." format.xml { head 500 }

end format.html { redirect_to projects_url }

end

end

# routes.rb

map.resources :projects, :member => { :close => :post } map.resources :projects do |projects|

projects.resources :iterations

end

# url : http://localhost:3000/projects/1;close This page contains the following errors:

error on line 1 at column 1: Extra content at the end of the document Below is a rendering of the page up to the first error.

# So it doesn't work in safari but in firefox it's ok, the page is rendered # I can make it work in safari too if I change the controller for :

def close

respond_to do |format|

if Project.find(params[:id]).update_attribute(:closed, true)

flash[:notice] = "Project was successfully closed." format.html { redirect_to projects_url } format.xml { head :ok }

else

flash[:notice] = "Error while closing project." format.html { redirect_to projects_url } format.xml { head 500 }

end

end

end

# But it's not DRY anymore

Change History

02/27/07 13:35:26 changed by tomafro

  • cc set to tomafro.
  • status changed from new to closed.
  • resolution set to invalid.

You need to be more careful in the order you specify formats in your respond_to block. In the first example xml is above html, in the second it's the opposite. The actual response type chosen is based on the order you specify these formats together with the order the formats are listed in the accepts header sent by each browser, firefox and safari presumably sending different lists, hence the 'bug'.

02/13/08 20:43:45 changed by arthurgeek

  • status changed from closed to reopened.
  • resolution deleted.
  • milestone changed from 1.x to 2.1.

And what about using the params[:format]?

Hey, I'm passing the format, why not use it?

I'm expliciting telling rails to render using the requested format (passed in url), and want it that way!

02/13/08 22:30:35 changed by ernesto.jimenez

  • status changed from reopened to closed.
  • resolution set to invalid.

@mime_type_priority = Array(Mime::Type.lookup_by_extension(@request.parameters[:format]) @request.accepts)

It works like you say

class RespondToController < ActionController::Base
  def html_xml_or_rss
    respond_to do |type|
      type.html { render :text => "HTML"    }
      type.xml  { render :text => "XML"     }
      type.rss  { render :text => "RSS"     }
      type.all  { render :text => "Nothing" }
    end
    #...
  end
end


class MimeControllerTest < Test::Unit::TestCase
  def test_forced_format
    get :html_xml_or_rss
    assert_equal "HTML", @response.body

    get :html_xml_or_rss, :format => "html"
    assert_equal "HTML", @response.body

    get :html_xml_or_rss, :format => "xml"
    assert_equal "XML", @response.body

    get :html_xml_or_rss, :format => "rss"
    assert_equal "RSS", @response.body
  end
end

Consither attaching a failing test case if you are willing to reopen the ticket.

02/14/08 11:39:22 changed by arthurgeek

Ok, before reopen the ticket let explain it better.

For explanation:

Safari sends the header HTTP ACCEPT = "/". This way it will accept anything the server gives it. Which on the surface seems just fine, but rails does not work that way. If the request (from the browser) does not specify a mime type in the url, then rails tries to figure out what the browser wants based on the accepts header. In this case the browser will take anything, so rails gave it the first thing on the list.

I don't think it's completely a Rails bug. And it's not a Safari bug too. But, I think the implicit format needs to be html. And, show the other formats when requesting it. Actually, it's that way when we aren't using respond_to, right? It loads the erb (html) file.

At least I think this should be on documentation, since took so many times to figure out that.

Ok, enough talking, let's code.

class RespondToController < ActionController::Base
  def html_xml_or_rss
    respond_to do |type|
      type.xml  { render :text => "XML"     }
      type.html { render :text => "HTML"    }
      type.rss  { render :text => "RSS"     }
      type.all  { render :text => "Nothing" }
    end
    #...
  end
end


class MimeControllerTest < Test::Unit::TestCase
  def test_forced_format
    get :html_xml_or_rss
    assert_equal "HTML", @response.body

    get :html_xml_or_rss, :format => "html"
    assert_equal "HTML", @response.body

    get :html_xml_or_rss, :format => "xml"
    assert_equal "XML", @response.body

    get :html_xml_or_rss, :format => "rss"
    assert_equal "RSS", @response.body
  end
end

This test pass (using ruby), but while on Safari, it's not what happens. I got: "XML" as response.body!

02/17/08 04:38:57 changed by arthurgeek

  • cc changed from tomafro to tomafro, ernesto.jimenez.
  • status changed from closed to reopened.
  • resolution deleted.

Reopening this for better attention.