14

I have index.php that reads full path by $_SERVER[‘REQUEST_URI’] variable. My task is when user enter: www.domain/resource/777 redirect to index.php with path /resource/777 and parse $_SERVER[‘REQUEST_URI’] to do some logic. But I have also real files and folders like:

  • css/theme.css
  • assets/assets.js
  • resource/locale.js

When I try this config:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /index.php [L]

Client could not get all css and etc files. How to write correct rule in Apache to achive this?

Ceeee
  • 1,392
  • 2
  • 15
  • 32
Eazy
  • 3,212
  • 5
  • 24
  • 40
  • Hmmm, that config usually works for me. Can you give more info. Did some css files work but not others? Or did all css files not work. Is the config in an .htaccess file or in the httpd.conf? – BareNakedCoder Dec 08 '15 at 06:54
  • I got 404 Not Found on all files. Config in httpd.conf. Real example: http://lib.c.nis.edu.kz/resource/5 – Eazy Dec 08 '15 at 06:57
  • Thanks for the link to your page. When I sent a request for one of your .js files, the response headers say that your web server is nginx/1.8.0. The RewriteCond, etc are Apache config, not nginx. Which web server are you running? – BareNakedCoder Dec 08 '15 at 07:14
  • Nginx is on top of Apache. Nginx just proxy pass to apache 88 port. – Eazy Dec 08 '15 at 08:25
  • Im not an expect, but isn't the rules above is saying to redirect all request file to `index.php` and `index.php` is not a `css` nor a `js` file?? – Andrew Dec 08 '15 at 08:52
  • @Andrew: The 2 rewrite conditions (RewriteCond) determine if the RewriteRule is executed. Kinda like an "if" statement but in Apache's klunky language. It is saying: if (request is not (!) an existing directory (-d) AND is not (!) an existing file (-f)) { Rewrite to index.php }. In other words, if the request is for an existing directory or file, then don't rewrite the rule and so respond with the existing directory or file. – BareNakedCoder Dec 08 '15 at 17:09

5 Answers5

26

If you are using Apache 2.2.16 or later, you can replace rewrite rules entirely with one single directive:

FallbackResource /index.php

See https://httpd.apache.org/docs/2.2/mod/mod_dir.html#fallbackresource

Basically, if a request were to cause an error 404, the fallback resource uri will be used to handle the request instead, correctly populating the $_SERVER[‘REQUEST_URI’] variable.

SirDarius
  • 41,440
  • 8
  • 86
  • 100
3

Your rule is fine. Issue with css/js/image is that you're using relative path to include them.

You can add this just below <head> section of your page's HTML:

<base href="/" />

so that every relative URL is resolved from that base URL and not from the current page's URL.

Also keep just this rule in your .htaccess:

DirectoryIndex index.php
RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^[^.]+$ index.php [L]
anubhava
  • 761,203
  • 64
  • 569
  • 643
  • Didn't work. The problem is I got 404. Real example: http://lib.c.nis.edu.kz/resource/4 – Eazy Dec 08 '15 at 07:08
  • 1
    Your `http://lib.c.nis.edu.kz/assets/css/style.css` is throwing 404. What is correct URL for this `css` file? – anubhava Dec 08 '15 at 08:10
  • That is main problem! These files are exists. RewriteEngine doing something that user can not get these files. If I remove all Rewrite* user can achive these files. But index.php won't get "/resource/4" by $_SERVER[‘REQUEST_URI’] – Eazy Dec 08 '15 at 08:30
  • Now I can achive files but index.php do not work: http://lib.c.nis.edu.kz/resource/5 I got 404 error – Eazy Dec 08 '15 at 09:10
  • 1
    You're using `Server: nginx/1.8.0` not Apache hence these htaccess rules don't work. – anubhava Dec 08 '15 at 09:47
  • Nginx is on top of Apache. Nginx just proxy pass to apache 88 port. – Eazy Dec 08 '15 at 09:48
  • This is definitely some weird setup that's causing simplest possible rule like above to not work. No one can guess what's wrong, only ones who have access to your host can dig into this. – anubhava Dec 08 '15 at 09:53
1

According to the documentation REQUEST_FILENAME only evaluates to the full local filesystem path to the file if the path has already been determined by the server.

In a nutshell this means the condition will work if it is inside an .htaccess file or within a <Directory> section in your httpd.conf but not if it's just inside a <VirtualHost>. In this latter case, you can simply wrap it in a <Directory> tag to get it working.

<VirtualHost *:80>
     # ... some other config ...
    <Directory /path/to/your/site>
        RewriteEngine On
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteRule ^(.*)$ /index.php [L]
    </Directory>
</VirtualHost>
Matt Raines
  • 4,149
  • 8
  • 31
  • 34
0

You can set the error document in your htaccess file so that index.php will be used then a non existing file is requested:

ErrorDocument 404 /index.php
mario.van.zadel
  • 2,919
  • 14
  • 23
0

For now only this helped to me:

RewriteEngine On
RewriteCond %{REQUEST_URI} !^/src/
RewriteCond %{REQUEST_URI} !^/assets/
RewriteCond %{REQUEST_URI} !^/resource/
RewriteCond %{REQUEST_URI} !^/data.json
RewriteRule ^(.*)$ /index.php [L]
Eazy
  • 3,212
  • 5
  • 24
  • 40