开发者

htaccess rewrite loop?

开发者 https://www.devze.com 2023-03-20 20:22 出处:网络
I have user-uploaded files stored in /public/upload/* for instance: /public/upload/gallery/segway/child-on-a-segway.jpg

I have user-uploaded files stored in

/public/upload/*

for instance:

/public/upload/gallery/segway/child-on-a-segway.jpg

My current .htaccess rules already eliminate the /public part, but I still need to get rid of the /upload part, BUT, only for files with a given extension and not contained in one other directories, such as js or img. My current .htaccess looks like this (typical for Zend Framework projects):

RewriteEngine On

RewriteRule ^\.htaccess$ - [F]

RewriteCond %{REQUEST_URI} =""
RewriteRule ^.*$ /public/index.php [NC,L]

RewriteCond %{REQUEST_URI} !^/public/.*$
RewriteRule ^(.*)$ /public/$1

RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^.*$ - [NC,L]

RewriteRule ^public/.*$ /public/index.php [NC,L]

In hopes of getting rid of the /upload part working, I wrote this at the end of my .htaccess:

RewriteCond %{REQUEST_URI} ^(?<!upload|img|js|less|css)/.*(jpg|mp3|png)$
RewriteRule ^(.*)$ /upload/$1

Basically, if a file has jpg, png or mp3 extension and the path to it does NOT start with "upload", "js", "css", "img" or "less", prepend "upload" to the request URI. Well, it fails. When I type in the address bar: http://example.com/gallery/1/php193A.jpg, I get a 303 error:

You don't have permission to access /upload//public/upload/public/upload/public/upload/public/upload/public/upload/public/upload/public/upload/public/upload/public/gallery/1/php193A.jpg/1/php193A.jpg/gallery/1/php193A.jpg/1/php193A.jpg/upload/public/gallery/1/php193A.jpg/1/php193A.jpg/gallery/1/php193A.jpg/1/php193A.jpg/upload/public/upload/public/gallery/1/php193A.jpg/1/php193A.jpg/gallery/1/php193A.jpg/1/php193A.jpg/upload/public/gallery/1/php193A.jpg/1/php193A.j开发者_Python百科pg/gallery/1/php193A.jpg/1/php193A.jpg...

And the URL goes on and on for several dozen lines, as if it was looped.

This is the first time I'm dealing with .htaccess rewrite rules. I'd appreciate some help in setting them straight, as I'm completely lost here. Thanks in advance.


You said you "wrote this at the end of my .htaccess". TBH I see no way how that rule should be reached (order of rules matters) without changing some other rules a bit (like, removing L flag).

Let's examine this request: /gallery/segway/child-on-a-segway.jpg.

  1. It will be rewritten to /public/gallery/segway/child-on-a-segway.jpg by this rule: RewriteRule ^(.*)$ /public/$1

  2. Because there is no such file, it will be further rewritten to /public/index.php by this rule: RewriteRule ^public/.*$ /public/index.php [NC,L]. Because of [L] flag rewrite goes to next iteration.

  3. On 2nd rewrite iteration this rule RewriteRule ^.*$ - [NC,L] sees that /public/index.php does exists and terminates any further rewrites.


Considering all of the above it become obvious that such additional rule needs to be placed somewhere in the middle without modifying any of the existing rules. This is the rule I come up with that matches your requirements (based on your attempt to rewrite):

RewriteCond %{REQUEST_URI} !^/(public|img|js|css)/.*$
RewriteCond %{DOCUMENT_ROOT}/public/upload%{REQUEST_URI} -f
RewriteRule ^(.+\.(jpg|png|mp3))$ /public/upload%{REQUEST_URI} [NC,L]

The correct place to place it, in my opinion, would be before this rule: RewriteRule ^(.*)$ /public/$1. Such .htaccess will have the following content:

RewriteEngine On

RewriteRule ^\.htaccess$ - [F]

RewriteCond %{REQUEST_URI} =""
RewriteRule ^.*$ /public/index.php [NC,L]

RewriteCond %{REQUEST_URI} !^/(public|img|js|css)/.*$
RewriteCond %{DOCUMENT_ROOT}/public/upload%{REQUEST_URI} -f
RewriteRule ^(.+\.(jpg|png|mp3))$ /public/upload%{REQUEST_URI} [NC,L]

RewriteCond %{REQUEST_URI} !^/public/.*$
RewriteRule ^(.*)$ /public/$1

RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^.*$ - [NC,L]

RewriteRule ^public/.*$ /public/index.php [NC,L]

I have tested it -- it works. It may not be the most optimal as file lookup is executed (-f), but considering it will only work for a limited number of extensions (this is a good requirement) it should be fine (if it would be for EVERY extension then it will slowdown system on busy server/under load).

P.S. As I understand, the (?< pattern means "variable length look-behind" (although I'm not 100% sure on this).

0

精彩评论

暂无评论...
验证码 换一张
取 消