Skip to content

Commit

Permalink
Add a header that tells Internet Explorer (all versions) to use the b…
Browse files Browse the repository at this point in the history
…est available standards support. This ensures that IE doesn't go into quirks mode because it has been blacklisted by too many users pressing the incompatible button. It also tells IE to use the ChromeFrame renderer, if the user has installed the plugin.

This guarantees that the best available standards support will be used on the client.
  • Loading branch information
wycats committed Jul 28, 2010
1 parent e17e08e commit 123eb25
Show file tree
Hide file tree
Showing 6 changed files with 7 additions and 3 deletions.
1 change: 1 addition & 0 deletions actionpack/lib/action_dispatch.rb
Expand Up @@ -47,6 +47,7 @@ module ActionDispatch
end

autoload_under 'middleware' do
autoload :BestStandardsSupport
autoload :Callbacks
autoload :Cookies
autoload :Flash
Expand Down
3 changes: 2 additions & 1 deletion actionpack/lib/action_dispatch/railtie.rb
Expand Up @@ -7,10 +7,11 @@ class Railtie < Rails::Railtie
config.action_dispatch.x_sendfile_header = ""
config.action_dispatch.ip_spoofing_check = true
config.action_dispatch.show_exceptions = true
config.action_dispatch.best_standards_support = true

# Prepare dispatcher callbacks and run 'prepare' callbacks
initializer "action_dispatch.prepare_dispatcher" do |app|
ActionDispatch::Callbacks.to_prepare { app.routes_reloader.execute_if_updated }
end
end
end
end
1 change: 1 addition & 0 deletions railties/lib/rails/application.rb
Expand Up @@ -205,6 +205,7 @@ def default_middleware_stack
middleware.use ::ActionDispatch::ParamsParser
middleware.use ::Rack::MethodOverride
middleware.use ::ActionDispatch::Head
middleware.use ::ActionDispatch::BestStandardsSupport if config.action_dispatch.best_standards_support
end
end

Expand Down
2 changes: 1 addition & 1 deletion railties/lib/rails/commands.rb
Expand Up @@ -70,4 +70,4 @@
All commands can be run with -h for more information.
EOT
end
end
2 changes: 1 addition & 1 deletion railties/lib/rails/engine/configuration.rb
Expand Up @@ -50,4 +50,4 @@ def autoload_paths
end
end
end
end
end
1 change: 1 addition & 0 deletions railties/test/application/routing_test.rb
Expand Up @@ -40,6 +40,7 @@ def index

get '/foo'
assert_equal 'foo', last_response.body
assert_equal "IE=Edge,chrome=1", last_response.headers["X-UA-Compatible"]
end

test "simple controller with helper" do
Expand Down

28 comments on commit 123eb25

@wycats
Copy link
Member Author

@wycats wycats commented on 123eb25 Jul 28, 2010

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this can be turned off with config.action_dispatch.best_standards_support = false

@mislav
Copy link
Member

@mislav mislav commented on 123eb25 Jul 28, 2010

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strange seeing something IE-specific to go in Rails.

@joeljunstrom
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreeing with Mislav here, even tho it's is possible to override it with the config, seeing rails sending IE specific headers by default is in my book not what a framework should do. Is the incompatible button really a proven problem for websites? And in that case knowing how to avoid it by sending specific headers should really be in the concern of the application author(s). For those unlucky people that rely on quirks mode / forcing older rendering engines for legacy reasons this might lead to confusion. And for the rest of us just use a decent doctype, say doctype html.

@drogus
Copy link
Member

@drogus drogus commented on 123eb25 Jul 28, 2010

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's a bad move. Why should Rails not help with IE weirdness?

When javascript helpers were provided by Rails would you also want to handle any IE cases by yourself? ;-)

@dmathieu
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with drogus. Seeing something specific to IE here seems fine to me.

@Wijnand
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer a helper tag that inserts the equivalent metatag for IE < 9

@mislav
Copy link
Member

@mislav mislav commented on 123eb25 Jul 28, 2010

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re: JavaScript frameworks: Prototype and jQuery are separate projects which are developed and released independently.

I don't claim this is a bad move, it just feels weird to me and I wanted to know what others think. As long as the preference is put into new apps by the generator, with a comment on what it does and how to turn it off, it's fine by me. Client-side magic should, if necessary, at least make itself apparent to the developer.

@defkode
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is cool, but I think it should be turned off by default. I wouldn't call ChromeFrame "best practice". I don't know any non-dev person that install such addons to IE.

@fpauser
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To me it feels 'bloaty' to have ie-specific stuff in rails-core. Could'nt this be a plugable rack-filter or a rails-plugin?

@josh
Copy link
Contributor

@josh josh commented on 123eb25 Jul 28, 2010

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

script/plugin install git://github.com/rails/ie_standards.git

@tcocca
Copy link

@tcocca tcocca commented on 123eb25 Jul 28, 2010

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Josh, is that a private repo? I don't seem to have access to it. Or is that just a thought?

@dmathieu
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tcocca that was a suggestion. This repo does not exists (yet?)

@davout
Copy link

@davout davout commented on 123eb25 Jul 28, 2010

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A plugin sounds much better in my opinion.
Or at least something disabled by default with a commented-out line in the template configuration file to enable it.

@fpauser
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the '_snowman'-hack should also go into this 'ie_standards' plugin. The plugin would document all these ie-specific things in detail so no one should be surprised by strange ie-specific headers or a '_snowman'-param (aka 'Principle of Least Surprise').

@nateware
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with josh and mislav - putting IE hacks into Rails is the opposite direction it has been moving. If Rails is going to have IE hacks in core, then browser-independent functionality like pagination and ssl_requirement should move back into core. Plugin please.

@wycats
Copy link
Member Author

@wycats wycats commented on 123eb25 Jul 28, 2010

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are actually quite a few hacks already in Rails for Internet Explorer. I think most users expect Rails to make Internet Explorer behave as expected, without having to understand the problems that give rise to the issues in question, as long as we don't resort to sniffing IE in particular.

IE hacks already in Rails:

  • Rails modifies original_filename on uploaded file objects to hack around a bug where Internet Explorer was giving full Windows file paths
  • Files sent via send_file set Content-Type to application/octet-stream to work around quirks in IE involving SSL
  • Files sent via send_file set Cache-Control to "private" because the default "no-cache" broke the open/save dialog
  • HTTP authentication handles a case in IE where the URL sent in the Authorization header is absolute (containing http:// etc)

We also handle (by default) a quirk in some versions of Safari in which it sends a trailing null character at the end of params, and another in which it does not correctly handle an empty body (so we send " " for render :text => :none)

Rails has always handled weird Internet Explorer quirks, because (like when using a JavaScript library), Rails users don't even want to know that these problems exist. If they had to wait until the first time a user reported a bug with a file download, research it, and find the Rails plugin that patched the cache headers, they would be (correctly) quite frustrated.

Again, the line that I personally draw is that we don't fix any user-agent bugs that absolutely require sniffing. Otherwise, making the vast majority of both Rails developers and users of applications written in Rails blissfully unaware of Internet Explorer quirks is what we're here for.

@slightlyoff
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nateware, mislav: So this isn't so much a "hack" as the supported way in IE to trigger a given rendering mode which, thanks to history, is orthogonal from doctype depending on the zone...a change in behavior you almost never want. All this change does is set a designer up for success by setting things into the most standards compliant mode available regardless of zone. As for Chrome Frame, I can tell you with some authority that many users are installing it and the rate is increasing, but I'm biased as I work on the project. That said, on many Google properties, Chrome Frame is providing orders of magnitude improvements in performance over IE and is allowing apps to send better (more standards compliant even than IE8) code.

@rickmzp
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree with this being called a "hack." It's just a header that sets a new preferred expectation for IE dealing with Rails applications. I think it's extremely beneficial as a default and too easy to turn off by those who would actually not want this functionality.

@Xac
Copy link

@Xac Xac commented on 123eb25 Jul 28, 2010

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this confuse developers that are testing in IE with chrome frame installed (but don't know it's active)? I'm not very familiar with CF but I assume if you need to send a header to use it if it's installed, it wouldn't be used by default during normal page loading. Will future Rails developers doing cross browser testing need to know to manually disable this if they want to test with IE's default rendering engine?

@wycats
Copy link
Member Author

@wycats wycats commented on 123eb25 Jul 28, 2010

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Xac good point. We should have this off in development mode by default :)

@mislav
Copy link
Member

@mislav mislav commented on 123eb25 Jul 28, 2010

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I never called this a "hack"—others did. These are nothing more than mere parameters that trigger certain features in IE.

@wycats: What you summarized is all HTTP-level, and we all know that Rails gracefully abstracts away its details (and quirks) from the developer. This change is a little different because it affects the rendering side of a browser. But I generally agree with arguments in defense of this change, and with Xac in his point against.

@mitchellh
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wycats Discussing this with a coworker, we think this would be a good idea to add to the test mode as well, for those who run continuous integration builds which run selenium clients against the various browsers. Of course in these environments chrome frame probably shouldn't be installed, but it would be a good default to disable it in test mode, I believe.

@rickmzp
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"We should have this off in development mode by default" +1

@paulirish
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IE Compatibility mode can kick in for a few reasons:

  1. Sites that run inside an intranet (except localhost and the loopback address)
  2. Users that have opted-in to the Compatibility View List and your site incorrectly flagged
  3. Users that have clicked the broken-page icon accidentally (directly next to Refresh and Stop). it affects the whole domain.
  4. Some other content on the site caused IE8/9's renderer to crash and fall back to the old renderer;
  5. A user or group policy setting made all sites to be viewed in compat mode.

In all cases, the user will get the Trident equivalent of IE7 (but the JScript version of IE8 or IE9) -- For example localStorage is present in IE8 Compat Mode, but you still get the CSS bugs of IE7. These pseudo- browser versions are likely to be edge case bugs QA wouldn't normally catch.

The X-UA-Compatible header forces the latest mode, resulting in the best possible experience for the user, using the fastest (and best) rendering engine available. As Steve Souders likes to recommend, it's "fast by default".

@Wijnand
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"off in development mode" -1

When I am going through the hell of fixing IE rendering bugs I am working in development mode. I want pages to look exactly the same when in production.
I don't want to add a IE hack to find out it creates another bug in production.

@jasoncodes
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"off in development mode" -1

The rule of least surprise.

@dlee
Copy link
Contributor

@dlee dlee commented on 123eb25 Jul 28, 2010

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with Wijnand that rendering should be consistent between development and production.

A developer would expect rails to trigger ChromeFrame when installed, and non-quirks-mode otherwise. We don't want a developer to be confused because IE6 is not using ChromeFrame in development even though it's installed. We also don't want IE6 using quirks mode in development but non-quirks-mode in production.

@rickmzp
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dlee, that's a good point. I was thinking only of triggering ChromeFrame. With chrome=1 I think it more sense until you hit an issue where the developer is doing some IE specific magic via a user-agent check that doesn't account for ChromeFrame and it gets triggered when it shouldn't. Regarding IE=edge, I agree that behavior should not differ between dev and production.

Please sign in to comment.