there is an error of htaccess configuration - apache

Here is the link on the address bar:
durnitibaz.com/news.php?n=ACC-raid-on-passport-office-3-brokers-jail-fine
Here is the code of .htaccess :
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^news/([0-9] + )/([0-9a-zA-Z_-]+) news.php?n=$1 [L]
Now I cannot understand what is wrong with this code. Because this is not working when I try to access news from database like this url in address bar:
durnitibaz.com/news/ACC-raid-on-passport-office-3-brokers-jail-fine
This is Showing 404 error.

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^news/([0-9] + )/([0-9a-zA-Z_-]+) news.php?n=$1 [L]
There are many things wrong here:
The regex, in this context (with unescaped spaces), in syntactically invalid.
The regex is entirely wrong (even when "corrected") - it does not match the requested URL. There is no "id" (2nd path segment) in the requested URL. But this doesn't seem to be required for the target URL anyway.
The second condition (RewriteCond directive) that checks whether the request maps to a .php file is never going to be successful for such a request, so the rule will also fail for this reason.
The first condition that checks whether the request does not map to a directory would seem to be unnecessary.
Try the following instead:
RewriteRule ^news/([\w-]+)$ news.php?n=$1 [L]
This matches the example URL you posted. eg. /news/ACC-raid-on-passport-office-3-brokers-jail-fine and internally rewrites the request to /news.php?n=ACC-raid-on-passport-office-3-brokers-jail-fine.
The preceding RewriteCond directives are not required.
The shorthand character class \w is the same as [0-9a-zA-Z_].
Note the end-of-string anchor ($) - this ensures you do not match too much (eg. actual files that contain a file extension) and result in a many-to-one rewrite.

Related

The requested URL was not found on this server .htacess

I am trying to rewrite URL like:
example.com/speciality_details.php?id=23&name=ent
TO
example.com/specialities/23/ent
But I am getting this error:
Not Found
The requested URL was not found on this server.
Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.
This is my .htaccess file
RewriteEngine on
RewriteRule ^doctor/([0-9]+)/([^/.]+)$ doctor_details.php?id=$1&name=$2 [NC,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/specialities/([0-9]+)/([^/.]+)$ speciality_details.php?id=$1&name=$2 [NC,L]
The first RewriteRule working but the second one is not working
Please help me to know what the problem is. How should I rewrite the code?
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/specialities/([0-9]+)/([^/.]+)$ speciality_details.php?id=$1&name=$2 [NC,L]
Just as in the first rule (which is "working"), you should not be matching a slash prefix on the URL-path. And the preceding condition (RewriteCond directive) is superfluous, since a URL of the form /specialities/23/ent could not possibly match a physical file (could it?).
In .htaccess, the URL-path matched by the RewriteRule pattern does not start with a slash since the directory-prefix (that always ends with a slash) has already been removed.
So, the rule should look like the following instead (and no RewriteCond directive):
RewriteRule ^specialities/([0-9]+)/([^/.]+)$ speciality_details.php?id=$1&name=$2 [NC,L]
This would match a URL of the form example.com/specialities/23/ent, as per your example. And assumes the file being rewritten to is speciality_details.php in the document root.
The NC (nocase) flag should also be superfluous, unless you are expecting mixed case versions of sPeCiAlItIeS? But if you are then that is better resolved with a redirect since the rewrite would potentially result in a duplicate content (SEO) issue.
Make sure you clear your browser cache before testing.
Although, from your earlier question edits it looks like you had already tried this without the slash prefix, but at the time you had /speciality/23/ent, not /specialities/23/ent as the example request URL - which would obviously not match.

mod-rewrite, how to implement a second rule?

I'm trying to get a .htaccess file RewriteRule in my web application. I need a double rule to match two URL formats that might happen:
Rule 1 (not commented below and works like a charm)
http://example.com/whatever -> /index.php?page=whatever&
http://example.com/whatever/ -> /index.php?page=whatever&
http://example.com/whatever/?test=me -> /index.php?page=whatever&test=me
Rule 2 (commented out below and does not work, but should work like this)
http://example.com/api/ -> index.php?page=api&func=
http://example.com/api/whateverelse -> index.php?page=api&func=whateverelse
The folder /api/ does not exists on the server and by reading the documentation the L parameters should prevent the parsing of more rules. Yet if I uncomment the ^\/api\/(.*)$ I get an 404 response.
The goal is that if the first rule gets parsed the second rule is omitted, and the goal is that the first rule actually works.
Is there someone that could point me in the right direction here?
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
#RewriteRule ^\/api\/(.*)$ //index.php?page=api&func=$1 [NC,L]
RewriteRule ^\/?([^\/]+)\/?$ //index.php?page=$1&%{QUERY_STRING} [NC,L]
I tried to debug it by adding:
LogLevel alert rewrite:trace6
but this is not allowed in the .htaccess and I do not have direct access to the server configuration files.
#RewriteRule ^\/api\/(.*)$ //index.php?page=api&func=$1 [NC,L]
This doesn't work because in .htaccess the URL-path matched by the RewriteRule pattern does not start with a slash. You have included a slash prefix on the regex, so it never matches.
In the following rule, the slash prefix is made optional with the ? quantifier, ie. ^\/? - so it will match. (The slash prefix is only required when the directive is used in a server context. By making it "optional", it would work in either.)
If you are only using .htaccess then you can remove the slash prefix from the RewriteRule pattern altogether.
For example:
RewriteRule ^api/(.*) /index.php?page=api&func=$1 [NC,L]
Additional notes...
No need to backslash escape slashes in the regex, as they carry no special meaning. (Apache uses spaces as argument delimiters.)
Not sure what the double slash prefix on the substitution string was for? ie. //index.php. You should only have at most one slash here, or none at all for an internal rewrite (and the index.php file is in the same directory as the .htaccess file). (The double slash still "works", only because Apache is reducing instances of multiple slashes when it maps the URL to the filesystem.)
The RewriteCond directives only apply to the first RewriteRule directive that follows, so you may need to repeat these for the second rule. (Or reverse the logic and stop processing when a request does map to a file/directory? However, this might depend on what other directives you have in the file.) If you don't have physical files that start /api then you can remove the conditions from that rule.
You don't need to manually append the QUERY_STRING to the substitution. This is what the QSA (Query String Append) flag is for. The QSA flag will also avoid a stray & at the end when no query string is present on the request.
The NC flag is not required on the last rule. It may not be required on the "api" rule either, unless /API, or /ApI etc. might be required - but this should be avoided.
So, bringing this together, we have....
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^api/(.*) /index.php?page=api&func=$1 [NC,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/?$ /index.php?page=$1 [QSA,L]

Why does mod_rewrite process the rules after the [L] flag

There are the rules:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.+) dir/index.php?$1 [L]
RewriteRule dir/index\.php.* - [F]
Why the last rule is processed and it returns Forbidden for all requests?
I need that if file or directory is not found then the next rule shouldn't be processed.
The next example isn't working for me as well:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .? - [S=1]
RewriteRule dir/index\.php.* - [F]
RewriteRule (.+) dir/index.php?$1
It still returns Forbidden for all requests.
Why the last rule is processed and it returns Forbidden for all requests?
When the URL foobar is requested:
The two conditions (line 2, 3) match
Pattern matches, the resulting URL becomes dir/index.php?foobar (line 4)
The [L] flag causes the rewriting to stop -- it does not stop Apache from having another go at the rewritten URL since it has changed (see below).
With dir/index.php as the input URL:
The condition does not match (line 2) since file exists
Jumps to line 5
Pattern matches, hence the Forbidden error
When directory or filename changes, Apache has to re-evaluate various configuration sections (e.g. Directory and Files) and the .htaccess file for the "re-written" path. This is why Apache might perform another iteration even when the previous one was ended by [L] flag.
The last string supposes to restrict the direct access to UFL handler.
Direct access means requesting the file through a link like: domain.com/dir/index.php
I think adding another condition before line 5 should work:
RewriteCond %{THE_REQUEST} dir/index\.php\x20HTTP/\d\.\d$
RewriteRule . - [F]
The THE_REQUEST server variable contains the request sent by the browser without any rewriting applied. This could be useful to detect what page was originally requested by the browser.
THE_REQUEST
The full HTTP request line sent by the browser to the server (e.g.,
"GET /index.html HTTP/1.1"). This does not include any additional
headers sent by the browser. This value has not been unescaped
(decoded), unlike most other variables below.
I am not exactly sure of what you meant by "the next rule".
But if you don't want some rules to be executed when a non-existent file is requested, then using the following structure may help. (The following piece of code is copied from the Apache RewriteRule Flags Page)
# Is the request for a non-existent file?
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# If so, skip these two RewriteRules
RewriteRule .? - [S=2]
RewriteRule (.*\.gif) images.php?$1
RewriteRule (.*\.html) docs.php?$1
And also using [R] for redirecting instead of [L] might help with the problem of returning Forbidden for all requests.

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.

Trying to put an exception to RewriteRule in .htaccess

I am redirecting all requests like so:
RewriteRule ^sitemap.xml$ sitemap.php?/ [QSA,L]
# the line below is the one I'm having trouble with
RewriteCond %{REQUEST_URI} !^market-reports$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) /index.php?section=$1 [QSA,L]
All my incoming links are meant to go to index.php, as you can see. But now I want to stop one from going there. I've never written my own RewriteCond before, so I'm a little unsure if what I am doing is correct.
Basically what I'm trying to say is: "If incoming URL is a file, directory or /market-reports/ do nothing. Otherwise send on the URL to index.php?section="
What am I doing wrong? Thanks
So you just need to ignore http://yourdomain.com/market-reports (in addition to files/directories?). You should be fine with:
RewriteCond %{REQUEST_URI} !^/market-reports/?$
This will (not) match "http://yourdomain.com/market-reports" as well as "http://yourdomain.com/market-reports/" as the question mark "?", in the Perl Compatible Regular Expression vocabulary that mod_rewrite uses, makes the match optional (a wildcard) before the end of the string anchor, which is represented with the literal dollar sign "$".
The "^" symbol acts as an anchor matching the beginning of the string and the "!" negates the match, so that any string URL that does not match the rest of the expression will be rewritten to the other specified rules.
See mod_rewrite regex vocabulary