-
Notifications
You must be signed in to change notification settings - Fork 127
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Deface/JRuby closes head tag leaving head elements within the body #84
Comments
@swrobel @BDQ This may not be related to the cross-referenced bug. This will happen if you're streaming responses out with Deface enabled. It will try parsing incomplete and thereby invalid markup and insert shit left and right. Found this out preparing my talk for SpreeConf actually. To verify, disable streaming temporarily or just launch with a server that doesn't support chunked responses like the vendored WEBrick. Cheers |
@jumph4x @BDQ I just tried starting my jruby server with @jumph4x can you provide more info about what exactly your scenario is? Are you talking about running jruby? I'm using streaming successfully w/ MRI & unicorn without this deface issue. It only crops up on jruby and doesn't seem to be dependent on the webserver (puma & webrick both exhibit it) @BDQ have you been able to repro? I'm running a super stock setup here and seeing this, so I'm hoping you've been able to test on your end. |
@swrobel @BDQ I lied. The symptoms will persist even with a non-streaming server. It will curb all benefits of streaming, but rails will still try to flush the buffer (meaning a premature pass through libxml), only difference is that it will be held at WEBrick until the full response is received. I reproduced in development. I'd consider this an app-level concern. I stream in production and I precompile deface. See recent fix. |
Interesting, so I'm not crazy! @jumph4x if I understand correctly, the temporary solution is to precompile deface when using jruby until this is resolved? |
(I wasn't using Jruby) Basically, the way things stand, I don't think there is any say we have in how libxml treats chunked responses. And they leave the domain of the app before ever being combined in some circumstances (your and my production, it seems). So while I accept invalid markup for development environment with deface compiling into memory (default), I certainly precompile all deface views in production and have no problems. So yes? 🎉 |
Thinking about it I don't see how Deface could affect Streaming responses (or vice versa). Deface hooks into, and "overrides" the view at compile time - i.e. when file view is pulled from disk and just before it's passed to Erubis for compilation. So the Deface changes are made before any of the streaming logic could possible take effect, ergo it's not related. @swrobel - I'm sure I'll be able to reproduce, and I have an inkling I know where the issue is. I'm just swamped with SpreeConf prep right now and won't get to it for a while. I appreciate your patience. |
@BDQ no problem, just wanted to make sure I wasn't leading you on a wild goose chase |
@BDQ and @swrobel No pressure whatsoever, I know we're all busy, but going to leave this here for when you find a moment. Here is what I think is happening.
@BDQ 's logic would be sound if all of this somehow only affected ActionView::Template.render at https://github.com/spree/deface/blob/master/lib/deface/action_view_extensions.rb#L25 but it actually affects template instantiation, which needless to say, does NOT just occur at compile time. Perhaps I am missing something, but let's wait until the SpreeConf craze is over and we'll sort it. |
@jumph4x - Thanks for all the details, the render method on action_view_extensions.rb#L25 is a very edge feature (that we only ever used on StoreWorks) normally in production has no effect. As as test you could comment that out and see if the issue persists (as I expect it would). This method can probably be dropped now. |
What I meant to articulate is that it is the #initialize not the #render that is ultimately responsible for this, if you re-read just ignore the last 2 paragraphs. I should type less... I just cause confusion 😆 Tested the things I traced above: commented out the initialization alias chain in https://github.com/spree/deface/blob/master/lib/deface/action_view_extensions.rb#L2-18. Output: <!DOCTYPE html>
<html>
<head>
<link href="assets0.fcpstores.com" rel="dns-prefetch" />
...
</head>
<body>
... Correct output. Put the #initialize chain back, but commented out the render one as in https://github.com/spree/deface/blob/master/lib/deface/action_view_extensions.rb#L20-38: <!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<link href="assets0.fcpstores.com" rel="dns-prefetch" />
... Specifically, notice the So I still hold this is due to the way Deface forced ActionView:: Template to instantiate, thereby causing the Applicator class to apply HTML parsing by way of Nokogiri/libxml. |
For anyone looking to test this one for themselves:
|
@jumph4x - this is beginning to make sense. You do have overrides defined for the layout in question? Deface (or more specifically the Applicator) doesn't pass the source through Nokogiri unless there's overrides defined for it. https://github.com/spree/deface/blob/master/lib/deface/applicator.rb#L13 |
Yup, all default Spree installations do, assuming we're all using and/or overriding spree_application.html.erb :) [1] pry(main)> Rails.application.config.deface.overrides
=> #<Deface::Environment::Overrides:0x00000006d1f410
@all=
{:"spree/layouts/spree_application"=>
{"add_analytics_header"=>
#<Deface::Override:0x00000007c78628
@args=
{:virtual_path=>"spree/layouts/spree_application",
:name=>"add_analytics_header",
:insert_bottom=>"head",
:partial=>"spree/analytics/header",
:original=>"6f23c8af6e863d0499835c00b3f2763cb98e1d75",
:updated_at=>1368609774.9760637,
:railtie_class=>"Spree::Dash::Engine"}>}, (: |
Per @jumph4x's advice, I tried precompiling deface under jruby. Thanks to Denis & @BDQ for walking me through the finer points of deface @ spreeconf. It seems that precompilation does not solve this, so streaming is definitely not at fault under jruby. See below for code from <!DOCTYPE html >
<!--[if lt IE 7 ]> <html class="ie ie6" lang="<%= I18n.locale %>"> <![endif]--><!--[if IE 7 ]> <html class="ie ie7" lang="<%= I18n.locale %>"> <![endif]--><!--[if IE 8 ]> <html class="ie ie8" lang="<%= I18n.locale %>"> <![endif]--><!--[if IE 9 ]> <html class="ie ie9" lang="<%= I18n.locale %>"> <![endif]--><!--[if gt IE 9]><!--><html lang="<%= I18n.locale %>"><!--<![endif]-->
<head data-hook="inside_head">
<% if Spree::Dash::Config.configured? %>
<script id="analytics" type="text/javascript">
var jirafe= <%= raw analytics_tags.to_json %>;
(function(){
var d=document,g=d.createElement('script'),s=d.getElementsByTagName('script')[0];
g.type='text/javascript',g.defer=g.async=true;g.src=d.location.protocol+'//c.jirafe.com/jirafe.js';
s.parentNode.insertBefore(g, s);
})();
</script>
<% else %>
<!-- Spree Analytics has not been initialized correctly -->
<% end %></head><body><%= render :partial => 'spree/shared/head' %> |
Looks like this is probably something to do with either JRuby or parsing logic branching in libxml itself, as @BDQ mentioned. The only last idea I have is to try and remove conditional IE |
@BDQ as promised, here's my Gemfile for jruby testing: https://gist.github.com/swrobel/7b43e4ade4db9567f5a7 |
As this appears to be caused by a "bug" in libxml 2.9, and has been worked around in Nokogiri 1.6.0-rc1, any chance of getting the Nokogiri version dependency updated in the gemspec? |
@mrbanzai I'm pretty sure jruby doesn't use libxml because java has xml parsing builtin... |
@swrobel Ah, I may be hijacking an issue then; my apologies. I'm seeing the same symptoms with MRI using Nokogiri 1.5.9 / libxml 2.9 as mentioned in spree/spree#2633 (referenced by the description). I'll create a separate issue regarding the dependency version, if necessary. |
I did try bumping to nokogiri to 1.6.0.rc1 when it was released but as there's no jruby version the bundle install fails when using jruby. It looks like whatever fix that's in 1.6.0.rc1 is not needed on jruby so they are in no rush to release a java version of it until it's final. I'm open to suggestions (and especially pull requests) that allow different dependencies per platform (I did a quick google and it doesn't appear to be trivial). |
@swrobel - I've figured out what's going on here: So layouts/spree_application.html.erb has the following markup: <head data-hook="inside_head">
<%= render :partial => 'spree/shared/head' %>
</head> Deface temporarily converts this (before passing to Nokogiri) into : <head data-hook="inside_head">
<code erb-loud> render :partial => 'spree/shared/head' </code>
</head> libxml on MRI is fine with a "code" tag being inside the "head" tag, but on jruby (and whatever java parser it uses) it decides the "code" can't be in "head" and moves into to body. |
A possible workaround would be to:
Deface::Override.new(virtual_path: 'spree/layouts/spree_application',
replace_contents: 'head',
partial: 'spree/shared/head')
Deface::Override.new(virtual_path: 'spree/layouts/spree_application',
remove: "body code:contains('spree/shared/head')") Both are untested. |
About to cross reference something I found that is OS-lib-level, on MRI. |
This changes the ERB template parser to use `<erb>` rather than `<code>` to designate code blocks in a template. For example: <%= render template: 'foo/bar' %> Used to parse as: <code erb-loud> render template: 'foo/bar' </code> But not parses as: <erb erb-loud> render template: 'foo/bar' </erb> This fixes a number of problems that result from using `<code>`: * There may be </code> tags in the original ERB, which would be turned into `%>` (Fixes spree#101) * Any <code> tags in the <head> of a document would be moved to the body, since <code> is a real HTML tag, and isn't allowed in the head. This happens in nokogiri under jRuby or libXML 2.9.0 (Fixes spree#84, Fixes spree#100)
This is similar to the behavior reported in spree/spree#2633
Test this issue with:
Look at the HTML source of the index page or run it through http://validator.w3.org/ to see all of the errors this generates. First few lines of the doc as a sample:
The text was updated successfully, but these errors were encountered: