views:

208

answers:

2

Hi,

I'm running a Rails Application which gets a lot of traffic at the moment so I started using Page Caching to increase the performance. So far everything works like a charm. But when I tried to also cache search results I run into a strange problem.

My Approach:

  • Use meaningful URLs for searching and pagination (/search?query=term&page=3 becomes /search/term/3)
  • Use Javascript to submit the form - if JS is disabled it falls back to the old form (which also works with my routes, but without caching)

My Code:

// Javascript
function set_search_action() {
  window.location = '/search/' + escape(document.getElementById('query').value);
  return false;
}

// HTML
<form action="/search" id="search_form" method="get" onSubmit="return set_search_action();">
  <input id="query" name="query" title="Search" type="text" />
  <input class="submit" name="commit" type="submit" value="Search" />
</form>

The Problem

Everything works for single words like "term". But when I search for "term1 term2" the form is submitted to /search/term1 term2/ or /search/term1 term2/1 . It should be submitted to /search/term1+term2 That's what the JS escape function should do I think.

So far it works also with spaces in development mode. But I guess it will become a problem in production mode with caching enabled (URLs shouldn't contain any whitespaces).

Any ideas on what I did wrong? Thanks!

+3  A: 

Never use escape()! It's broken and highly dis-recommended for what you do. Use encodeURIComponent() instead.

To have + instead of %20, append a .replace(/%20/g, "+").

Tomalak
As @bobince points out, the `+` is only valid in the query string. And even there it can be substituted with `%20` without any problems.
Tomalak
+4  A: 

It should be submitted to /search/term1+term2

Nope. Plus symbols only represent spaces in application/x-www-form-urlencoded content, such as when the query-string part of the URL is used to submit a form. In the path-part of a URL, + simply means plus; space should be encoded to %20 instead.

That's what the JS escape function should do I think.

Yes it does, and that's the problem. escape encodes spaces to +, which is only suitable for form submissions; used in a path, you will get an unexpected and unwanted plus sign. It also mangles non-ASCII characters into an arbitrary format specific to the escape function that no URL-decoder will be able to read.

As Tomalak said, escape()/unescape() is almost always the wrong thing, and in general should not be used. encodeURIComponent() is usually what you really want, and will produce %20 for spaces, which is safe as it is equally valid in the path part or the query string.

bobince
+1 for thorough explanation of where and when `%20` is valid.
Tomalak