Why does nginx + memcache corrupt my response body? - ruby-on-rails

I'm caching some web pages in memcache. When I read the page directly from the cache, the page is well formed like this ...
!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"-:-- 0
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
but when I use a browser or curl to read it from nginx (version 0.8.50), it looks like response headers are ending up in the body of the response like this ...
�{
" ETag"'"16bb9f51667d334aa4e7663ca28d308a""X-Runtime177"Content-Type"text/html; charset=utf-8"Content-Length"5428"Set-Cookie""Cache-Control"(private, max-age=0, must-revalidate"4<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
My nginx config is pretty simple ...
set $memcached_key $cookie__app_session$uri;
memcached_pass localhost:11211;
default_type text/html;
error_page 404 502 /fallback$uri;
Does anyone have an idea why the response is corrupt?

Do! Stupid developer problem!
There were two mistakes
(a) I was storing the response header and body in memcache, then adding headers in an nginx rule. Storing only the response body in memcache removed the bulk of the problems
(b) I was storing the response in Ruby's marshal format (the default setting in memcache-client) - reading the contents of memcache using a simple Ruby client was hiding the fact that the format was not directly usable by nginx.
Hope that helps someone sometime!
Chris

Related

Doctype in JSF Mojarra

What Doctype should I use in JSF pages? The other day I'm trying to migrate from Mojarra 2.1.13 to 2.1.18 and it seems that the way the doc types are interpreted changed. In the root template I have following DOC TYPE
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
Do I also have to include this?
<?xml version="1.0"?>
In composites (that use this template) I used to have following doctype
<!DOCTYPE composite PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
But it seems that Mojarra 2.1.18 doesn't really support that. Also I didn't find this in any JSF 2.0 reference, this we used to use in JSF 1.2. If I have this doctype in composite page, it will render composite doctype instead of html that is in the template. In the result, the css styles are messed up.
So what's the correct usage of doctypes in JSF 2.0. Or is this issues with Mojarra? I didn't find any reference regarding this.
I created a JIRA issue for this: http://java.net/jira/browse/JAVASERVERFACES-2820
and it has been closed as this is the expected behavior.
"The composite page is where you actually use the template. So it is the outer most file where you specified a doc type. As such it defines the doc type that will be rendered."
Just specify the doctype in a template and nowhere else
I also migrated Jboss 7.1 to JBoss EAP 6.1
I found not very nice workaround - to insert on each page (not template):
<!DOCTYPE html>
e. g.:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html" template="template.xhtml">
Is there any other way - for doctype to be read from master template?

Passing UTF-8 string to f:viewParam in JSF

I tried to pass UTF-8 String as f:viewParam value but value shown as garbage string, i added EncodingFilter in web.xml for setting UTF-8 to request and response as below
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpServletRequest request = (HttpServletRequest) servletRequest;
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=UTF-8");
and i defined facelet page in this style, but problem not resolved
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<f:metadata>
<f:viewParam name="q" value="#{searchBean.query}"/>
</f:metadata>
.....
</html>
I test this with Myfaces 2.0.5 and Mojarra 2.0.5
Apparently you're using a server configuration which interprets GET query strings using a different character encoding by default. For example Tomcat interprets them as ISO-8859-1 by default. You need to open Tomcat's /conf/server.xml and add URIEncoding attribute to the <Connector> element with a value of UTF-8.
<Connector ... URIEncoding="UTF-8">
That filter is by the way totally unnecessary. Remove it. JSF 2.x on Facelets defaults to UTF-8 at all levels already. Besides, the HttpServletRequest#setCharacterEncoding() doesn't affect GET requests, it affects POST requests only.
See also:
Tomcat HTTP connector configuration reference
Unicode - How to get the characters right?

Avoid multiple DOCTYPE and html tags when using ui:include

we are using several ui:include tags in the "main" page. The page that is to be included looks like this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns=".." xmlns:ui="..." ...>
<ui:fragment rendered="${foo}">
some html code
</ui:fragement>
<ui:fragment rendered="${!foo || bar}">
some more html code
</ui:fragement>
</html>
Using the ui:include for templating results in repeating the DOCTYPE and html tag several times in the source code, which is pretty ugly. (Sure, the user doesn't see, but I'm a fan of tidy html)
However, if I remove the DOCTYPE and html tag from the to-be-included-xhtml, the Faces Servlet throws an exception stating that the prefix ui for ui:fragment is not bound.
Does anybody know, how I can include another XHTML page without the multiple DOCTYPEs and htmls?
You should take a look at the ui:composition tag.
We also use ui:include to include jsf2 pages, and to solve the problem you have I believe you could alter your included page by adding the ui:composition tag as follows:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns=".." xmlns:ui="..." ...>
<ui:composition>
<ui:fragment rendered="${foo}">
some html code
</ui:fragement>
<ui:fragment rendered="${!foo || bar}">
some more html code
</ui:fragement>
</ui:composition>
</html>

nokogiri and video tags

some pieces of HTML structure are stored on server. Before saving, they will be preprocessed.
Preprocessing inserts HTML 5 video tags to certain places.
I trying to do it, but, everytime i deal with video tags, i get following:
Tag video invalid
I think, they this is because of the HTML 4.0 DOCTYPE, that i saw in debugger:
< !DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
I also tried to use XML as a parser, but, i cannot figure out, how to obtain clean HTML code from Nokogiri::XML object.
Any ideas ?
First, you can use #to_html (or #to_xhtml) on an XML document. However, I'm not sure that's necessary here. I don't get any 'Tag video invalid' errors when creating elements. Here's a sample program showing how to parse existing HTML4, inject a video element, and get HTML out again:
require 'nokogiri'
html = Nokogiri::HTML <<ENDHTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html><head><title>Sauceome</title></head>
<body><p class="video" id="foo"><!-- put vid here--></p></body></html>
ENDHTML
wrap = html.at('.video')
wrap.inner_html="<video src='#{wrap['id']}.mov'></video>"
puts html.to_html
#=> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
#=> <html>
#=> <head>
#=> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
#=> <title>Sauceome</title>
#=> </head>
#=> <body><p class="video" id="foo"><video src="foo.mov"></video></p></body>
#=> </html>

ASP.NET MVC: How do I send "text/xml" to all browsers but IE?

I need to be able to send the content type "text/xml" to Firefox and Safari, to allow them to render inline SVG in one of my pages.
This works, as long as the content type is "text/xml".
However, when IE hits the page, if the content type is not "text/html" it tries to render the XML document tree, rather than the XHTML content of the page.
What is the "right way" in ASP.NET MVC to set the HTTP Content-Type of ALL of my views?
Keep in mind that I am going to be rendering the views as ViewResults.
Ok, to clear any confusion up:
User Agent Content-Type Desired
-----------------------------------
IE 5.5 text/html
IE 6 text/html
IE 7 text/html
IE 8 text/html
Firefox text/xml
Safari text/xml
Chrome text/xml
And so on.
All of the browsers listed support SVG inline in some way or another. I have a consistent delivery format, save the content type.
You could look at the properties in Request.Browser and sniff out IE that way, and return the proper view that way, though that is prone to issues. This isn't optimal because IE might support it in the future.
public ActionResult MyAction() {
if (this.Request.Browser.Browser == "IE") {
return View("NonSVG");
} else {
return View("SVG");
}
}
Something worth looking into a little more might be this page on Codeplex. They define a property on Browser called AcceptsImageSVG, but it looks like it's geared towards mobile browsers, don't know if it could be used in your situation.
According to W3, you should be using application/xhtml+xml rather than text/xml to signify XHTML:
http://www.w3.org/TR/2002/NOTE-xhtml-media-types-20020801/#text-xml
The above article also notes that text/html should not be used for XHTML content.
You can determine the browser type by using the Request.Browser object
See this example http://msdn.microsoft.com/en-us/library/system.web.configuration.httpcapabilitiesbase.type%28VS.80%29.aspx
So you could do something like:
if( Request.Browser.Type.ToUpper().Contains("IE") )
{
// Return IE View
}
else
{
// Return the other view
}
Or, if you use this in lots of places you could create a ViewResult factory that returns the proper view result based on the browser type.
Kind of hacky, but... What if the SVG was in a frame, the frame advertised content-type=text/xml, while the containing page advertsized the more proper application/xhtml+xml. This divides the problem into two (possibly) more tractable ones.
I'm not sure whether this will work, but you could try using conditional comments:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<!--[if lte IE 8]>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<![endif]-->
<!--[if gt IE 8]>-->
<meta http-equiv="Content-Type" content="text/xml; charset=UTF-8" />
<!--<![endif]-->
<title>Test page</title>
</head>
<body>
<p>Test page</p>
</body>
</html>
Or, better yet, use HTML5:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Test page</title>
</head>
<body>
<p>Test page</p>
</body>
</html>
You don't even need to specify the content type.

Resources