Rewritten URL shows 404 errors - php

I have re-written my URL from website.com?id=1 to website.com/1 and I'm getting 404 errors when trying to access the page and cannot think of a solution to this. I'm currently developing a link shortener. This is required so users will be able to access their shorted links.
This is my current .htaccessfile
RewriteEngine On
RewriteCond %{THE_REQUEST} ^(GET|HEAD)\ /(index\.php)?\?id=([0-9]+)([^\ ]*)
RewriteRule ^ /%3?%4 [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([0-9]+)/?$ /?id=$1 [L,QSA]
I cannot figure out whether this has something to do with the .htaccess file or if I need to add something else to my php code.
Would someone have some sort of idea? Thanks.

You need to explicitly rewrite back to index.php in your second rule. By the time rewrite rules are processed the DirectoryIndex directive has already been processed (or may never be processed at all - it depends a little on your virtual host configuration and in what scope the DirectoryIndex directive was declared).
The end result of this is that you need to explicitly rewrite the request to the script that you want to handle the request, you can't just rewrite it to the root of a directory. Try changing your second rewrite rule to:
RewriteRule ^([0-9]+)/?$ /index.php?id=$1 [L,QSA]
On a personal note, it's interesting to see someone else use the %{THE_REQUEST} approach to this problem, this is an idea that I myself only recently came up with, although presumably I am not the first to do so. For the benefit of future visitors, here is a related post that explains why this requirement would come about and the thinking behind it.

I think you have written wrong rewrite rules.
They must be something like this:
for example.com/website.php?id=x..
RewriteEngine On
RewriteCond %{QUERY_STRING} ^id=([^/]+)$
RewriteRule ^website\.php$ %1/ [L]
as discussed here: https://stackoverflow.com/a/4951918/2274209
Hope this will solve your query.

Related

Rewrite/hiding some URL in .htaccess

I'm trying to get right syntax for .htaccess without any result...
I've a URL structured as domain.com/app/public/pageName .
It's working fine but I would "hide" the 'app/public/' part in browsers, basically doing something like:
[real URL] domain.com/app/public/pageName -> domain.com/pageName [what users type and see in browsers]
I think in that way it should be more readable and seo-friendly.
As I understood from docs (and maybe it's wrong because it's not working...) I should tell to Apache to map/redirect all URL like domain.com/pageName to domain.com/app/public/pageName , but only internally, in order to show the minimal URL in users' browsers.
Right now I have something like:
RewriteEngine on
#RewriteBase /app/public/
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)$ https://localhost/app/public/index.php?url=$1 [QSA,L]
(I'm using full URL with https://... in order to get something that will be quick and easy to adapt when I upload all to my hosting, is it right?).
Problem is that RewriteRule actually change the URL, because it perform a redirect and URL rewrite it's not handle internally.
So, first of all: is it possible what I'm trying to do? If so, how can I handle the URL rewrite only internally?
Everything should be uploaded to a shared hosting, so I don't have other than .htaccess.
Anyway, I can consider to upgrade to a vps if there are not other possibilities...
Thanks!
==============
EDIT (should be more clear now)
tl;dr version:
I'm looking for a method that let users to type domain.com/pageName (and they will see that address in their browsers) and rewrite internally that URL in order to point to domain.com/app/public/pageName.
==============
More: after /app/public/ there can be an arbitrary number of elements, separated by / . All of these elements are appended at the end of the URL after index.php. At the end URL looks like:
domain/app/public/index.php?url=lot/of/elements/here
This is already working with the RewriteRule posted above, I would keep that too.
Thanks!
This is working fine for me, Hope it will work for you as well.
Check .htaccess here
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_URI} ^/app/public
RewriteRule ^app/public/(.*)$ /$1 [L,QSA]
Just for reference, I found a solution, maybe will be usefull for someone.
Basically I moved .htaccess to the root server (instead of /app/public directory) and changed the RewriteRule as follow:
RewriteEngine on
RewriteBase /app/public/
#RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [PT]
Now it's working (at least on localhost).
What do you think? Are there any side effects with this config?

How to automatically make pretty urls

I have a site that I'm working on, but I'm annoyed that I have to work with ugly URLS. So, I have a URL of http://example.com/user.php?id=54 and another of http://example.com/foobar.php?name=Test.
How could I convert both of them to pretty URLS without adding it to .htaccess for every URL I want to make pretty?
example.com/user.php?id=54 => example.com/user/54
example.com/foobar.php?name=Test => example.com/foobar/Test
I have this in my .htaccess file:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1\.php -f
RewriteRule ^([^/]+)/?$ $1.php [L]
RewriteRule ^$1/$3/? /$1.php?$2=$3 [NC]
Thanks,
Lucy
My full .htaccess file:
# include classes on every page
php_value auto_prepend_file Resources/Classes.php
# add custom Directory Indexes
DirectoryIndex index.php Default.php Down.php
# begin routing to pretty URLs
Options +FollowSymLinks
RewriteEngine On
RewriteRule ^/(?!Resources)([0-9a-zA-Z-]+)/([0-9]+) /$1.php?id=$2 [NC]
RewriteRule ^/(?!Resources)([0-9a-zA-Z-]+)/([a-zA-Z-]+) /$1.php?name=$2 [NC]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*?)/?$ $1.php [L]
Try this
Options +FollowSymLinks
RewriteEngine On
RewriteRule ^user/([0-9]+) /user.php?id=$1 [QSA,L]
RewriteRule ^foobar/([0-9a-zA-Z-]+) /foobar.php?name=$1 [QSA,L]
if you want global rule you can make
Options +FollowSymLinks
RewriteEngine On
RewriteRule ^([0-9a-zA-Z-]+)/([0-9a-zA-Z-]+) /$1.php?parameter=$2 [NC]
or more specifically
Options +FollowSymLinks
RewriteEngine On
RewriteRule ^([0-9a-zA-Z-]+)/([0-9]+) /$1.php?id=$2 [NC]
RewriteRule ^([0-9a-zA-Z-]+)/([a-zA-Z-]+) /$1.php?name=$2 [NC]
when argument will be a string it will pas name parameter and when argument will be integer there will be id parameter passed.
I may delete this answer in the future as it might be specific to my setup.
I recently discovered, using Apache, that anything after the URL was populating the PATH_INFO environment variable. This means that given your example, example.com/user/54, if user was a script the server could process, anything after it would be populated into PATH_INFO; in this case it would look like /54. This is a great find because with proper structure, you could make your own router similar to Rails.
I would create some landing page (e.g., index) which is going to be your application router: example.com/index/<model>/<id>/. Inside index would be your routing code. I'll use Perl to demonstrate, since it's better than PHP :) Note that index could be called anything that Apache can process (e.g., router.php, index.pl, application.rb); though, removing the extension adds to the beauty of the URL.
index:
#!/usr/bin/perl
use 5.012;
# Retrieve what you're looking for; obviously not production-ready
my ($model,$id) = $ENV{PATH_INFO} =~ m{^/([^/]+?)/([^/]+)};
# route the request
given($model){
when('user'){ callUser($id); } # callUser defined elsewhere, perhaps another script
when('foobar'){ callFoobar($id); } # callFoobar defined elsewher, perhaps another script
default { makePageDefault(); }
}
http://example.com/index/user/1: passes 1 to callUser()
http://example.com/index/foobar/5: passes 5 to callFoodbar()
http://example.com/index/user: calls makePageDefault() because regex was not smart enough to handle anything without an ID
http://example.com/index/diffmodel/1: also calls makePageDefault(), since we don't handle diffmodel didn't exist
The script above is not production ready because it doesn't perform any sanitation and doesn't handle all the use cases you will need. My guess is you want something similar to Rails (e.g., example.com/movie/1/edit). While Apache is designed to handle the routing for you, there is some convenience in being able to manage this close to where your application code lives.
I have not implemented this method, so I'm curious to hear if this is something used and if there's any reason not to trust it.

htaccess Redirect Causes Errors

I'm working on a website that has been built sloppily.
The website is filled with regular links that are translated into the corresponding .php pages by the .htaccess page.
This is it:
RewriteEngine on
RewriteRule ^koral/(.*)/$ page.php?name=$1
RewriteRule ^koral/(.*)$ page.php?name=$1
RewriteRule ^(.*).html/(.*)/(.*)/(.*)$ cat.php?cat=$1&page=$2&order=$3&dir=$4
RewriteRule ^(.*).html$ cat.php?cat=$1
RewriteRule ^(.*)/(.*).html$ product.php?cat=$1&product=$2
<IfModule mod_security.c>
SecFilterEngine Off
</IfModule>
First of all, I would love some help regarding whether or not this page has everything it should. I've never messed with it before.
Secondly and my main issue, if, for example, I would write the address www.thewebsite.com/foobar.html, it would be translated into www.thewebsite.com/cat.php?cat=foobar by the .htaccess page, and it would give a database error (and reveal information about the database).
I've put a check into cat.php which checks if the category exists, but I can't redirect the user to the 404 error page. There's a page called 404.shtml in the website, but redirecting the user to it causes the .htaccess to just change it again to cat.php?cat=404.
Is the way they used the .htaccess page normal? Should I change this system?
And how are users sent to error pages? From what I understood the server should be doing it on its own?
I would love some clarification... There is some much about this subject I don't understand.
Update:
This is my new .htaccess page
RewriteEngine on
RewriteRule ^error.php?err=(.*)$ Error$1.html
# Only apply this rule if we're not requesting a file...
RewriteCond %{REQUEST_FILENAME} !-f [NC]
# ...and if we're not requesting a directory.
RewriteCond %{REQUEST_FILENAME} !-d [NC]
RewriteRule ^koral/(.*)/$ page.php?name=$1
RewriteRule ^koral/(.*)$ page.php?name=$1
RewriteRule ^(.*).html/(.*)/(.*)/(.*)$ cat.php?cat=$1&page=$2&order=$3&dir=$4
RewriteRule ^(.*).html$ cat.php?cat=$1
RewriteRule ^(.*)/(.*).html$ product.php?cat=$1&product=$2
<IfModule mod_security.c>
SecFilterEngine Off
</IfModule>
Because the redirecting is in the code and the user cannot see it, I allowed myself to write the link in a non-clean way. I tried turning it into a clean URL but the following does not do anything:
RewriteRule ^error.php?err=(.*)$ Error$1.html
Can someone please help me understand why? I thought since error.php is a real page, I should put it before the conditional but it didn't work. BTW, I saw in an article about .htaccess that the page should start with Options +FollowSymLinks. It seems to me that everyone sort of has their own way of writing it. Is there a guide or something like that, which I can be sure is authentic and covers all the bases there is about .htaccess?
Thank you so much!!
Using rewrite rules to work around links to .html pages that don't exist is unusual in my experience, but it's really just a different take on "pretty" URLs, e.g. www.thewebsite.com/foobar/ gets routed to cat.php?cat=foobar on the backend.
Your 404 issue is different. You need to be able to display error pages.
One option here is to rewrite requests as long as they don't request an existing file. This is very common for serving up static content like images, CSS files, and the like. To do this, you can use the -d and -f options to RewriteCond, which apply when requesting a directory and file respectively:
RewriteEngine On
# Only apply this rule if we're not requesting a file...
RewriteCond %{REQUEST_FILENAME} !-f [NC]
# ...and if we're not requesting a directory.
RewriteCond %{REQUEST_FILENAME} !-d [NC]
RewriteRule ^([^.]+)\.html$ cat.php?cat=$1 [L,QSA]
Now, requests to 404.shtml should go through, because you're requesting an existing file on the filesystem.
Note that the RewriteConds only apply to the single RewriteRule that immediately follows. For additional RewriteRules, also include additional RewriteConds.
Your regex is wrong anywhere. Literal dot needs to be escaped using otherwise it will match any character. Also it is better to use L and QSA flags to end each rule properly.
RewriteEngine on
RewriteBase /
RewriteRule ^koral/([^/]+)/?$ page.php?name=$1 [L,QSA]
RewriteRule ^([^.]+)\.html/([^/]+)/([^/]+)/([^/]*)/?$ cat.php?cat=$1&page=$2&order=$3&dir=$4 [L,QSA]
RewriteRule ^([^.]+)\.html$ cat.php?cat=$1 [L,QSA]
RewriteRule ^([^/]+)/([^.]+)\.html$ product.php?cat=$1&product=$2 [L,QSA]

Seems like POST values are lost when .htaccess RewriteRule used. GET values are OK. How to fix?

Several days ago I had a question about removing index.php from the address bar, so the address of the page looks shorter and better. The shortest solution of this problem was (RewriteRule ^index.php / [L,R=301] in the .htaccess file). And it works!
Since I put that string into the .htaccess, some pages are redirected to the main page. I spent a lot of time to guess, why. As I understand, the answer is: with RewriteRule ^index.php / [L,R=301], $_POST parameters are not sent to the next page. $_GET parameters are OK.
Once I remove RewriteRule ^index.php / [L,R=301] from .htaccess, everything becomes fine as usual.
Why does it happen and how to fix that?
Thank you.
The [R] flag will incur a redirect. And user-agents issue a redirect as GET request. There is nothing that can be done if you really want to shorten URLs down to the / root path.
You could however block POST requests specifically from being rewritten/redirected:
RewriteCond %{REQUEST_METHOD} !POST
RewriteRule ^index.php / [L,R=301]
You could try using [L,R=307] instead. 307's must not change the request-method according to the spec, but I don't know how browser implemented 307.
But the root of the problem is the use of <form action="____/index.php" ...
Just leave the action empty to POST to the current url e.g.
I'm using something like:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_URI} !^/(css|images|js)/
# don't rewrite existing files, directories and links
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
# rewrite everything else to index.php
RewriteRule .* index.php [L]
</IfModule>
And its working for all requests, rewriting it via index.php file.
If you need to redirect 301 (which stands for Moved Permanently code) check out this question: Is it possible to redirect post data?
POST values will NEVER survive an external redirect (the R=301), it's a security liability, so browsers will never support that. Remove the R=301 and you will be fine. You just should alter all existing links to the page to the shorter/prettier one (<a>'s but also form actions etc.)
I had the same problems but my htacces was like this:
RewriteEngine on
RewriteRule .* index.php [NC]
Just change NC for L and everything works fine.
Final code:
RewriteEngine on
RewriteRule .* index.php [L]
In My case I used .htaccess.
Refer : PHP $_POST not working?
i.e
action="booking.php" to action="booking" worked for me

Mod rewrite user URL

I'm lost here. I'm using this script to give users the opportunity to enter their username lijke this:domain/username
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/?$ userpage.php?user=$1 [NC,L]
</IfModule>
This works fine. However, every user has pages I must link to: Video, Music, Images etc...
So I need something like:
domain/username/video
In php code it must be something like:
user.php?user=test&page=video
And one other question: What is the preferable way to link in this situation?
userpage.php?user=test&page=video
or
/test/video
And finally: Is it possible to deny the possibility to enter the url:
domain/userpage.php?user=test&page=video? Instead just always show: domain/test/video
Thanks in advance
I'm not 100% sure what you're asking? Do you need to change the rewrite rule to match the URL site.com/moonwalker/videos? You could try this:
RewriteRule ^([^/]+)/(images|videos|music)/?$ userpage.php?user=$1&page=$2 [NC,L]
Update
Just a quick note on the domain/member/videos URL structure. That could end up causing you problems in the future. For instance what if you decide to have a single page that shows all member videos? You'd probably want to URL to look something like site.com/members/videos. That's a problem, because the rewrite rule will also match that, but "members" isn't a member username.
I would probably structure my member page URLs like site.com/user/moonwalker/videos so it doesn't clash with future rewrite rules. You would change the above rewrite rule to this:
RewriteRule ^user/([^/]+)/(images|videos|music)/?$ userpage.php?user=$1&page=$2 [NC,L]
Then later on you can add a rewrite rule like:
RewriteRule ^members/(images|videos|music)/?$ allusers.php?page=$1 [NC,L]
To show all member videos.
Yes, it is possible by looking at the request line:
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /userpage\.php[?\ ]
RewriteRule ^userpage\.php$ - [F]
This is necessary as the URL path could already be rewritten by another rule and thus using just RewriteRule would match those already rewritten requests too.

Categories