HTACCESS REQUEST_URI without the filename - php

RewriteEngine On
RewriteCond %{REQUEST_URI} !(images)
RewriteRule ^(.*)\.(txt|rtf|docx?|odt|pdf|bmp|gif|jpe?g|png|tiff?)$ http://%{SERVER_NAME}/~abc123/uploader/process.php [nc]
Is there any way of not having to quote ~abc123/uploader but to modify my regular expression so that the request_uri without the filename is dynamically passed through?
I've tried looking at removing the filename from the request_uri and also changing my regular expression but to no avail.
What I'm trying to do is to make sure certain file types are processed by a PHP script and cannot be accessed directly.

Here are two clues that might help you:
First, you can use those keywords into your regular expression (I let you google for more information) : %{SCRIPT_FILENAME} and %{REQUEST_URI}
Second, here's an example of how to use it:
# (1) if domain name is static:
RewriteCond %{HTTP_HOST} ^(.*)\.s\.(.*) [NC,OR]
RewriteCond %{HTTP_HOST} ^(.*)\.static\.(.*) [NC]
# (2) and it's not the JavaScript directory:
RewriteCond %{REQUEST_URI} !^/js/(.*)$
# (3) *always* add /templates/ (if not there):
RewriteRule /(templates/)*(.*) /templates/$2 [L]
And a few people know that you can even change the whole destination filename this way (note: the STATIC and PATH_LOCAL variable is an environment variable that I've calculated a few steps before):
# If static...
RewriteCond %{ENV:STATIC} 1
# ...first test to see if the file exists in the language path:
RewriteCond %{DOCUMENT_ROOT}/%{ENV:PATH_LOCAL}/%{ENV:EXT}%{REQUEST_FILENAME} -f
# It exists => rewrite filename then end:
RewriteRule ^(.+) %{DOCUMENT_ROOT}/%{ENV:PATH_LOCAL}/%{ENV:EXT}%{REQUEST_FILENAME} [QSA,L]

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} ^(?!images)(.*)/[-\w\.]*$
RewriteRule ^(.*)\.(txt|rtf|docx?|odt|pdf|bmp|gif|jpe?g|png|tiff?)$ http://%{SERVER_NAME}/%1/process.php [NC,L]
will do what you ask. The (?!...) is a negative lookahead i.e don't include images. The [-\w.]*$ bit will match normal file names. What I don't understand is that a http://%{SERVER_NAME}/... redirect without the [R] is just a normal internal rewrite why you don't just do
RewriteRule ^(?!images)(.*)/[-\w]*\.(?:txt|rtf|docx?|odt|pdf|bmp|gif|jpe?g|png|tiff?)$ $1/process.php [NC,L]
Without any conds or
RewriteCond %{REQUEST_URI} !^images
RewriteCond %{REQUEST_URI} (txt|rtf|docx?|odt|pdf|bmp|gif|jpe?g|png|tiff?)$
RewriteRule ^(.*)/.* $1/process.php [NC,L]
if you want to keep it easier to understand.

Related

htaccess move to mamp

I'm setting up a working copy of a site, and copied the entire site to a mamp. But I have problem setting up a working version of .htaccess.
Working directory on localhost is "folder1".
This is the live .htaccess:
RewriteEngine On
RewriteBase /
# Rewrite site site.eu to site.eu/en/
RewriteCond %{QUERY_STRING} !language=(sv|en|ru|jp)
RewriteRule ^$ en/ [L,R=301]
# Add trailing slash if necessary
RewriteRule ^(sv|en|ru|jp)$ $1/ [R=301,L]
# Add language part to old bookmarks/links
RewriteCond %{REQUEST_URI} !^/(sv|en|ru|jp)/
RewriteCond %{QUERY_STRING} !language=(sv|en|ru|jp)
RewriteRule (sale|brands|latest_in_stock)(.*) en/$1$2 [R=301,L]
# Remove www
RewriteCond %{HTTP_HOST} ^www\.site\.eu$ [NC]
RewriteRule (.*) http://site.eu/$1 [R=301,L]
RewriteRule ^(sv|en|ru|jp)/(.*)$ $2?language=$1 [L,QSA]
RewriteRule ^sale sale.php [L,QSA,NC]
RewriteRule ^brands/([^/]+) /designer.php?idnr=$1 [L,QSA,NC]
RewriteRule ^brands /labelList.php [L,QSA,NC]
...
On the local copy I changed to:
RewriteBase /folder1/
I tried to removed the part with "Add language code to old... " and the part "Remove www".
I also tried different changes to the last RewriteRule for exampel adding "folder1" and remove it from RewriteBase.
RewriteRule ^brands /folder1/labelList.php [L,QSA,NC]
The php-files and the index-file is working fine, but none of the /brands for example. I get a 500 error, too many redirects.
The variable %{REQUEST_URI} will contain the part behind the domain name, regardless of which .htaccess file it is in. What will happen is the following:
We start with localhost/en/brands/asdf. It matches the following rule:
RewriteCond %{REQUEST_URI} !^/(sv|en|ru|jp)/
RewriteCond %{QUERY_STRING} !language=(sv|en|ru|jp)
RewriteRule (sale|brands|latest_in_stock)(.*) en/$1$2 [R=301,L]
The first condition is true, because ^/(sv|en|ru|jp)/ does not match /folder1/en/.... The second condition is true, because we haven't reached the rule yet that sets the language in the query string. Finally it will match the last one, because (sale|brands|latest_in_stock)(.*) will match en/brands/asdf ($1 will contain brands and $2 will contain /asdf). This will redirect to localhost/folder1/en/brands/asdf after re-adding the directory-prefix.
You have several options:
1. adding folder1 to the condition
If you add folder1 to the condition with %{REQUEST_URI}, this problem does not occur:
RewriteCond %{REQUEST_URI} !^/folder1/(sv|en|ru|jp)/
2. adding a negative look-ahead
If you add a negative look-ahead to the rule, and remove the condition, things work out correctly, because the first argument of RewriteRule will match against what you expect. The pro of this is that you do not need to know in which directory this is:
#Remove this: RewriteCond %{REQUEST_URI} !^/(sv|en|ru|jp)/
RewriteCond %{QUERY_STRING} !language=(sv|en|ru|jp)
RewriteRule ^(?!(sv|en|ru|jp)/)[^/]*/?(sale|brands|latest_in_stock)(.*) en/$1$2 [R=301,L]
You might need to alter the capture group references. I can't test them here.
3. Moving rules around
Moving the following rule:
RewriteRule ^(sv|en|ru|jp)/(.*)$ $2?language=$1 [L,QSA]
just above the rule I just pointed out should theoretically solve this problem. I would strongly recommend against this solution, because intermixing redirects and rewrites makes it very hard to read.

.htaccess mod rewrite help needed

I have written this little piece of code. I am very new to this so i am not sure it is all correct. but basically it lets me access urls with the php extension. When people get on the site they are being redirected from the geo ip page to the correct language which like looks like this
main.php?lang=uk or nl or en or eu etc.
right now i can also use it like this
main/?lang=uk or nl or en or eu etc.
I would like to be able to to also remove the variable in the url ?lang=uk.
How would i do this. My .htaccess code is below
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
DirectorySlash On
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{SERVER_NAME}/$1 [R=301,L]
# remove trailing slash
RewriteRule ^(.*)\/(\?.*)?$ $1$2 [R=301,L]
RewriteRule ^([\w\/-]+)(\?.*)?$ $1.php$2 [L,T=application/x-httpd-php]
</IfModule>
Thanks too anyone willing to help.
The first argument of RewriteRule does match anything after the domain name and prefix* and before any query string if that exists. In http://localhost/this/is/my/test?lang=123 with a .htaccess file in the this/is/ directory it would match my/test. To match a query string, you have to use the %{QUERY_STRING} variable.
If the second argument (the rewritten url) of RewriteRule does not contain a query string, it will automatically append the query string of the original url to the new url.
In the code below I use %{THE_REQUEST}. This is the string that is used to make the request for a page. It is in the form of GET /my/resource?query=string HTTP/1.1. It does not change when rewriting things, which makes it useful to prevent infinite loops.
In your php file make sure that the language is read from a cookie instead of a get variable, then do the following:
#Set cookie for language
RewriteCond %{QUERY_STRING} ^(.*?)&?lang=([^&]+)&?(.*?)$
RewriteRule ^ %{REQUEST_URI}?%1&%3 [CO=lang:%2:127.0.0.1:1:/:0:1,R,L]
#Remove potential prefix or suffix & from query string
RewriteCond %{QUERY_STRING} ^&(.*?)$ [OR]
RewriteCond %{QUERY_STRING} ^(.*?)&$
RewriteRule ^ %{REQUEST_URI}?%1 [R,L]
#External requests with \.php should be without that.
RewriteCond %{THE_REQUEST} \.php
RewriteRule ^(.*)\.php$ $1 [R=301,L]
#Try to load php page if resource does not alreay have an extension
RewriteCond %{REQUEST_URI} !\.[a-z]+$
RewriteRule ^(.*)$ $1.php [L]

Change ugly query string to a prettier /path/to/page/ pattern

I have a site which uses a custom query string to deliver pages to the visitor. A sample query string looks like /?sec=news&pg=current&bg=203. I'd like to use .htaccess to rewrite the strings into a pattern like /news/current/203.
I know how to take the /news/current/203 URL and make it into a query string that I can parse with PHP. I typically use this bit of htaccess code:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+) - [PT,L]
RewriteRule ^(.*) /index.php?id=$1 [L]```
And my PHP then explodes id on the / and off we are running.
My question is this... How can I add a few more lines to this htaccess code that will allow the old URL query pattern to continue to work for people that have bookmarks or links that use the /?sec=news... pattern? Basically, it seems like I need to take this old query string and combine the values into one string that I can pass to index.php in the id parameter. I don't want to lose the ability to honor the old pattern, but also need to promote the new cleaner path-based string.
I know there is some regex that can help here, but I am terrible at understanding regular expressions. Any help would be appreciated, and let me know if I am not making any sense.
Update: The answer provided makes my final htaccess file look like this...
RewriteEngine on
# Prevent directory listings
Options All -Indexes
# Rewrite to www
Options +FollowSymLinks
RewriteCond %{HTTP_HOST} ^sample.com[nc]
RewriteRule ^(.*)$ http://www.sample.com/$1 [r=301,nc]
# WHEN DONE TESTING< CHANGE ALL 302 to 301 !!!
# Honor the old format /index.php?sec=XXX&pg=XXX&bg=XXX and turn it into the new format
RewriteCond %{QUERY_STRING} sec=(\w+)&pg=(\w+)&bg=(\d+)
RewriteRule ^(.*)$ /%1/%2/%3? [R=302,L]
# Turn /path/to/page into index.php?id=path/to/page
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+) - [PT,L]
RewriteRule ^(.*) /index.php?id=$1 [L]
Add this rule
RewriteCond %{QUERY_STRING} sec=(\w+)&pg=(\w+)&bg=(\d+)
RewriteRule ^(.*)$ /%1/%2/%3? [R=302,L]
Change 302 to 301

Remove File Extension and URL Variable using .htaccess

I'm making up myself a small blog and I found a useful .htaccess file to remove file extensions:
AddType text/x-component .htc
RewriteEngine On
RewriteBase /
# remove .php; use THE_REQUEST to prevent infinite loops
RewriteCond %{THE_REQUEST} ^GET\ (.*)\.php\ HTTP
RewriteRule (.*)\.php$ $1 [R=301]
# remove index
RewriteRule (.*)/index$ $1/ [R=301]
# remove slash if not directory
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} /$
RewriteRule (.*)/ $1 [R=301]
# add .php to access file, but don't redirect
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteCond %{REQUEST_URI} !/$
RewriteRule (.*) $1\.php
This works just fine and all pages are showing up .php less. I know wanted to extend this so when I click a link to a specific blog post (say /blog/index.php?art=1) it just shows in the url as website/blog/1. I thought to tag on to the end of the .htaccess file:
RewriteRule ^blog/(.*)$ blog/index.php?art=$0 [L]
But that doesn't seem to be working. EDIT Actually it breaks the blog page so no snippets are pulled through from the DB
My .htaccess file is in the root directory and the blog files are /root/blog/index.php
Any help would be gratefully appreciated
Unlike most other languages, the parameters in .htaccess are not 0-based. To access the first parameter, you should use $1, not $0.
The following should work:
RewriteRule ^blog/(.*)$ blog/index.php?art=$1 [L]
It might also be worthwhile to add some tests in there, for example you might only want numerical values passed to art, so you can improve it using:
RewriteRule ^blog/([0-9]+)$ blog/index.php?art=$1 [L]
Also, it might be worthwhile to add the QSA flag, since this will also preserve any query string that is passed in the original URL:
RewriteRule ^blog/([0-9]+)$ blog/index.php?art=$1 [L,QSA]

Remove .php from example.com/test.php/foo/bar

I'm looking for a way to simply remove ".php" from a url while ignoring everything after the .php
So example.com/test.php/foo/bar would become example.com/test/foo/bar
and then in the PHP template I can search for and utilize foo or bar as I please. Everything I've found to remove .php interferes with the variables at the end.
UPDATE: I've found some success by removing .php from the file name and then using ForceType. Although It'd still be nice if I could keep the .php extension so my Code Editor knows how to highlight the syntax :)
<FilesMatch "^test$">
ForceType application/x-httpd-php5
</FilesMatch>
Update 2
Here's a RewriteRule that I've tried using to some success, but when I add a trailing slash and some content after, it results in a 500 internal server error
RewriteEngine On
RewriteBase /
# remove .php; use THE_REQUEST to prevent infinite loops
RewriteCond %{THE_REQUEST} ^GET\ (.*)\.php\ HTTP
RewriteRule (.*)\.php$ $1 [R=301]
# remove index
RewriteRule (.*)/index$ $1/ [R=301]
# remove slash if not directory
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} /$
RewriteRule (.*)/ $1 [R=301]
# add .php to access file, but don't redirect
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteCond %{REQUEST_URI} !/$
RewriteRule (.*) $1\.php [L]
Your last block is almost there. However you need a bigger assortment of RewriteConds to make it work with an optional PATH_INFO.
Namely you need to match the word characters from the REQUEST_FILENAME/_URI first, and then test for existence of a like-named .php script:
RewriteCond %{REQUEST_URI} ^/(w+)/
RewriteCond %{DOCUMENT_ROOT}/%1.php -f
RewriteRule ^(\w+)/(.+)$ $1.php/$2 [L]
The last RewriteRule depends on existing trailing vars. Add one of the generic rule blocks for plain http://example.com/test requests without PATH_INFO. Note that this specific set will work with xyz.php scripts in the webroot only.
Please try to recheck this:
RewriteCond %{REQUEST_URI} ^/([a-z0-9-_]+)/([a-z0-9-_]+)/([a-z0-9-_]+)/?$
RewriteRule ^(.*) ^/%1.php/%2/%3

Categories