I am currently learning the regular expressions and applications of regex in .htaccess file.
And in one of the videos I have seen this kind of code:
RewriteRule ^(.*)$ ./index.php/$1 [L]
So I wondered what the hell ./ is doing before index.php?
I tried to type ./ in the URL and it worked:
http://localhost/CodeIgniter3Test/./index.php/welcome
was redirected automatically to
http://localhost/CodeIgniter3Test/index.php/welcome
So my question is where this redirection engine is executed (file where this rule is written httpd or elsewhere) and for what reason could possibly ./ be added to the Pattern Substitution in RewriteRule?
As #Sebastian has already pointed out in his answer, the . (dot) in a filesystem path refers to the current working directory (CWD). However, in the context of Apache mod_rewrite, the ./ prefix is arguably an error and should be removed. The "current directory" is determined by the directory-prefix*1 - which has nothing to do with the dot.
However, unless you are chaining directives together, then ./index.php/$1 is the same as index.php/$1 and the ./ is going to get resolved away anyway (either by the rewrite engine when the request is mapped to the filesystem, or by the browser in the case of an external redirect).
When the RewriteRule substitution string is prefixed by ./, mod_rewrite simply sees it as a "relative" path (any string that does not start with a protocol or slash is considered "relative"). In this case mod_rewrite appends the directory-prefix regardless.
For example, given the following directive in the .htaccess file located in the document root (eg. /var/www/example/public_html)
RewriteRule ^(.*)$ ./index.php/$1 [L]
If you requested /foo then the above directive rewrites the request to ./index.php/foo, after which (at the end of this phase of processing) the directory-prefix is added back to become /var/www/example/public_html/./index.php/foo.
Apache then resolves away the ./ when the request is mapped to the filesystem, so it becomes /var/www/example/public_html/index.php/foo.
So, the ./ prefix on the original substitution string serves no purpose here.
what reason could possibly ./ be added to the Pattern Substitution in RewriteRule?
To answer your original question.... none.
I tried to type "./" in url and it worked
The browser actually removes it before making the HTTP request - the ./ part is not sent as part of the HTTP request and never reaches your server.
were redirected automatically
There's no actual "redirect" here - the browser simply "fixes" (ie. resolves) the URL in the browser address bar.
*1 The directory_prefix is the absolute filesystem path of where the .htaccess file is located. However, this can be overridden by setting a URL-path with the RewriteBase directive. Note that the directory-prefix always ends in a slash.
See also:
What does a dot mean in a URL path?
the ./ characters means "From the current directory" in a lot of systems, and, that is what it means, to look the file that is in the current directory that this file is executed.
You also can say "From one directory above" with two dots instead of one (../)
Related
My WP site has two languages. Default language (EN) used to be the default language, and the 2nd language (NL) in a subdirectory. Now all pages and directories in the default language have also been moved to a subdirectory, and the root url just shows a splah page where you are forced to choose your language.
So all stuff in root.com/... should be redirected with a 301 redirection rule to root.com/en/...
Except all stuff in root.com/nl/... which should just stay in root.com/nl/...
AND Except the splash page with the language selection which remains root.com
How should I write the redirection rules in the htaccess file?
This should be quite simple actually.
We use a RewriteCond to check that the requested URL path did not start with /nl/. The ^ anchors the pattern at the start of the test string, and the ! negates it.
And in the RewriteRule pattern, we demand that the path consists of at least one character. The leading / has already been stripped off at this point (only when the rewriting is configured in .htaccess though, if it was done via the central server configuration, that would be different) - which means, the request for your splash screen at the root URL will be an “empty” path here. By anchoring the pattern at the start and finisch, and using the + quantifier, we demand that the path must consist of at least one character here, so this rule will simply do nothing, if the root path was requested.
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/nl/
RewriteRule ^(.+)$ /en/$1 [R=302,L]
Google Search Console is showing 404 Page Not Found error for
https://example.com/page/https://example.com/page/
and the link is coming from an external website.
I want to redirect with .htaccess:
https://example.com/page/https://example.com/page/
to
https://example.com/page/
Can anyone can help me in this regard?
Try the following mod_rewrite directives at the top of your .htaccess file:
RewriteEngine On
RewriteRule ^(.*?)https?:/ /$1 [R=301,L]
This just removes any trailing part on the URL-path that starts http:/ (or https:/).
UPDATE: The ? in the capturing subpattern (.*?) makes it non-greedy, so it only captures up to the first occurrence of https:/ and discards the rest, rather than up to the last occurrence (greedy) and looping (redirect loop) until all occurrences of https:/ were removed.
Additional notes:
First test with 302 (temporary) redirect to make sure it works. Only change to 301 when confirmed, to avoid caching issues.
The URL-path that is matched by the RewriteRule pattern has already had sequences of slashes reduced to single slashes, so you can't match // (double slash) here (but I don't think you need to).
If there are query strings involved then you may need a slightly different approach and another directive, since the query string itself (as opposed to the URL-path) might contain the "repeated URL" that needs to be removed (we would need to see an example first). The RewriteRule pattern matches against the URL-path only, not the query string.
On Windows: If the (scheme and) colon (:) appears in the first path segment (ie. the malformed link is for the document root) then Apache will generate a 403 Forbidden before .htaccess is able to redirect. There is nothing you can do to avoid this since it is a limitation of the OS (colons are not allowed in filesystem paths - the 403 occurs when Apache tries to map the URL to a filesystem path). This does not happen on Linux. For example: https://example.com/https://example.com/.
UPDATE: If you are not seeing a redirect, just a 404 then you may need to enable additional pathname information (PATH_INFO) on your URLs. For example, at the top of your .htaccess file:
AcceptPathInfo On
I use redirections quite a lot but I'm not able to achieve my goal despite searching.
What I like to achieve:
a request to /aaaa redirected to /articles/aaaa.php
but only show /aaaa in browser (this already works for years)
a request to /bbbb which is a directory, no file exist with this name, has to be redirected to /products/bbbb/index.php (but only show /bbbb in browser)*
This is what I use now:
RewriteRule ^([a-z0-9-_]+)$ /articles/$1.php [NC,L]
*as alternative if it is too complex this is ok: a request to /bbbb (which is a directory no file exist with this name) redirect to /products/bbbb (and in the directory /products/bbbb I'll pick it up there with a local .htaccess and redirect it to index.php) still in the browser /bbbb should be shown.
When rewriting to the file in the /articles directory you can check that it exists first (as a file). For example:
RewriteCond %{DOCUMENT_ROOT}/articles/$1.php -f
RewriteRule ^([a-z0-9-_]+)$ /articles/$1.php [L]
I've also removed the NC flag, unless you explicitly need this?
Likewise to internally rewrite to the directory:
RewriteCond %{DOCUMENT_ROOT}/products/$1/index.php -f
RewriteRule ^([a-z0-9-_]+)$ /products/$1/index.php [L]
This actually checks that the index.php file exists, rather than the parent directory, since you are ultimately rewriting to a file, not a directory.
Sorry if this is a duplicate: I found many questions about caching system, but my problem seems to tied to the fact that the whole script is working within a subfolder.
All I need to do is implementing a simple caching system for my website, but I can't get this to work.
Here's my .htaccess file (widely commented to be clear - sorry if too many comments are confusing):
RewriteEngine on
# Map for lower-case conversion of some case-insensitive arguments:
RewriteMap lc int:tolower
# The script lives into this subfolder:
RewriteBase /mydir/
# IMAGES
# Checks if cached version exists...
RewriteCond cache/$1-$2-$3-{lc:$4}.$5 -f
# ...if yes, redirects to cached version...
RewriteRule ^(hello|world)\/image\/([a-zA-Z0-9\.\-_]+)\/([a-zA-Z0-9\.\-_]+)\/([a-zA-Z0-9\.\-_\s]+)\.(png|gif|jpeg?|jpg)$ cache/$1-$2-$3-{lc:$4}.$5 [L]
# ...if no, tries to generate content dynamically.
RewriteRule ^(hello|world)\/image\/([a-zA-Z0-9\.\-_]+)\/([a-zA-Z0-9\.\-_]+)\/([a-zA-Z0-9\.\-_\s]+)\.(png|gif|jpeg?|jpg)$ index.php?look=$1&action=image&size=$2&data=$3&name=$4&format=$5 [L,QSA]
# OTHER
# This is always non-cached.
RewriteRule ^(hello|world)\/([a-zA-Z0-9\.\-_\s]+)\/([a-zA-Z0-9\.\-_\s]+)?\/?$ index.php?look=$1&action=$2&name=$3 [QSA]
Now, the issue is that the RewriteCond seems to be always failing, as the served image is always generated by PHP. I also tried prepending a %{DOCUMENT_ROOT}, but is still not working. If I move the whole script to the root directory, it magically starts working.
What am I doing wrong?
Well one thing that you are doing wrong is trying to use a rewrite map in an .htaccess file. in the first place. According to the Apache documentation:
The RewriteMap directive may not be used in <Directory> sections or .htaccess files. You must declare the map in server or virtualhost context. You may use the map, once created, in your RewriteRule and RewriteCond directives in those scopes. You just can't declare it in those scopes.
If your ISP / sysadmin has already defined the lc map then you can use it. If not then you can only do case-sensitive file caching on Linux, because its FS naming is case sensitive. However, since these are internally generated images, just drop the case conversion and stick to lower case.
%{DOCUMENT_ROOT} may not be set correctly at time of mod_rewrite execution on some shared hosting configurations. See my Tips for debugging .htaccess rewrite rules for more hints. Also here is the equivalent lines from my blog's .htaccess FYI. The DR variable does work here, but didn't for my previous ISP, to I had to hard-code the parth
# For HTML cacheable blog URIs (a GET to a specific list, with no query params,
# guest user and the HTML cache file exists) then use it instead of executing PHP
RewriteCond %{HTTP_COOKIE} !blog_user
RewriteCond %{REQUEST_METHOD}%{QUERY_STRING} =GET [NC]
RewriteCond %{DOCUMENT_ROOT}html_cache/$1.html -f
RewriteRule ^(article-\d+|index|sitemap.xml|search-\w+|rss-[0-9a-z]*)$ \
html_cache/$1.html [L,E=END:1]
Note that I bypass the cache if the user is logged on or for posts and if any query parameters are set.
Footnote
Your match patterns are complicated because you are not using the syntax of regexps: use the \w and you don't need to escape . in [ ] or / . Also the jpeg isn't right is it? So why not:
RewriteRule ^(hello|world)/image/([.\w\-]+)/([.\w\-]+)/([\w\-]+\.(png|gif|jpe?g))$ \
cache/$1-$2-$3-$4 [L]
etc.. Or even (given that the file rule will only match for valid files in the cache)
RewriteRule ^(hello|world)/image/(.+?)/(.+?)/(.*?\.(png|gif|jpe?g))$ \
cache/$1-$2-$3-$4 [L]
The non-greedy modifier means that (.+?) is the same as ([^/]+) so doing hacks like ../../../../etc/passwd won't walk the file hierarchy.
I am terrible with mod_rewrite however I need to rewrite any request to the folder /files/users/*/ (* is a wildcard) to /view/ and insert the filename into a query paramater like so:
/files/users/9/test.pdf becomes /view/?file=test.pdf
How would I go about this assuming that the .htaccess file will be located inside /files/users/?
I would really appreciate if you explained how your solution works as I am slowly trying to become familiar with mod_rewrite.
So, you wanna have all my trade secrets on a silver plate?
Well, I try my best. ;-)
First of all, you must know where the documentation is. Look here for the reference: mod_rewrite. Or mod_rewrite, if your Apache version is 2.2.
You will find an overview with lots of links at Apache mod_rewrite. There, you will find a nice introduction to rewriting URLs. Also look here for lots of standard examples.
Since mod_rewrite supports PCRE regular expressions, you might need perlre and/or regular-expression.info from time to time.
Now to your question
RewriteEngine On
RewriteRule ^(?:.+?)/(.*) /view/?file=$1
This might already be sufficient. It looks for a subdirectory (?:.+?) in /files/users and captures the name of a file (.*) in this subdirectory. If this pattern matches, it rewrites the URL to /view/?file= and appends the captured file with $1, which gives /view/?file=$1.
All untested, of course, have fun.
P.S. Additional info is here at SO at .htaccess info and .htaccess faq.
Put the directive below in your .htaccess file to rewrite /files/users/9/test.pdf to /view/?file=test.pdf. In practical terms this means that if you visit http://yourdomain.com/files/users/9/test.pdf then the visitor will be served the rewritten url which is http://yourdomain.com/view?file=test.pdf
RewriteRule ^[^/]+/(.*)$ /view/?file=$1 [L]
A RewriteRule directive is part of the Apache mod_rewrite module. It takes two arguments:
Pattern - a regular expression to match against the current URL path (note that the URL path is not the entire URL but eg. /my/path, but in a .htaccess context the leading slash / is stripped giving us my/path).
Substitution - the destination URL or path where the user will rewritten OR redirected to.
Explaining the rule
The pattern ^[^/]+/(.*)$:
^ - the regex must match from the start of the string
[^/] - match everything but forward slash
+ - repetition operator which means: match 1 or more characters
/ - matches a forward slash
(.*) - mathes any characters. The dot means match any character. The star operator means match ANY characters (0 or more). The parantheses means the match is grouped and can be used in backreferences.
$ - the regex must match until the end of the string
The substitution /view/?file=$1:
...means that we rewrite the URL path to the /view/ folder with the query parameter file. The query parameter file will contain our first grouped match from the pattern as we pass it the $1 value (which means the first match from our RewriteRule pattern).
The [L] flag:
...means that mod_rewrite will stop processing rewrite rules. This is handy to avoid unwanted behaviour and/or infinite loops.