Page cache matching is case insensitive, which may lead to the return of cached 404's on existing pages.

To reproduce:

1. Enable 'normal' page caching.
2. Visit the URL http://example.com/NODE - a 404 page not found is returned
3. Visit the URL http://example.com/node - the same 404 page not found is returned.

On MySQL (5.0.21, 4.0.24), PHP ( 5.1.4, 4.3.10-18), Apache (2.2.2)

Now, changing cid to be a VARCHAR BINARY allows case-sensitive matching, but I haven't given all the possible implications much thought yet.

Why critical? Because a user may have a hard time getting a site back to serving normal pages without access to the database.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

chx’s picture

Making cid case snesitive at this point -1

What about adding a simple PHJP string compare instead.

pwolanin’s picture

In general, it seems that URLs should be considered case sensitive. So, it seems like there either needs to be a case-insensitive path/menu lookup to start with, or case-sensitive caching as proposed.

Heine’s picture

Status: Active » Needs review
FileSize
737 bytes

We'd only modify the cid colum in the table cache_page and not touch the rest of the cache. I'm not sure how we could do a simple string comparison without extensive surgery to cache_get / cache_set.

Postgresql shouldn't have this issue as it always matches in a case-sensitive manner.

pwolanin’s picture

Ok, I had been ignorant on this topic, but after some research this seems like the right approach since mysql.com says

If you want a column always to be treated in case-sensitive fashion, declare it with a case sensitive or binary collation

.

The BINARY and VARBINARY data types are distinct from the CHAR BINARY and VARCHAR BINARY data types. For the latter types, the BINARY attribute does not cause the column to be treated as a binary string column. Instead, it causes the binary collation for the column character set to be used, and the column itself contains non-binary character strings rather than binary byte strings. For example, CHAR(5) BINARY is treated as CHAR(5) CHARACTER SET latin1 COLLATE latin1_bin, assuming that the default character set is latin1. This differs from BINARY(5), which stores 5-bytes binary strings that have no character set or collation.

see: http://dev.mysql.com/doc/refman/5.1/en/case-sensitivity.html and http://dev.mysql.com/doc/refman/5.1/en/binary-varbinary.html

chx’s picture

I think you need patch some upgrade too.

Heine’s picture

Indeed.

drumm’s picture

Status: Needs review » Fixed

Committed to HEAD.

Anonymous’s picture

Status: Fixed » Closed (fixed)
CarbonPig’s picture

Modifying the mySQL table from within phpMyAdmin solves the issue of making your URL aliases case sensitive.

You simply change the database filed in URL ALIAS from:

dst varchar

To:

dst varbinary(128)

Hope that makes sense.

TAGS: How to make your url aliases case sensitive, make alias case sensitive, enable, disable

dczaretsky’s picture

Version: 5.x-dev » 7.23
Status: Closed (fixed) » Active

Hi,
I'm having this same problem in Drupal 7. When pages are cached, it is not case-sensitive. Therefore, when an erroneous page is called, the 404 error is cached, and then subsequent calls to the correct page return a 404 error.

I looked into the system.install module, and the above patch will not work. It seems they made it a bit more difficult to enable binary matching. A single schema is applied to all cache types as follows, and so you cannot make the cid binary without affect all other cache tables:

$schema['cache_page'] = $schema['cache'];

In most cases, URLs are case sensitive, so this should be fixed in the system module.

Mixologic’s picture

Priority: Critical » Normal

I think you might be having some other problem.

As far as I can tell, URL aliases in drupal *are not* case sensitive. so a call to http://mywebsite.com/content/MyPage will return http://mywebsite.com/content/mypage . And subsequent hits to any variant of casing will return the cached page.

So I dont know how you would ever get the 404 cached in the first place. What kind of page callback is it? A node or view? Or is it a custom menu callback you've added yourself?

Elijah Lynn’s picture

Current Drupal 7 behavior is that the page caching is not case-sensitive. I just tested the below two scenarios with Drupal page cache.

e.g. /node/1 & /nODE/1 are the same cache object
e.g. /foo & /FOO are the same cache object

This is interested because Acquia's default VCL is treating them as separate objects (for our org at least). This means more load on origin if people type the case differently and more importantly, purging the content from varnish is not accurate.

And cache invalidation is a reason why Drupal should not be case-sensitive, not to mention a better end user experience. Why have users be on the waiting end of creating multiple cache objects for the same piece of content?

Elijah Lynn’s picture

Issue summary: View changes

Worth noting that in default Drupal 8 install this is opposite behavior and aliases are case-sensitive.

http://sandbox/d8/foo == 200, http://sandbox/d8/fOO == 200

But x-Drupal-Cache: miss on the second one first time around

Of note is also this...

http://sandbox/d8/node/1 == 200, http://sandbox/d8/nOde/1 == 404

I guess maybe the external cache invalidation strategy will have to change with this behavior or we will need to make Drupal 8 case-insensitive again.

  • drumm committed dcd80a6 on 8.3.x
    #99970 by Heine. Make page cache keys case-sensitive on MySQL.
    
    

  • drumm committed dcd80a6 on 8.3.x
    #99970 by Heine. Make page cache keys case-sensitive on MySQL.
    
    

  • drumm committed dcd80a6 on 8.4.x
    #99970 by Heine. Make page cache keys case-sensitive on MySQL.
    
    

  • drumm committed dcd80a6 on 8.4.x
    #99970 by Heine. Make page cache keys case-sensitive on MySQL.
    
    

  • drumm committed dcd80a6 on 9.1.x
    #99970 by Heine. Make page cache keys case-sensitive on MySQL.
    
    

Version: 7.23 » 7.x-dev

Core issues are now filed against dev versions. More information about choosing a version.