.htaccess rewrite with optional custom POST variables - php

I've looked around on here to try and find a solution to my problem with no avail. Or I may have missed it.
Okay so I have a .htaccess rewrite rule setup:
# redirect all calls to index.php
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?page=$1 [PT,L]
</IfModule>
Which rewrites all mysite.com/?page=thisroute/thispage or mysite.com/?page=thispage to: mysite.com/thisroute/thispage or mysite.com/thispage
Is there a way to pass custom POST variables as well? How could I pass a form through this format without calling the php file that processes it directly?
Ex: mysite.com/thispage/?name=scott&this=that etc.

Related

htaccess adding [NC,F] to GET parameter

I'm working on an MVC project and I have the following .htaccess file:
Options -Indexes
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?path=$1 [L]
RewriteRule !^(public/|index\.php) [NC,F]
It works OK. I only want the public/ folder and the index.php file to be accessible to the public. All other paths should be inserted into the path GET parameter. For example, mysite.com/controller/method should point to mysite.com/index.php?path=controller/method.
Now, there is a problem. When visiting the URL directly (without including index.php, it is adding [NC,F] to the GET path parameter. It's like visiting mysite.com is pointing to mysite.com/index.php?path=[NC,F].
Why is this happening and how do I fix it?
EDIT
I moved index.php into the public/ folder. Here is my .htaccess file now:
Options -Indexes
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ public/index.php?path=$1 [L]
RewriteRule ^(/)?$ public/index.php [L]
RewriteRule !^(public/) [NC,F]
It seems to work OK. Are there any other improvements I could make on this?
You don't have a redirect location on the last rule, so it's taking the flags as the redirect location. Just a dash will be fine since it's a forbidden response. Change the last line to:
RewriteRule !^(public/|index\.php$) - [NC,F]
Also adding the dollar sign after index.php just to be clear.
Edit:
I would suggest updating your new rule set to the following (actually I suggest a complete re-think below, but this is an update on what you have):
RewriteEngine On
RewriteRule ^$ public/index.php [L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !^/public/
RewriteRule ^(.*)$ public/index.php?path=$1 [L]
RewriteRule !^(public/) - [NC,F]
The (/)? wasn't needed in your homepage rule, as the opening forward slash is not included in .htaccess matches anyway.
I moved your rule for the homepage to the top or it will never be used due to being matched by the previous rule (so the path param is not there when empty, which is presumably what you intended).
I stopped anything in /public/ from being passed to your index.php script, since the way you had it, anything in public that didn't exist would have been passed to your index script, which does not seem to be what you intend.
I added RewriteCond %{REQUEST_URI} !=/public/index.php so the rule couldn't be executed on itself and create a loop if rule processing is run through more than once, which it can be, but then took it back out because the above match on /public/ covers that anyway.
A Re-Think
All that said, I don't think it really makes sense to check if files don't exist and then just send forbidden responses to the ones that do, yet send everything else to your index script. Why not just send everything to your index script? That seems to be what you want really. I would suggest you simplify to this:
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/public/
RewriteRule ^(.*)$ public/index.php?path=$1 [L]
Dropping the homepage rule since no need to worry about an empty path parameter being passed to your index script. Changing the logic to be "Leave anything in /public/ alone. For anything else, pass it through to the index.php script." so files tests not needed since the script handles it all, and no forbidden response needed because there is nothing left to match, it's all covered by the rules. You can always return forbidden to anything you don't want to process in your script, which you would have needed to do anyway for existing file URLs in your previous setup.
One Last Re-Think
And finally, if I might suggest, it would be cleaner to have your index.php file in the root of the website, so you can make /public/ work with its own index file later if you like, so finally I would move it back to the root and change the rules to this:
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/public/
RewriteCond %{REQUEST_URI} !=/index.php
RewriteRule ^(.*)$ index.php?path=$1 [L]
And if you like all that, an up-vote to go with already accepting the answer would be much appreciated. :)
Adding RewriteRule ^(/)?$ public/index.php [L] seems to have resolved the issue. I'm not sure if this is the best approach, but here is my .htaccess file now:
Options -Indexes
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ public/index.php?path=$1 [L]
RewriteRule ^(/)?$ public/index.php [L]
RewriteRule !^(public/) [NC,F]
I moved index.php into the public folder to make things clearer.

htaccess add .html extension for urls with or without trailing slash

So to begin with I have a custom url rewrite that sends a request variable to a php script
Rewrite rule is below:
RewriteRule ^([\w\/-]+)(\?.*)?$ test/index.php?slug=$1 [L,T=application/x-httpd-php]
So if you access something like domain.com/slug-text it sends slug-text to index.php located in folder named test.
What I want is all my urls to look like domain.com/slug-text.html, but slug-test variable should still be sent to index.php file.
And
What I can't figure out is the redirect. I want all the old urls to be redirected from domain.com/slug-text or domain.com/slug-text/ to domain.com/slug-text.html and slug-text sent to index.php file located in test folder.
Searched a lot but could not find the answer for this question anywhere on the Internet.
Thank you all for the help.
UPDATE:
my new code is:
RewriteEngine On
Options +FollowSymlinks
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-l
RewriteRule ^(([\w/\-]+)?[\w-])(?!:\.html)$ http://domain.com/$1\.html [L,R=301]
RewriteRule ^(([\w/\-]+)?[\w-])(/|\.html)?$ test/index.php?slug=$1 [L]
domain.com/slug-text/ does not get redirected to domain.com/slug-text.html
domain.com/slug-text works as intended redirecting to domain.com/slug-text.html
What do i need to change?
This rule:
RewriteRule ^(([\w/\-]+)?[\w-])(/|\.html)?$ test/index.php?slug=$1 [L]
Will trap domain.com/slug-text, domain.com/slug-text/ and domain.com/slug-text.html and send slug-text to /test/index.php inside slug param.
If you really want to redirect using [R=301] from old urls to new then use this:
RewriteRule ^(([\w/-]+)?[\w-])/?(?!:\.html)$ http://domain.com/$1.html [L,R=301]
RewriteRule ^(([\w/-]+)?[\w-])\.html$ test/index.php?slug=$1 [L]
Also note that as using explicit redirect bottom rule is modified to trap url's ending with .html
It is also advisable (if your .htaccess does not already contain this) to filter conditions for existing files and folders not to be trapped by your redirect rules. Simply add these lines before RewriteRule lines:
# existing file
RewriteCond %{SCRIPT_FILENAME} !-f
# existing folder
RewriteCond %{SCRIPT_FILENAME} !-d
And if using symlinks:
# enable symlinks
Options +FollowSymLinks
# existing symlink
RewriteCond %{SCRIPT_FILENAME} !-l
// addition
Your .htaccess file should look like this:
RewriteEngine on
Options +FollowSymLinks
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-l
RewriteRule ^(([\w/-]+)?[\w-])/?(?!:\.html)$ http://domain.com/$1.html [L,R=301]
RewriteRule ^(([\w/-]+)?[\w-])\.html$ test/index.php?slug=$1 [L]
This is supposed to redirect /slug-text to /slug-text.html
RedirectMatch ^/([\w-]+)/?$ http://domein.com/$1.html
This is in the case when slug-text is only letters, digits, – and _.
Rewrite slug-text.html to a php file and pass the slug as a param:
RewriteRule ^([\w-]+)\.html$ test/index.php?slug=$1 [R,L]
If you have both line in your .htaccess the first one will do the redirects from the legacy URLs to the new ones and the second one will process the request.

Apache mod_rewrite conditions

i've got a problem using apaches module rewrite (browser friendly urls). I want to rewrite each request to an specified php document expecting any request containing a given string:
RewriteBase /folder/directory/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?url=$1 [PT,L]
How to include a condition to redirect requests including "teststring" (ignoring pre and post text) to another directory? I want to redirect jQuery ajax calls to another directory directly!
Finally got the solution: .htaccess mod_rewrite - how to exclude directory from rewrite rule
I'm not sure if I understand what exactly you want. But here's my take on it:
RewriteRule ^(.*)teststring(.*) newdirectory [R,L]

How to rewrite URL to include variables and remove php while allowing directories

I have the following htaccess
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/?user=$1
which works as expected for example
http://example.com/index.php?user=USERNAME -> http://example.com/USERNAME
However I have created a form on the page index.php which posts to /directory/save.php
How do I remove .php while allowing for the directory so that I can post to /directory/save/ instead?
if it is going to one and only such file in /directory then probably hard code it by adding following before the above rules?
RewriteRule ^directory/save$ /directory/save.php [L]
directory/ might have it's own rewrite rules and not have a physical save.php, that's why !-f might not work. Try adding a new rewrite condition to stop rewriting for directory/
RewriteCond %{REQUEST_URI} !^directory
Try to check this one if it's rewriting /directory/save.php file to directory /directory/save/
RewriteCond %{REQUEST_URI} ^/directory/save\.php$
RewriteRule ^(.+) /directory/save/ [NC]

.htaccess not allowing sub-directory to work

Here is the .htaccess file
RewriteEngine on
RewriteCond $1 !^(index\.html|index.php|administrator|system|template|js|lib|favicon\.ico|robots\.txt)
RewriteRule ^(.*)$ /index.html?tpl=$1 [L]
Options +FollowSymlinks
However what is happening is that all the following folders wont allow me to go into them and view a PHP file.
|administrator|system|template|js|lib
I thought by putting the files in RewriteCond that it would allow a user to still go to http://example.com/news/happy which then would go to the index.php?tpl=etc etc but it has stopped me from going into any subdirectory like
http://example.com/system/index.php
I don't know if this would work for you. But what I do is to add this rules to load calls to any .php file without the .php ending. You can call both, with or without that ending.
For example, you can call my_url.com/myfolder/myfile and it will load myfile.php, with the friendly URL.
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php
i would like to recommend that you read about mod rewrite first
1 - put that line at top
Options +FollowSymlinks
That line ask your server to follow symlinks but i would like recommend that you use the more secure option "SymLinksIfOwnerMatch"
Source:
http://httpd.apache.org/docs/2.2/mod/core.html#options#FollowSymLinks
RewriteEngine on
Enables or disables runtime rewriting engin
Source:
http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html#rewriteengine
RewriteCond $1 !^(index\.html|index.php|administrator|system|template|js|lib|favicon\.ico|robots\.txt)
Here you go . that rule ask the web server to add rewrite Condition to ignore everything listed in your regex
also i have added regex explain for you
!
not equal
^
Start with
RewriteRule ^(.*)$ /index.html?tpl=$1 [L]
you are asking to write everything else to index.html?tpl=$1
** I think you mean index.php i will assume that you don't need the query string
i would like to recommend using a better way to handle the excluding
RewriteEngine On
Options +FollowSymLinks
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(index\.html|index.php|administrator|system|template|js|lib|favicon\.ico|robots\.txt)
RewriteRule ^(.*)$ /index.html?tpl=$1 [L]

Categories