htaccess rewrite rule, parameter with unicode letters - apache

I have tried to follow many answer in the site, without success.
I am trying to rewrite:
domain.com/articles/<author>
To:
domain.com/articles/index.php?author=<author>
My current rule is:
RewriteRule ^(\w*)$ /articles/index.php?author=$1 [B]
That works with letters or numbers, but not with unicode charachters like א and ".
For א, i am getting the following error:
Object not found!
The requested URL was not found on this server. If you entered the URL
manually please check your spelling and try again.
If you think this is a server error, please contact the webmaster.
Error 404
localhost Apache/2.4.23 (Win32) OpenSSL/1.0.2h PHP/7.0.9
And for ":
Access forbidden!
You don't have permission to access the requested object. It is either
read-protected or not readable by the server.
If you think this is a server error, please contact the webmaster.
Error 403
localhost Apache/2.4.23 (Win32) OpenSSL/1.0.2h PHP/7.0.9
And i need them both.
EDIT:
After reading #user82217 comment i have tried again (.*) regex, this time with the END flag like this:
RewriteRule (.*) /articles/index.php?author=$1 [END]
Now א case is being interpreted well. But " case still gives the same error (Access Forbidden).
#user82217 has suggested to investigate the log. For the " case the log is:
Cannot map GET /articles/%22 HTTP/1.1 to file
Conclusion:
As #user82217 said in a comment, It appears that under Windows OS an address with " char is considered an illegal file to serve, although the address isn't a file at all.
So i gave up the " case for now. Will glad to hear if there is a way to get around that.

RewriteRule ^(\w*)$ /articles/index.php?author=$1 [B]
If you simply replace your pattern with (.*) then you will get a rewrite-loop (which is your 500 Internal Server Error). You could either make the RewriteRule pattern match everything except slashes:
RewriteRule ^([^/]*)$ /articles/index.php?author=$1 [B,L]
However, from your examples it's not clear where your .htaccess file is located. The above assumes it is in the /articles subdirectory.
Alternatively, you could check the query string and only process the directive if the query string is empty:
RewriteCond %{QUERY_STRING} ^$
RewriteRule (.*) /articles/index.php?author=$1 [B,L]
But " case still gives the same error (Access Forbidden).
UPDATE: Ah, this is probably a more fundamental error and is probably a limitation of the OS (are you using Windows?). The " character is not a valid filename character. Apache is unable to map this to a valid filename which would appear to result in a system generated 403 Forbidden.

For the double quotes issue:
The " character is not a valid filename character like #MrWhite said.
#Deadooshka stated in his comment that it cannot be done in .htaccess context.
I think he is right.
#Deadooshka also said it can be done in the <]VirtualHost[> context. However, in my development server i don't use <]VirtualHost[> context.
So the solution was to put the rewrite rule under the global context of Apache's config file (in my case: C:\xampp\apache\conf\httpd.conf) like this:
# <<< existing line >>>
DocumentRoot "C:/xampp/htdocs"
# <<< existing line >>>
# <<< solution >>>
RewriteEngine on
RewriteRule /articles/(\w*)$ /articles/index.php?author=$1 [B]
# <<< solution >>>

Related

Rewrite rule to return status 200 for certain URLs

I want URLs with a specific path to return an automatic 200 status response. I have tried the below, but get a an error when I try to start Apache:
First error: RewriteCond: bad flag delimiters
RewriteEngine On
RewriteCond %{THE_REQUEST} GET /the_url/
RewriteRule ^ - [R=200]
If I remove the path part then I do not get the error:
RewriteEngine On
RewriteCond %{THE_REQUEST} GET
RewriteRule ^ - [R=200]
But, of course, I need a way to include the path requirement.
Another error is that, even when the server does return a status 200 above (verified in Developer Tools), then the page still displays an error message: "OK The server encountered an internal error or misconfiguration and was unable to complete your request...." Is it not really returning a status 200? Or is it, but this is just what the default HTML page is when nothing is provided by the server?
The following did the trick. From https://httpd.apache.org/docs/2.4/custom-error.html
Enable the mod_rewrite module
LoadModule rewrite_module modules/mod_rewrite.so
and then add the following to your virtual host.
ErrorDocument 200 "ok"
RewriteEngine On
RewriteRule "/the_url/" - [R=200]
EDIT:
My original answer has been edited so much by someone else that it is no longer quite the same. I'll leave the edited answer (above), but I did not have to enable the mod_rewrite module. Some Linux distributions come with this by default or your host might have provided it as their default starting point. I added the three lines to httpd.conf.

Simple .htaccess rewrite rule returning 'Not Found' issue

I have this code:
Options -Indexes
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^referral/([0-9]+)/?$ /referral.php?code=$1 [NC,L]
It is supposed to do two things:
block the access to folders' content
modifies a URL that ends with referral/test#email.com to referral.php?code=test#email.com.
Different formats have been tried, but the same error comes up:
Not Found
The requested URL /referral/test#email.com was not found on this server.
Apache/2.4.7 (Ubuntu) Server at Port 443
The first line of code works fine alone.
RewriteRule ^referral/([0-9]+)/?$ /referral.php?code=$1 [NC,L]
The RewriteRule pattern (ie. ^referral/([0-9]+)/?$) does not match a URL of the form "an address that ends with referral/test#email.com". For that you would need something like the following instead:
RewriteRule ^referral/([a-zA-Z0-9.#-]+)$ /referral.php?code=$1 [L]
This assumes that the URL "ends with" an email address, but that is otherwise the complete URL. The regex [0-9]+ only matches digits, not an email address (letters, digits, "#", ".", etc.), that you appear to require.
I've also removed the NC flag and incorporated the case-insensitivity into the regex, since I assume only the email address could be mixed case, not the URL-path?
After viewing other related questions (notably this one), I finally got it to work by adding the following line:
Options -MultiViews

htaccess redirect dynamic url to one with hashbang

I have http://domain.com/frame/1234sdfs but I want to change it to http://domain.com/#/frame/1234sdfs
I'm using trial and error at the moment and getting nowhere with the following in my .htaccess
RedirectMatch 301 ^/frame/([^/]*)$ /#/frame/$1
Could someone place me in the right direction? I have been using http://htaccess.madewithlove.be/ to try get the output URL as expected but can't figure it out.
You should use mod_rewrite so that you can use the NE flag. It's probably being converted to %23 using mod_alias. You need to send it literally with this code here.
RewriteEngine On
RewriteRule ^frame/([^/]+)/?$ /#/frame/$1 [NE,L,R=301]
Omitting the [NE] will result in the # being converted to its hexcode
equivalent, %23, which will then result in a 404 Not Found error
condition.
https://httpd.apache.org/docs/2.4/rewrite/flags.html#flag_ne
Note: Makes sure .htaccess is allowed and mod_rewrite is enabled.

Apache is rewriting to index.php, but does not attach the query string

I am trying to get .htaccess to work in my localhost (I've got Mac OS X 10.5). I enabled .htaccess by following articles like this one. But although now the rewriting is taking place, it is not working correctly. As an example, one of the rewrite rules is:
RewriteRule ^(home|faq|about|contact)$ index.php?section=$1 [QSA,NC]
So when I enter http://localhost/~MyUsername/MyWebsite/home, I should be shown http://localhost/~MyUsername/Mywebsite/index.php?section=home ...but instead, a 404 error occurs, and the error message is "The requested URL /Users/MyUsername/Sites/MyWebsite/index.php was not found on this server."
My guess is that something in my Apache configuration is wrong (the rewrite rule works fine in my online host), but how to solve it is beyond my knowledge. Any ideas? Thanks in advance.
Try the following RewriteRule:
RewriteRule ^/(.*)/(home|faq|about|contact)$ /$1/index.php?section=$2 [QSA,NC]
You can test your rewrite rules here - http://martinmelin.se/rewrite-rule-tester/

Apache rewrite rule leading slash

Leading slash first argument: ignored?
What's the syntax difference between
RewriteRule help help.php?q=noslash [L] #1
RewriteRule /help help.php?q=withslash [L] #2
If I hit http://localhost/help, it goes to #1, if I hit http://localhost//help it still goes to #1.
Am I right in saying the leading slash in the first argument to RewriteRule is essentially ignored?
Leading slash second argument: error?
Also, why doesn't this rewrite rule work?
RewriteRule help /help.php [L] #1
Putting a leading slash in front of the second arg actually creates a 500 error for the server. Why?
I should note I'm using a .htaccess file to write these rules in
Strangely enough,
RewriteRule ^/help help.php?q=2 [L]
The above rule fails and never matches.
This rule:
RewriteRule ^help help.php?q=1 [L]
Matches http://localhost/help, http://localhost//help and http://localhost///help
It appears RewriteRule never sees leading slashes of the path, and as TheCoolah said they are collapsed (to 0.. when using a .htaccess file anyway) no matter how many there are.
For the second part of the question,
RewriteRule ^help /help.php
I'm getting the answer from Definitive Guide to Apache Mod_rewrite
... a rewrite target that does not begin with http:// or another protocol
designator is assumed to be a file system path. File paths that do not begin with a slash are interpreted as being relative to the directory in which the rewriting is taking place.
So /help.php looks in the root of the system for a file called help.php, which on my system it cannot find.
To make /help.php appear as a relative URL (relative to the root of the site) you can use the [PT] directive:
RewriteRule ^/help /help.php [PT]
That directs http://localhost/help to http://localhost/help.php.
Regarding double slashes: Most Web servers silently collapse multiple slashes into a single slash early in the request processing pipeline. This is true for at least Apache, Tomcat and Jetty. Most Unix-based file systems work the same way. If you really want to check for this, you need to do something like:
RewriteCond %{REQUEST_URI} ^(.*)//(.*)$
help matches "help" anywhere in the path.
/help matches nothing since the rewriterule directive omits the leading slash for matching purposes (i.e., you must use ^, not / or ^/, to reference the current directory).
(This can be very confusing if you've used %{REQUEST_URI} in rewritecond because %{REQUEST_URI} does begin with a trailing slash. When matching against %{REQUEST_URI}, ^ and ^/ are equivalent and a directory name will always be preceded by a slash character regardless of whether or not it is in the top-level directory.)
The server error is caused by an infinite loop. "help" becomes "/help.php" which is then matched by the same directive that did the rewriting. So, after the first match, "/help.php" becomes "/help.php" infinitely resulting in a URL that can't be resolved.
I believe such loops can be fixed with the end flag (i.e., [end]), but that flag requires Apache 2.3.9+ whereas Apache 2.2 seems to be more common in deployment. It'd probably be better to just fix the regular expression anyway; ^help$ would seem to be the better choice here.
The way RewriteRule works is that if the given regular expression matches any part of the path part of the URL (the part after the host and port but before the query string), then the entire path part is completely replaced with the given substitution. This explains the behaviour you're seeing in the first part of your question.
I'm not sure what could be causing the 500 errors on the second part; maybe the collapsing of doubled slashes doesn't happen after the rewrite engine has run and then generates a server error.
The reason for the 500 Error is an infinitive Loop:
help gets rewritten to /help
/help gets stripped to help
help gets rewritten to /help
etc. until the MaxRewrites limit is hit -> 500
Whereas if the rule rewrites help to help, Apache is smart enough to abort rewriting at that point.