.htaccess rewrite commands acting not as expected - .htaccess

I have the following .htaccess file
RewriteEngine on
RewriteRule ^about$ about.html [NC]
RewriteRule (.*) index.php?url=$1 [L]
# Prevent loops
RewriteCond %{ENV:REDIRECT_STATUS} !200
# Map new URI to file
RewriteRule code/(.*) code.php?id=$1 [L]
first rule replace about with about.html - works
second rule
should have allowed me to write www.example.com/test-me - but when I var_dump $_GET["url"] I get: index.php while I expected $_GET["url"] to return test-me.
third rule:
not working - return 404 error. I expected file code.php on root to return with id as a URL param.
What I am trying to achieve is that when someone types www.example.com/lesson/lesson-name this will trigger the file code.php on the root and plant lesson-name as $_GET['lesson_name']
.

The second rule is triggering a the rewrite engine to start over and since you have no preceding condition (unlike the directive below) it ends up rewriting index.php on the second pass.
Your directives are also in the wrong order. The second rule that catches everything needs to go last. However, as stated, this rule catches everything - including all requests for static resources etc. So, you'll probably need additional conditions to prevent this.
Try the following instead:
Options -MultiViews
RewriteEngine on
RewriteRule ^about$ about.html [NC]
# Map "/lesson/<lesson-name>" to "/code.php?lesson_name=<lesson-name>"
RewriteRule ^lesson/(.*) code.php?lesson_name=$1 [L]
# Map everything else - for example "/index.php?url=test-me"
# Exclude static resources
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php?url=$1 [L]

Related

Rewrite rule in htaccess is not working

Here are the .htaccess rules:
RewriteEngine On
RewriteRule ^([^/]*)$ content.php?seourl=$1 [L]
RewriteRule ^pdf/([^/]*)$ content-single.php?seourl=$1 [L]
RewriteRule ^browsepdf$ browse.php [L]
RewriteRule ^browsepdf-([^/]*)$ browse.php?page=$1 [L]
RewriteRule ^download/([^/]*)$ download.php?pdf=$1 [L]
RewriteRule ^sitemap.xml$ xmlsitemap.php [L]
Options -Indexes
Here every URL is pointing to content.php?seourl=$1, even css, js and image files.
Here are some example URLs I need,
http://example.com/sjskjfsk21
http://example.com/asfasfasf43sf
http://example.com/pdf/fhfdhdh3432aaf
http://example.com/pdf/aisfyiahm2faf3
http://example.com/browsepdf
http://example.com/browsepdf-1
http://example.com/browsepdf-2
http://example.com/download/fjaskfjalsk3rs
http://example.com/download/usaydiy7aisydi
http://example.com/sitemap.xml
Can anyone please fix the .htaccess file.
Here every url is pointing to "content.php?seourl=$1"
Because your first (generic) rule catches all the requests. You need to change the order so you have the most specific rules first, and the most generic (catch-all) rules at the end. In your case you just need to move the first rule to the end. For example:
RewriteRule ^pdf/([^/]*)$ content-single.php?seourl=$1 [L]
RewriteRule ^browsepdf$ browse.php [L]
RewriteRule ^browsepdf-([^/]*)$ browse.php?page=$1 [L]
RewriteRule ^download/([^/]*)$ download.php?pdf=$1 [L]
RewriteRule ^sitemap\.xml$ xmlsitemap.php [L]
RewriteRule ^([^/]*)$ content.php?seourl=$1 [L]
NB: I backslash-escaped the dot in sitemap.xml to match a literal dot, otherwise it matches any character.
even css, js and image files.
You can make an exception for these static resources at the beginning of your file, before the existing directives. For example:
RewriteRule \.(js|css|png|jpg|gif)$ - [L]
For any URL that ends in any of the stated file extensions then stop processing the current mod_rewrite rules.
Alternatively (although perhaps marginally less efficient), you can prevent processing of requests for files that exist. Again, this goes before your existing mod_rewrite directives. For example:
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
However, this must now check every request for the existence of a file on the filesystem that maps to the request. (It could also be combined with the above rule if required.)
UPDATE: Bringing this together, we have:
# Exclude any existing files from being rewritten
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
# Specific rewrites
RewriteRule ^pdf/([^/]*)$ content-single.php?seourl=$1 [L]
RewriteRule ^browsepdf$ browse.php [L]
RewriteRule ^browsepdf-([^/]*)$ browse.php?page=$1 [L]
RewriteRule ^download/([^/]*)$ download.php?pdf=$1 [L]
RewriteRule ^sitemap\.xml$ xmlsitemap.php [L]
# Any other requests for the form "/<anything>"
RewriteRule ^([^/]*)$ content.php?seourl=$1 [L]

.htaccess rewrite if nothing specified

I'm trying to modify my .htaccess file to link to three different places, based on the input after the endpoint:
"/api" - Link to the API
"/ABCD123" - If it's a 7 character
alphanumeric string, link to a specific page
"/" - If nothing specified, or for any other inputs link to the homepage.
Here is my .htaccess file:
Options -Indexes
RewriteEngine On
RewriteRule ^api/(.*) ./api/index.php [R,L]
RewriteRule ^([a-zA-Z0-9]{7})$ index.php?l=$1 [L]
RewriteRule ^(.+)$ everythingelse.php [L]
Even though I have the [L] flag specified I always seem to get redirected to the everythingelse.php route, even if I have the 7 character string.
How can I rewrite to match this correctly?
Your rules are looping and executing more than once. L flag only breaks current loop but mod_rewrite can loop again and execute all the matching rules.
Options -Indexes
RewriteEngine On
# skip all files and directories from rewrite rules below
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
RewriteRule ^api/(.*)$ /api/index.php [R,L]
RewriteRule ^([a-zA-Z0-9]{7})$ index.php?l=$1 [L,QSA]
RewriteRule . everythingelse.php [L]

Apache Rewrite module, complex rules

I basically want to redirect all requests to index.php doesn't matter what, except those with certain REQUEST_URI. Those requests that look like image files, so have an ending like: .jpg or .png should be examined and if they are under the public/ folder (or any subfolders in any depth) and if they are they should be served and the rewriting process should stop here! If not, I want to redirect to a default image at public/errors/image-not-found.png and terminate rewriting process. The other exceptions are files that end with .js, .css, .html or .swf. They also should only be served if they are located under the public/ folder or any other subfolders. If not, a simple 404-Not found should be sent back. In either case of the last to the rewriting process need to stop of course.
Any other request should be redirected to index.php and appended as a query string. (even if the request points to a directory or to a file that is not under the conditions aforesaid, but exists, e.g: www.xyz.com/library/Database.php -> www.xyz.com/index.php?url=library/Database.php)
I have half-measure solution:This is how I redirect everything to index.php:
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
I append a visual explanation of what I want. Maybe this is clearer:
Basically, you don't want to do anything if the requested file exists in public/ or any of its subfolders. So, first we deal with those:
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/public/.*\.(html|css|js|swf|jpe?g|png|gif|bmp|ico)$ [NC]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
Now, that is over with. We now check whether an image was requested:
RewriteCond %{REQUEST_URI} \.(jpe?g|png|gif|bmp|ico)$ [NC]
RewriteRule ^ /public/errors/image-not-found.png [R,L]
Similarly for other static files:
RewriteCond %{REQUEST_URI} \.(html|css|js|swf)$ [NC]
RewriteRule ^ - [R=404,L]
Redirect everything now to index.php:
RewriteCond %{REQUEST_URI} !/index\.php$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f [NC]
RewriteCond %{REQUEST_FILENAME} !-d [NC]
RewriteRule ^.*$ /index.php?url=$0 [R,L]
Following series of rules should probably mimic the flow-chart:
# for public folder pass through
RewriteRule ^public/.+?\.(?:jpe?g|ico|png|bmp|css|js|html|swf)$ - [L,NC]
# for other images
RewriteRule ^.+?\.(?:jpe?g|ico|png|bmp)$ /public/errors/img-not-found.jpg [L,NC,R=302]
# for other css|js|html|swf URIs
RewriteRule ^.+?\.(?:css|js|html|swf)$ - [L,NC,R=404]
# everything else, route to index.php
RewriteRule ^((?!index\.php).+)$ index.php?url=$1 [NC,QSA,L]

Force redirect for certain files (based on referer) and trigger a 404 page otherwise

We distribute different versions of a software product through a single download link. The delivery is based on the referer in conjunction with a default value, which works fine. In addition the user should be redirected to a 404-page, in case the wrong filename was used.
At the moment the .htaccess-file looks like this:
# stop directory listing
Options -Indexes
# turn rewrite engine on
RewriteEngine On
# force 404 if file name is missing or wrong
RewriteCond %{REQUEST_URI} !^(download_mac\.zip|download_pc\.zip)$
RewriteRule (.*) 404/index.html [L]
# an example based on the referer
RewriteCond %{HTTP_REFERER} ^http://([^.]+\.)*domain-a\.com [OR]
RewriteCond %{HTTP_REFERER} ^http://([^.]+\.)*domain-b\.com
RewriteRule ^(download_mac\.zip|download_pc\.zip)$ domain_ab/$1 [L]
# last rule if no referer matches
RewriteRule ^(download_mac\.zip|download_pc\.zip)$ default/$1 [L]
So I have one issue and one additional question with this file:
The first rule, to force 404, is very greedy and gets the error page every time, no matter what URL is called. I also tried single statements like RewriteCond %{REQUEST_URI} !^download_mac\.zip$ without any effect. How can I fix this?
How can I get rid of the filenames in any other rule? I tried things like RewriteRule ^(.*)$ default/$1 [L] but it gives me a hard time and an 500 Internal Server Error.
You can avoid repeating your filenames by using an Env variable like this:
RewriteRule ^(download_mac\.zip|download_pc\.zip)$ - [E=ALLOWED:$1,NC]
RewriteCond %{ENV:ALLOWED} ^$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ /404/index.html [L]
RewriteCond %{ENV:ALLOWED} !^$
RewriteCond %{HTTP_REFERER} ^http://([^.]+\.)*domain-a\.com [OR]
RewriteCond %{HTTP_REFERER} ^http://([^.]+\.)*domain-b\.com
RewriteRule ^ /domain_ab/%{ENV:ALLOWED} [L]
RewriteCond %{ENV:ALLOWED} !^$
RewriteRule ^ /default/%{ENV:ALLOWED} [L]
You can just move the rewrite rule to the end. The other rules handle the valid cases and if none of them matches the last rule applies
# an example based on the referer
RewriteCond %{HTTP_REFERER} ^http://([^.]+\.)*domain-[ab]\.com
RewriteRule ^download_(mac|pc)\.zip$ domain_ab/$0 [L]
# last rule if no referer matches
RewriteRule ^download_(mac|pc)\.zip$ default/$0 [L]
# force 404 if file name is missing or wrong
RewriteRule ^ 404/index.html [L]

QUERY_STRING in .htaccess While redirecting

How can I allow visitors to use this link (www.example.com/news?id=34) in order to see (www.example.com/index.php?page=news&id=34)
Right now I am hiding the extensions of my PHP files in order to make the links look nice. When visitors go to (www.example.com/news) they can see the page (www.example.com/index.php?page=news). However, when they go to (www.example.com/news?id=12) they get a 404 error.
At this point, PHP does not recognize the id parameter. Here is what I currently have in my .htaccess file
Options +FollowSymlinks
RewriteEngine on
# catch request with no querystring like /Home
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^([^/]+)$ /index.php?page=$1 [L]
# make other requests with a non-empty query string go to /index.php?id=XXXXX
RewriteCond %{QUERY_STRING} ^.*$
RewriteRule ^$ /index.php?id=$1 [QSA,L]
Your second test pattern (^$) only matches the case where the user doesn't put any path information in, but does include a query string (e.g. www.example.com/?id=12). Also note that the backreference $1 has no value in that rule either.
The simplest solution is to just combine the two rules, since you can use the QSA flag to do the work of appending the id=# part for you:
Options +FollowSymlinks
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]+)$ /index.php?page=$1 [QSA,L]
The condition of your first rule fails as the query is not empty. Try it without that condition but with the following condition instead:
RewriteCond $1 !=index.php
RewriteRule ^([^/]+)$ /index.php?page=$1 [L]

Resources