1

so basically I have a link in my html domain.com/app/css/build/app-23471942834.css however on the server the file actually lives in /fs/current/public/css/build/app-23471942834.css. Is there a way to check if a file exists in a RewriteCondition? The problem is that I basically need the /css/build/app-23471942834.css part to check, without the /app. Is there a way to remove this in a condition?

So I need:

  • domain.com/app/login to be rewritten to /fs/current/public/login
  • domain.com/app/build/css/app-123523.css to be rewritten to /fs/current/public/build/css/app-123523.css
  • domain.com/app/build/js/app-123523.js to be rewritten to /fs/current/public/build/js/build/app-123523.css

I am using Laravel so within my public directory there is another .htaccess by default with this:

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews
    </IfModule>

    RewriteEngine On

    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)/$ /$1 [L,R=301]

    # Handle Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]

    # Handle Authorization Header
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
</IfModule>

Sorry, but I really suck at htaccess files. Thanks for your help.

What I got so far:

RewriteCond %{HTTP_HOST} ^(www.)?domain.de$ [NC]
RewriteCond %{DOCUMENT_ROOT}/fs/current/public/$1 -f
RewriteRule ^app/(.*)$ /fs/current/public/$1 [L]

RewriteCond %{HTTP_HOST} ^(www.)?domain.de$ [NC]
RewriteRule ^app/(.*)$ /fs/current/public/index.php?/$1 [L]

SOLUTION:

I solved my issue like this:

RewriteCond %{HTTP_HOST} ^(www.)?domain.de$ [NC]
RewriteCond %{REQUEST_URI} \.(css|jpg|gif|png|js|svg)
RewriteRule ^app/(.+)$ /fs/current/public/$1 [L]

So all the rewrite only applies to css/jpg/gif/png/js/svg I think the issue I had before, was that the index.php file was rewritten by the script as well.

  • What do you mean by "need the /css/build/app-23471942834.css part to check"? Presumably app-23471942834.css never exists? Why do you need to check that the resource exists? Can't you just rewrite it if it matches the pattern? Or is this just an example of one such pattern and you have many different CSS and JS URLs/files like this? – MrWhite Jul 18 '16 at 13:42
  • Do you have multiple domains/hosts on the same webspace? If not then the %{HTTP_HOST} check is unnecessary. – MrWhite Jul 18 '16 at 16:15

1 Answers1

1

Try the following:

RewriteEngine On
RewriteRule ^/?app/(css/build/app)-\d+(\.css)$ /fs/current/public/$1$2 [L]

Not sure exactly what you are after, but this will internally rewrite a URL of the form domain.com/app/css/build/app-23471942834.css to /fs/current/public/css/build/app.css.

If you need to check that the destination file exists before rewriting then you can add a condition before the RewriteRule (although I'm not sure why you would need to do this, as you'll get a 404 regardless). For example:

RewriteCond %{DOCUMENT_ROOT}/fs/current/public/$1$2 -f

UPDATE#1: From comments...

I would need to rewrite anything that is not a file

Ah ok, that makes more sense. You can replace the above RewriteCond directive with the following:

RewriteCond %{REQUEST_FILENAME} !-f

That will only process the following RewriteRule substitution if the requested URL did not match a file on the filesystem.

UPDATE#2: From updated question...

A more general solution, after the existing RewriteEngine directive, try the following in .htaccess:

RewriteCond %{DOCUMENT_ROOT}/fs/current/public/$1 -f
RewriteRule ^app/(.+)$ /fs/current/public/$1 [L]

This will only rewrite the request if a file of the form <document-root>/fs/current/public/css/build/app-23471942834.css or <document-root>/fs/current/public/login exists on the filesystem.

MrWhite
  • 13,016
  • Hmm this sounds pretty good, however I would need to rewrite anything that is not a file to /fs/current/public/. Can you tell me how I can do this (PS: Updated the above example) – Lukas Oppermann Jul 18 '16 at 13:57
  • So what exactly is %{REQUEST_FILENAME} would it not include the app/? Would that not check if /app/build/css/app-123523.css exists instead of /fs/current/public/build/css/app-123523.css? – Lukas Oppermann Jul 18 '16 at 14:06
  • Yes, %{REQUEST_FILENAME} would potentially include /app/ (which I thought you were referring to in your first comment: "rewrite anything that is not a file"). The first RewriteCond checks the destination. I have updated my answer with a more general solution based on your updated question. (Although in your question, you state: "however on the server the file actually lives in /fs/current/public/css/build/app.css" - that doesn't include the numeric code?) – MrWhite Jul 18 '16 at 14:18
  • Hey, sorry, the missing numbers are an error. I updated the question again. The bottom 2 rows work to redirect the general request, however your solution does not quite work (I guess, because the /app is still in there correct?)

    I need it to be /fs/current/public/build/css/app-123523.css or for js /fs/current/public/build/js/app-123523.js (without the /app).

    – Lukas Oppermann Jul 18 '16 at 14:52
  • Yes, that is what UPDATE#2 should be doing, removing /app from the requested URL. You say it works to "redirect the general request", but "does not quite work"? In what way does it not "quite work" - is there another type of request, other than the "general request"? – MrWhite Jul 18 '16 at 14:57
  • Ah, sorry, no, this works RewriteCond %{HTTP_HOST} ^(www.)?domain.de$ [NC] RewriteRule ^app/(.*)$ /fs/current/public/index.php?/$1 [L] to redirect app/login to the correct path, but somehow your solution for the file seems to nor work. :( I am not sure what I am doing wrong, can I provide more information?

    How does it know that $1 is only the filename and not /app/filename.css?

    – Lukas Oppermann Jul 18 '16 at 14:59
  • $1 is a backreference to the captured group (ie. (.+)) in the RewriteRule pattern. So, given a URL /app/foo/bar.css, $1 will contain foo/bar.css, so the request gets rewritten to /fs/current/public/foo/bar.css. The additional condition ensures that the rewrite only occurs if <document-root>/fs/current/public/foo/bar.css exists as a physical file on the filesystem. – MrWhite Jul 18 '16 at 16:09
  • Somehow I can not get this to work. However I solved my case by doing:
    RewriteCond %{HTTP_HOST} ^(www.)?domain.de$ [NC]
    RewriteCond %{REQUEST_URI} \.(css|jpg|gif|png|js|svg)
    RewriteRule ^app/(.+)$ /fs/current/public/$1 [L]
    
    – Lukas Oppermann Jul 19 '16 at 05:42
  • It would seem that the check to see if the file exists (ie. RewriteCond %{DOCUMENT_ROOT}/fs/current/public/$1 -f) is failing for some reason? Is the %{DOCUMENT_ROOT} server variable set to the expected value (you appear to be checking the HTTP_HOST so you would seem to have multiple domains)? Is app-23471942834.css a physical file on the filesystem, or is the request rewritten? – MrWhite Jul 19 '16 at 12:27
  • NO, sorry, I updated the question, the problem was not your rewrite, but that it also applied to the index.php file, because it was not specifying only the files that need to be rewritten like that, I think. – Lukas Oppermann Jul 19 '16 at 12:35