Apache mod_rewrite path to query string for specific path format - apache

I've been working on this for weeks. I want to be able to use a friendly URL to pass variables to a PHP script. For example, if someone uses this URL:
https://example.com/foo/bar/who
I would like my PHP script to receive this:
https://example.com/index.php/?var1=foo&var2=bar&var3=who
The catch is that I ONLY want to do this rewrite when there are three vars in the path. If there are fewer or more than three, I do not want to rewrite the URL.
I've seen several other explanations related to this type of rewrite but nothing quite like this.
This is almost working, but not quite. I only want the rewrite done if there's something present for those first three variables. I know this is incomplete, but with this method at least the REQUEST_URI contains the values I can parse. But again, I only want to do this when there are three vars in the path.
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule !^index\.php/([^/]*)/([^/]*)/([^/]*)$ index.php [L]
Thank you.

You were pretty close, have it this way. Please make sure you clear your browser cache before testing your URLs. You had already created back references only thing you needed to use them, which I have added those now.
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]*)/([^/]*)/([^/]*)$ index.php?var1=$1&var2=$2&var3=$3 [L]

Related

htaccess mod_rewrite - rewrite folder and file to parameters

I have the follow folder structure for images:
http://www.localhost/memes/01/blaa.jpg
http://www.localhost/memes/02/blaa2.pg
etc.
Now I want to move the structure but the old one must still be available for PHP file.
So it should be rewritten like:
http://www.localhost/memes/01/blaa.jpg
to:
http://www.localhost/memes/?folder=01&pic=blaa.jpg
or to:
http://www.localhost/memes/?pic=blaa.jpg (ignoring the subfolder of memes)
yes it's www.localhost for what ever reason and I don't mind it so far :D
Could you please try following, written and tested with your shown samples. Please make sure you clear your browser cache before testing your URLs.
RewriteEngine ON
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^memes/([^/]*)/(.*jpg)$ memes/?folder=$1&pic=$2 [NC,L]

Rewrite files with certain extension to a specific directory

So... I have a few million PNGs with unique names spread across a complicated structure of directories that goes 15-20 levels deep, and I want to move them into a directory /my/special/directory/
I can't figure out a way to do this with rewrites (not redirects)
I have tried:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/\.]+).png?$ /my/special/directory/$1.png [R]
But this works on the first level only (root). I have also tried
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([a-zA-Z0-9/]+)([^/\.]+).png?$ /my/special/directory/$2.png [R]
But it doesn't work at all. How should I write this?
I am checking for the image not to exist because there are other directories in this vhost that contain images and will remain as they are.
TIA
I don't really understand that pattern you try: ^([^/\.]+).png?$...
Why the ? at the end? And why the explicity denial of dots in file names? The reason this only works for "the first level" certainly is that you explicitly deny acceptance of paths with contained / which happens to be the folder delimiter...
Also just use [L] instead of [R] since you do not want a redirection.
This gives us:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)\.png$ /my/special/directory/$1.png [L]
In case you have to rewrite such that only the file name is captured (depends on the structure of your links, actually), this would probably be a good start:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule /?([^/]+)\.png$ /my/special/directory/$1.png [L]
Note: there is no leading ^ in the second variant, since you are not interested in what path is specified before the last folder separator...

mod_rewrite - Removing index.php from URL (in subfolder)

I'm trying to get an API working (locally, for now), which lives in a subfolder. I've been trying every example I can find, but all are ending up in 404 errors.
I have this URL:
http://127.0.0.1/~owner/personal/api/v1/index.php/tasks
I want to be able to use this:
http://127.0.0.1/~owner/personal/api/v1/tasks
Eventually, it will become this:
http://api.mydomain.com/tasks
I just can't seem to get my .htaccess rules setup correctly. This keeps getting suggested, but does nothing:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
What am I missing?
Update
I have setup my virtual hosts to use http://api.local/ instead of the previously used addresses.
Accessing http://api.local/index.php/tasks works.
Accessing http://api.local/tasks does not.
Maybe part of your problem is your development environment. You are using a local server to do this on with several subfolders deep and I think it's messing with your .htaccess depending on the location.
If your .htaccess is in the root of your website http://127.0.0.1/.htaccess then it's not going to work properly.
Make sure it's in the same directory as your index.php file and make sure /~owner/personal/api/v1/ is your document root for your dev environment as specified in your apache config file.
Then you can test out your htaccess rules and see how they work. Your current rule should be ok providing /tasks won't be a real directory in the root.
On another note,
I always suggest using your real domain name so you could see how it works as if it were in production. You can do that by modifying your HOST file on your PC and the site will only available to you and you can access via yoursite.com. This quick easy guide will show you.
Try specifying the rewrite base.
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
You are using the parameters of RewriteRule backwards. You need this:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/?(.*?)/index.php(.+)?$ /$1$2
This means:
if it's not a file
and it's not a directory
and it looks like / (optional), possibly some more characters, then /index.php, then possibly some more characters, go to the URL without the /index.php part.
Note that I deleted the [L] for now -- it means "if the URL matches this rule, don't apply any more rules." You say you want to keep transforming it into http://api.mydomain.com/tasks, so you shouldn't use [L].

How to use mod_rewrite to direct anything but PHP pages to index.php?

I have a question that is a bit confusing. I'm trying to understand mod_rewrite but I am pretty confused by it.
What I'm trying to do is redirect all URLs such as /settings/account or /user/user123 to index.php. A PHP script (which I already created) uses $_SERVER['REQUEST_URI'] to break the URL down into pieces then uses include. For example it would include settings.php?page=account or user.php?uid=user123.
But if the URL is /settings.php?page=account or /user.php?uid=user123 I don't want it to be redirected through index. In other words, if the URl has a file extension, just go to that file, but if it doesn't (like /settings) go to index.php to process where it should go.
How can this be done? Thanks in advance for any suggestions!
If you don't want to use the commonplace redirect-every-url-which-has-no-corresponding-file approach, you can also try your approach. To redirect anything without dot to a common script, use:
RewriteRule ^([^.]*)$ index.php?path=$1
You might want to exclude some URLs still, like images/ or css/ etc. Use a simple RewriteCond before the rule then:
RewriteCond %{REQUEST_URI} !images/
RewriteCond %{REQUEST_URI} !css/
What you need is a RewriteCond directive with !-f and !-d patterns.
RewriteCond checks whether a user's HTTP request matches provided condition. In your case, you would want to check if a requested file (which is provided in a variable %{REQUEST_FILENAME}) already exists on your document root using the !-f postfix. Similarly, if you want indexing in directories, you can add the same pattern with !-d, which will check if requested directory is on your document root.
So these two lines before the actual RewriteRule would do the trick:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

How do I get apache RewriteRule working correctly for a subdomain?

I just setup a subdomain with the following RewriteCond:
RewriteCond $1 !^search.php$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/?([^/]+)$ search.php?q=$1 [L,NS]
I'm using the same rewrite condition on my main domain and it works perfectly. However, when I set it up on the subdomain, it simply outputs "index.php" when going to http://sub.domain.com
Every page on the subdomain outputs the page name in the body instead of processing the code, except for the search page, which appears to be working correctly.
What can I do to correct this issue?
I haven't played with your exact regex with mod_rewrite, but if I was looking at writing that regex in another engine, I would have to escape the slash. Also, given that $ is used to indicate a back reference, would that need escaping too (would your $ symbols in the regex be necessary as there is likely to be more text in the URI and it is not matched at the end of a string)?
I would try
RewriteCond $1 !^search.php$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/?([^\/]+)$ search.php?q=$1 [L,NS]
One other thing. Normally $ at the end of a regex means "only match if this is the end of the string". So from that, if RewriteCond is matching on ^search.php$ but the URL is search.php?q=... then I would think that this wouldn't match because search.php is not the end of the string. So that would look like the following (assuming you don't need to change anything else from your original).
RewriteCond $1 !^search.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/?([^/]+)$ search.php?q=$1 [L,NS]
In the main config the path always begins with / and you need an absolute path:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !^search.php$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/([^/]+)$ %{DOCUMENT_ROOT}/search.php?q=$1 [L]
In an .htaccess you need a RewriteBase which is stripped from the url (no / in the Rule now) and the path is relative.
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !^search.php$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]+)$ search.php?q=$1 [L]
Several things come to mind here:
I have a few suggestions/comments/gotchas. Hopefully one of them is useful to you:
Make sure search.php isn't just echoing out its $_GET parameters. While this sounds obvious in retrospect, it's one of the more overlooked solutions.
RewriteRule works slightly differently when you specify it in a server configuration file than if you specify it in an .htaccess. Specifically, ^/ is wrong in a server config version as the entire URL is used (http://sub.domain.com/blah).
Make sure no other rewrite rules are being processed for this subdomain first, either in the main httpd.conf / apache2.conf or .htaccess.
Make sure RewriteEngine On appears in your configuration, as it is activated per-VirtualHost.
The NS flag will ignore redirects done using a relative Redirect or relative RewriteRule.
It sounds like the pattern '^/?([^/]+)$' may not be matching at all.
I'd activate RewriteLog, crank RewriteLogLevel to level 3 or above, and see if your pattern is matching at all. If not, start with a simpler pattern, and then work your way to a more complex pattern.
Or, something else is matching the pattern, so the request never gets to 'RewriteRule ^/?([^/]+)$' at all. You will see this in the RewriteLog.
I believe I recently had a problem where '^/' didn't match in certain cases on a Virtual Host. But '/' worked. The folks in the #httpd on Freenode.org helped me. If I can find this in my notes, I'll post it here.