I use PHP's virtual() directive quite a lot on one of my sites, including central elements. This worked fine for the last ~10 years -- but after upgrading (or rather moving, as it is on a new machine) to Ubuntu 12.04 it somehow got broken.

Example setup (simplified)

To make it easier to understand, I simplify some things (contents). So say I need a HTML fragment like <P>For further instructions, please look <A HREF='foobar'>here</P> in multiple pages. 10 years ago, I used SSI for that, so it is put into a file in a central place -- so if e.g. the targeted URL changes, I only need to update it in one place. To serve multiple languages, I have Apache's MultiViews enabled -- and at $DOCUMENT_ROOT/central/ there are the files:

  • foobar.html (English variant, and the default)
  • foobar.html.de (German variant).

Now in the PHP code, I simply placed:

<? virtual("/central/foobar"); ?>

and let Apache take care to deliver the correct language variant.

The problem

As said, this worked fine for about 10 years: German visitors got the German variant, all others the English (depending on their preferred language). But after upgrading to Ubuntu 12.04, it no longer worked: Either nothing was delivered from the virtual() command, or (in connection with framesets) it even ended up in binary gibberish.

Trying to figure out what happens, I played with a lot of things. I first thought MultiViews was (somehow) not available anymore -- but calling http://<server>/central/foobar showed the right variant, depending on the configured language preferences. This also proved there was nothing wrong with file permissions. The error.log gave no clues either (no error message thrown).

Finally, just as a "last ressort", I changed the PHP command to <? virtual("central/foobar.html"); ?> -- and that very same file was in fact included. So PHP's virtual() function basically worked -- but the language dependend stuff obviously did no longer work together with it as it did before.

As the "binary gibberish" mentioned above made me curious, I copy-pasted it into a file named foo.gz, and ran gzip -d foo.gz. As already suspected, this yielded no error message (though the output still was gibberish -- just different gibberish). Comparing the /etc/apache2/mods-enabled on my new machine with a similar setup on an older machine turned up mod_deflate being enabled on the new machine. So I removed that from the enabled mods (by simply deleting the symbolic links), reloaded Apache... problem seemed solved: PHP's virtual now included the correct language variant. But Firefox now refuses to display the framesets (if the virtual() call was in the alternative part), but simply behaves as if no longer supporting them -- though they show up fine in the source (Ctrl-U -- but having the included "virtual" file's content moved in front of the <HEAD> tag!). Trying again with the full file name in virtual("central/foobar.html") the frameset was interpreted correctly again (and the included content is in the correct place).

I'm totally confused now.

Of course I tried to find some change, using Google a lot, and also searching the questions here -- unfortunately to no avail.

Finally: The question

Putting "design questions" aside (surely today I would design things differently -- but at least currently I miss the time to change that for a quite huge amount of pages): What can be done to make it work again? I surely missed something -- but I cannot figure out what...


I believe your problem to be the apache configuration.

Troubleshooting tips:
  - check if mod_negotiation is loaded 
  - check that Multiview Option is enabled 
  - The default is to map headers like the language to something known by mod_mime, so check you have stuff like:
    AddLanguage de .de
    AddLanguage en .en
  - check what your browser is sending in the headers. Try duplicating it with curl

  - Use mod_rewrite to rewrite the URL to the correct file and the virtual calls should work.
  - Try configuring the mime map manually:
    AddHandler type-map var
    Create a file named foobar.var with the following content:
    URI: foobar.html
    Content-Type: text/html
    Content-Language: en

    URI: foobar.html.de
    Content-Type: text/html
    Content-Language: de

    Check what happens when you access the foobar.var file.

  • Thanks for your answer! Maybe I mixed too many elements into my question: Negotiation itself works fine, as described above. PHP's virtual() also works, if the complete filename is given. But if virtual() get's passed something which needs negotiation, the resulting content is always placed at the very top of the output (i.e. before the <HTML> element), regardless of the position of the virtual() call. Everything else I solved 10 minutes after the post (and updated the post then to reflect this, which might look a bit confusing). Maybe I should place that in a new question... – Izzy Nov 13 '12 at 7:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.