Making RewriteRule to mock reddit's or Rails? - php

For fun I want to make a reddit clone in php. I have mostly java experience but know my way around php, if that matters at all. I also have very limited experince with Rails 3 and I believe how rails deals with URLs is also close to how I want to handle it.
So far in a .htaccess I have:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ /index.php/$1 [L]
This routes every page to index.php where I parse the URI and handle requests with a switch. I know this isn't scalable in the long run but I want to get off the ground.
My next stepis to add a / automaticly at the end of a URL like localhost/r/all so it becomose localhost/r/all/ I want and have tried to make a RewriteRule like:
RewriteRule ^/?(.+)$ /$1/ [R]
This gives a 500 error. I think it is because it gets stuck in an infinite loop of redirect because /$1/ will equal ^/?(.+). So I need something like:
RewriteRule ^/?(.+)Does not end in a forwardlash$ /$1/ [R]
How can I do this? I see that the ! charecter can be used to denote a condition it should not match, but I am having trouble getting this to work.
Any Advice is appreciated.
EDIT:
getenv("DOCUMENT_ROOT") //gives /var/www
I have /var/www/index.php living, well in /www.
My .htaccess file which I am making these changes to lives in /var.
I have .htaccess in /var because in my httpd.cong I have this:
<Directory /var>
AllowOverride All
</Directory>
I first tried to have it as
<Directory /var/www>
and putting .htaccess in www but it is never read. I know it is not read becuase I put garbage in it and there is no error. But, if I have garbage in it when it is in /var and the Drectory directive specifies /var I get an error.

Try this (untested):
# Turn mod_rewrite on, yada yada yada
RewriteEngine On
RewriteBase /
# We'll want to do the redirect before rewriting anything
# Files obviously don't have a trailing slash, and directories require one - so
# we only need to check if the file exists
# I'm not actually sure if mod_rewrite understands non-capturing groups though
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/?((?:.+?)[^/])$ http://%{HTTP_HOST}/$1/ [L,R=301]
# Do the rewrite
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ /index.php/$1 [L]
I get the feeling that the problem with your attempt is likely to be the order of the rules, a missing RewriteCond on the redirect RewriteRule and/or that you didn't put a L flag in the redirect RewriteRule - but the above regexes make me happier than yours do, because they are a little more specific about what they match.
I'm not actually sure if mod_rewrite supports all the regex features I have used above, so if you continue to get an error that might be why - come back here if you do have a problem and I'll look at it more closely.

Related

Specific redirection in .htaccess does not work

I have a specific problem with my mod_rewrite configuration that I cannot resolve. I am no admin, therefore I'm kindly asking for a collective advice :) Please note - it's not a general question about redirection, but very specific one.
Story
I have a shared hosting with access to FTP and ability to create my own .htaccess files. This shared hosting had plenty of files and directories before I created the website, so logical step for me was to place everything inside new-site folder.
Then I had to create custom rewrite rules so that everything under example.com points to new-site.
CONFIG
So I came up with the following config.
# (...) other rules
# 1. Make sure that /new-site/ is not a duplicated content
RewriteCond %{REQUEST_URI} ^/new-site/
RewriteRule ^/new-site/(.*)$ /$1 [R=301,L]
# 2. Make sure that example.com is internally handled by files in '/new-site'
RewriteCond %{REQUEST_URI} !^/new-site/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /new-site/$1
RESULTS
Rule marked with 2. works fine, my site is accessible as I want. However I didn't want https://example.com/new-site/ to be found on the server by bots and treated by a duplicated content, so I added rule 1..
This rule, however, doesn't seem to have any effect! I looked it up with CURL and request is handled immediately with a 200 status. I'm banging my head against the wall and experimenting with other variants of it, but everything fails.
What I'm after is pretty darn simple:
Make every request to the root domain be handled by website which is stored in /new-site/
Make sure that direct call to https://example.com/new-site/(.*) is redirected with 301 status back to the domain root.
What am I doing wrong?
EDIT
I've noticed that my setup seems to be doing far better if I remove a child .htaccess file under /new-site/ subfolder. I didn't mention it in my original question because there is nothing special about it (just some SEO rewrites).
RewriteEngine on
DirectoryIndex index.php
RewriteRule ^products$ products.php
# (...) similar rewrites
Old answer: RewriteRule does not accept leading slash. Try to change to
RewriteRule ^new-site/(.*)$ /$1 [R=301,L]
Edit:
Version that is provided by you will forward to the cyclic redirection. To avoid it, I think, you can use such .htaccess
RewriteEngine on
RewriteRule ^new-site/ - [R=404,L]
# 2. Make sure that example.com is internally handled by files in '/new-site'
RewriteCond %{REQUEST_URI} !^/new-site/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /new-site/$1 [L]
Direct asking /new-site/* wil receive 404 error, while url exaple.com/* wil be redirected to /new-site
And notice that if there are files with the same name, for example, /r.jpg and /new-site/r.jpg, the last never be achieve
Your first rule never matches because it must not begin with a leading slash.
With RewriteRule, you only need a leading slash if you're directly in httpd.conf or before Apache v2.4 i think.
While you have a good idea, your first rule will cause an infinite redirection loop if it's working. You have to use THE_REQUEST to match direct user request only.
You can put this code in /.htaccess
# 1. Make sure that /new-site/ is not a duplicated content
RewriteCond %{THE_REQUEST} \s/new-site/([^\s]*)\s [NC]
RewriteRule ^ /%1 [R=301,L]
# 2. Make sure that example.com is internally handled by files in '/new-site'
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^((?!new-site/).*)$ /new-site/$1 [L]
Also, you'll have to add this line in /new-site/.htaccess (to avoid automatic override)
RewriteOptions InheritBefore

.htaccess url rewriting not working?

I'll be honest in saying I have very little experience with .htaccess as I've always wanted to stay away from it as best I can. However, I've recently wanted to tidy up my urls and I've found that it's possible through .htaccess and rewriting.
Basically, I want to rewrite a url like:
www.mysite.com/profile.php?id=48194
To something like:
www.mysite.com/profile/48194
Here's the code I have currently:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php
RewriteRule ^profile/(.*)/$ profile.php?id=$1
The line I'm trying to use is on the very bottom, RewriteRule ^profile/(.*)/$ profile.php?id=$1. The rest is used to remove the page extensions from the urls. I've changed $1 to $2 thinking perhaps it was conflicting with the code above, but nothing changed.
I also removed all the code except for RewriteEngine on and the last line thinking maybe the codes were conflicting but, again, nothing changed or worked. The rest of the code does work, removing the extensions from urls that is, so I know the rewrite thing is on.
Could someone try to break down and explain what I did wrong and how all this works? As well as providing a working example of the thing I'm trying to accomplish?
Thanks in advance!
Change order of your rules and use MultiViews option. Option MultiViews is used by Apache's content negotiation module that runs before mod_rewrite and and makes Apache server match extensions of files. So /file can be in URL but it will serve /file.php.
RewriteEngine on
RewriteBase /
RewriteRule ^profile/([^/]+)/?$ profile.php?id=$1 [L,QSA,NC]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1\.php -f [NC]
RewriteRule ^(.+?)/?$ $1.php [L]

finding the names and view of all apache environment variables

I just want to know if there is a link with all of the environment variables in apache and what they look like when they are printed out.
The reason is i am trying to write some regex for .htacess mod_rewrite, but i don't know what these variables are printing. it's hard to write regex when im not sure what is printed, i keep getting them wrong.
Is there a list somewhere i am missing.
Trust me googling is easier than posting a question and waiting for response and people not quite sure what you are asked.
I can't seem to find a google source.
Eg %{THE_REQUEST} GET /index.php HTTP/1.1
The real problem i am having is i have this .htaccess file
# Do not remove this line, otherwise mod_rewrite rules will stop working
RewriteBase /
Options +Multiviews
AddHandler application/x-httpd-php .css
AddHandler application/x-httpd-php .js
Options +FollowSymLinks
RewriteEngine On
#NC not case sensitive
#L last rule don't process futher
#R 301 changes the url to what you want
RewriteCond %{HTTP_HOST} !^example\.host56\.com
RewriteRule ^(.*)$ http://example.host56.com/$1 [R=302,L]
RewriteRule ^demo(.*)$ finished$1 [NC]
RewriteCond %{REQUEST_URI} /
RewriteRule ^(.*)$ home/$1
I keep getting redirected to the error page
I am trying to get to
example.host56.com/home/
But it keeps leading me to errors. The home folder has a index.php file inside of it as well
Here's a mod_rewrite variable cheat sheet: http://www.askapache.com/htaccess/mod_rewrite-variables-cheatsheet.html
The rule here:
RewriteCond %{REQUEST_URI} /
RewriteRule ^(.*)$ home/$1
Is looping. The reason is because the %{REQUEST_URI} variable always starts with a /, and you're not using either the "^" or "$" to denote matching boundaries, so that condition will always be true. Since it's always true, the rule will always be replied. And since the rewrite engine continually loops until the URI stops changing (or until you've reached the internal recursion limit, causing a 500 error), the pattern always matches. Try changing it to:
RewriteCond %{REQUEST_URI} !^/home/
RewriteRule ^(.*)$ home/$1
or
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ home/$1

.htaccess being ignored? Not redirecting like it's supposed to

Okay I'm trying to use Lando (landocms.com) and I'm trying to get the pretty urls option to work.
Basically by default Lando creates link like: domain.com/index.php/page. Supposedly, there is a way to remove the index.php so the links become: domain.com/page. I have created an .htaccess as directed, however it does not work.
Here is the .htaccess I am using:
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
</IfModule>
I have tried alot of variations, /index.php/, index.php? and plenty more but none work. According to HostGator everything should be fine. Any thoughts? I think I'm going crazy haha.
Thanks!
Rewriting for a CMS is a two-tier approach. First, you need to set your .htaccess (I have put a safer one here for you):
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .+ index.php [QSA,L]
Then, LandoCMS allows you to remove the index.php from the generated addresses, by means of turning on the appropriate setting in the administration panel. See this link for more information.
If the .htaccess content I've given you doesn't work, then simply use the one that the CMS has given you.
You want to remove the index.php part from any URL, but process the incoming, friendly URLs through index.php nevertheless
RewriteEngine On
# remove index.php and redirect client
RewriteCond %{ENV:REDIRECT_SEO} ^$
RewriteRule ^/?index.php/(.*) /$1 [R,L]
# process friendly URL
RewriteCond %{REQUEST_URI} !^/index.php/
RewriteRule .+ /index.php/$0 [E=SEO:1,L]
The environment setting E=SEO:1 prevents an endless loop.

How can I display the resulting path when using mod_rewrite?

I am having a heck of a time trying to get an apache mod_rewrite rule to work. The thing that is making the process the most difficult is that I have no way of knowing what the final output string is. I continue to get 404 pages, but that doesn't tell me much except that I did something wrong. Is there some method of echoing out the final rewrite rather than redirecting me to a 404?
. . . And just in case someone feels like helping me out with my original problem, I'm trying to make it so that anyone who goes to /server/root/to/folder/public_html/ gets redirected to /server/root/to/folder/public_html/destinationFolder/. Below is one of the hundreds of variations that I've tried:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond $1 !^(favicon\.ico|assets)
RewriteRule ^public_html/(.*) destinationFolder/$1 [L]
</IfModule>
You are using system paths. Apache mod_rewrite only works with URLs (PT flag is implied in .htaccess files), that's your first error.
public_html is normally the root directory. For example: http://mydomain.com
Then, a complete rule set could be something like this:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^(favicon\.ico|assets) [NC]
RewriteRule ^(.*)/?$ DestinationFolder/$1 [L]
Maps silently
http://mydomain.com/Anything
To:
http://mydomain.com/DestinationFolder/Anything
Except when anything is file favicon.ico or folder /assets
For permanent redirection, replace [L] with [R=301,L]
This is just an example. The rules and parameters have to be modified to meet the real requirements.

Categories