.htaccess if-then-like selective rewrite - .htaccess

##### PART 1
# IF:
RewriteRule ^ac$ /ac05182018.pdf [R=301,NC,L]
# THEN:
RewriteCond %{DOCUMENT_ROOT}/downloads/$1 -f
RewriteRule ^(.+\.(pdf))$ downloads/$1 [L]
##### PART 2
# IF:
RewriteRule ^ac64$ /ac64_05182018.pdf [R=301,NC,L]
# THEN:
RewriteRule ^(.*).(pdf)$ download.php?file=$1.$2 [L]
"PART 1" works standalone (= if one requests http...mysite.com/ac then this rewrites to "http...mysite.com/downloads/ac05182018.pdf").
"PART 2" works standalone as well (= if one requests http...mysite.com/ac64 then this rewrites to "http...mysite.com/download.php?file=ac64_05182018.pdf").
I was wondering how to achieve the following:
I need both of them (PART 1 & 2) to be combined, so that either one will be executed, I mean that both work, depending on what file gets requested (either /ac or /ac64).
When I do so though, "PART 1" no longer rewrites to "/downloads/ac05182018.pdf" and then stops executing the rest. Instead it rewrites to "http...mysite.com/download.php?file=downloads/ac05182018.pdf"...
Any idea how to achive this?
Something like:
# IF:
RewriteRule ^ac$ /ac05182018.pdf [R=301,NC,L]
# THEN:
RewriteCond %{DOCUMENT_ROOT}/downloads/$1 -f
RewriteRule ^(.+\.(pdf))$ downloads/$1 [L]
# ELSE
# IF:
RewriteRule ^ac64$ /ac64_05182018.pdf [R=301,NC,L]
# THEN:
RewriteRule ^(.*).(pdf)$ http...mysite.com/download.php?file=$1.$2 [L]
Maybe with RewriteRule flag [S] or
<If ... >
...
</If>
<Else>
...
</Else>
as both seen in the answers of How to write "if...else" mod_rewrite statements in .htaccess ?

First this line RewriteCond %{DOCUMENT_ROOT}/downloads/$1 -f will prevent next rule RewriteRule ^(.+\.(?:jpe?g|pdf))$ downloads/$1 [L] to be executed because you don't have downloads yet in document root .
After remove it , there will be two rules to .pdf files :
RewriteRule ^(.+\.(?:jpe?g|pdf))$ downloads/$1 [L]
and this :
RewriteRule ^(.*).(rar|zip|pdf)$ http...mysite.com/download.php?file=$1.$2 [R,L]
Unless you do some conditions one of them both will match .pdf and that will give error .
Moreover , don't forget to to put L flag like here :
RewriteRule ^ac64$ /ac64_05182018.pdf [R=301,NC]
it should be RewriteRule ^ac64$ /ac64_05182018.pdf [R=301,NC,L]
L flag means if the rule matches, no further rules will be processed.
If i understand you your code should be like this :
RewriteEngine On
#Part 1
RewriteRule ^ac$ /ac05182018.pdf [R=302,NC,L]
RewriteCond %{REQUEST_URI} !(downloads|ac64)
RewriteRule ^(.+)\.(jpe?g|pdf)$ /downloads%{REQUEST_URI} [L]
#part 2
RewriteRule ^ac64$ /ac64_05182018.pdf [R=302,NC,L]
RewriteCond %{REQUEST_URI} !downloads
RewriteRule ^(.+)\.(rar|zip|pdf)$ /download.php?file=$1.$2 [L]
Clear browser cache and test it , if it is ok , change any 302 to 301 to get permanent redirection .
Note: any .pdf files not start with ac64 will be treated by the ac rule , first rule .

Related

CakePHP 3 htaccess ignore directory

After a lot of research I'm still struggling.
My ./.htaccess file looks like this:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_URI} !^/trackparser/.*$
RewriteRule ^(\.well-known/.*)$ $1 [L]
RewriteRule ^$ webroot/ [L]
RewriteRule (.*) webroot/$1 [L]
</IfModule>
However, if I go to www.mysite.com/trackparser it just gives me a missing controller error.
How do I make it ignore the trackparser directory?
Besides the required / as mentioned by #GregSchmidt, rewrite conditions only apply to the first rule that is following them, so your config basically says:
IF (URI != ^/trackparser/.*$) {
RewriteRule ^(\.well-known/.*)$ $1 [L]
}
RewriteRule ^$ webroot/ [L]
RewriteRule (.*) webroot/$1 [L]
What you want is to apply all three rules if the URI doesn't match ^/trackparser/.*$. To achieve that you can invert the condition and use a skipping rule, which when applied, will skip N number of the subsequent rules:
RewriteRule ^(\.well-known/.*)$ $1 [L]
RewriteCond %{REQUEST_URI} ^/trackparser(/.*|$)
RewriteRule . - [S=2]
RewriteRule ^$ webroot/ [L]
RewriteRule (.*) webroot/$1 [L]
This will skip the 2 CakePHP webroot rules in case the condition is met, so it's basically doing:
RewriteRule ^(\.well-known/.*)$ $1 [L]
IF (URI != ^/trackparser(/.*|$)) {
RewriteRule ^$ webroot/ [L]
RewriteRule (.*) webroot/$1 [L]
}
Note the removed negation operator, and the added (/.*|$) to make the ending slash optional. The rule for the well-known directory (certificate validation) could theoretically also be skipped, but I'd make it exempt in order to avoid it accidentally not being applied because of later changes.
See also
Apache > HTTP Server > Documentation > Version 2.4 > Modules > Apache Module mod_rewrite > RewriteCond Directive
Apache > HTTP Server > Documentation > Version 2.4 > Rewrite > RewriteRule Flags > S|skip

htaccess rewrite url with a parameter that equals 0

I would like to change
detail.php?cid=$category&ccid=$category2&cccid=$category3&fid=$id&ftitle=$titleseo
to
detail/$category/$category2/$category3/$id/$titleseo
But in case one of the parameters equals 0, the parameter should not be visible.
So in case $category=0, the url should become:
detail/$category2/$category3/$id/$titleseo
In case $category2=0, the url should become:
detail/$category/$category3/$id/$titleseo
Is this possible with a rewrite rule in htaccess and if yes how should this look like?
You could use this considering /$category/$category2/$category3/ have given names /$id/$titleseo are fixed :
RewriteEngine On
RewriteBase /
RewriteRule ^detail/(\$category)?/?(\$category2)?/?(\$category3)?/?(\$id)/(\$titleseo)$ - [E=PASS:cid=$1&ccid=$2&cccid=$3&fid=$4&ftitle=$5]
RewriteCond %{ENV:PASS} (.*)(&)[a-z]+=&(.*)$|[a-z]+=&(.*)$
RewriteRule ^ details.php?%1%2%3%4 [L]
RewriteCond %{QUERY_STRING} (.*)(&)[a-z]+=&(.*)$|[a-z]+=&(.*)$
RewriteRule ^ details.php?%1%2%3%4 [L]
RewriteCond %{ENV:PASS} ^(.+)$
RewriteRule ^ details.php?%1 [L]
In general use this :
RewriteEngine On
RewriteBase /
RewriteRule ^detail/([^/]+)?/?([^/]+)?/?([^/]+)?/?(\$id)/(\$titleseo)$ - [E=PASS:cid=$1&ccid=$2&cccid=$3&fid=$4&ftitle=$5]
RewriteCond %{ENV:PASS} (.*)(&)[a-z]+=&(.*)$|[a-z]+=&(.*)$
RewriteRule ^ details.php?%1%2%3%4 [L]
RewriteCond %{QUERY_STRING} (.*)(&)[a-z]+=&(.*)$|[a-z]+=&(.*)$
RewriteRule ^ details.php?%1%2%3%4 [L]
RewriteCond %{ENV:PASS} ^(.+)$
RewriteRule ^ details.php?%1 [L]
The rules above , first make and environment by capturing any request start with details and ended with /$id/$titleseo then check that ENV values to see which one has/hasn't a value and finally redirect it accordingly.
Both rules work in case of three levels of categories if you need more you could edit the rules like this :
Add this ([^/]+)?/? after RewriteRule ^detail/ then [E=PASS:cid=$1&ccid=$2&cccid=$3&ccccid=$4&fid=$5&ftitle=$6] at the end , you could compare to see the difrenec between this and previous one to get a criteria , and finally add %5 to /details.php?%1%2%3%4 [L] like this /details.php?%1%2%3%4%5 [L] and so on .
Did not get the code from Mohammed to work so far, but used
RewriteRule ^detail/?([0-9a-zA-Z]+)?/?([0-9a-zA-Z]+)?/?([0-9a-zA-Z]+)?/([0-9a-zA-Z]+)/([0-9a-zA-Z]+) detail.php?cid=$1&ccid=$2&cccid=$3&fid=$4&&ftitle=$5

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]

301redirect to remove folder from URL

I have:
mydomain.com/folder-name/segment1/segment2
I want to change it to:
mydomain.com/segment1/segment2
using a 301 redirect.
I've tried:
RewriteCond %{REQUEST_URI} !^/test/.*$
RewriteRule ^(.*)$ /test/$1 [L]
but its not working
here is my htacess file:
# #AddHandler application/x-httpd-php53 .php .php5 .php4 .php3
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_URI} ^/b1/.*$
RewriteRule ^(.*)$ /b1/$1 [R=301,L]
The answer for the first part of the question should be like this:
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/? $2/$3 [R=301,L]
The second code that you've tried is the opposite of what you're asking for initially. This line matches anything not starting with /test/:
RewriteCond %{REQUEST_URI} !^/test/.*$
This line says take everything and rewrite it to the /test/ directory:
RewriteRule ^(.*)$ /test/$1 [L]
So together anything that's not in the test directory is being rewritten to the test directory.
If you're trying to specifically remove the word test then you would remove the ! symbol in your attempt to create a match. Since you already know it's called test there's no need to even make Apache perform this look for 'test' because Apache handles the RewriteCond statement after the RewriteRule (rather unintuitively).
RewriteCond %{REQUEST_URI} ^/?test
You can specialize the rewrite rule like this (I've added [QSA] to catch any query strings:
RewriteRule ^test/([^/]+)/([^/]+)/? $1/$2/ [R=301,L,QSA]
Simply change your code to:
RewriteRule ^test/(.*)$ /$1 [R=301,L,NC]

.htaccess: mod_rewrite

Here is what I'm trying to accomplish:
(this .htaccess file is located in mysite.com/test/):
http://mysite.com/test/admin go to http://mysite.com/test/admin/index.php
http://mysite.com/test/contact go to http://mysite.com/test/contact.php
http://mysite.com/test/salt-lake-city/ go to http://mysite.com/test/index.php/city=salt-lake-city
http://mysite.com/test/salt-lake-city/deals/ go to http://mysite.com/test/deals.php?city=salt-lake-city
To start, I have:
RewriteRule ^(.*)/(.*)\.php$ $2.php?city=$1 [L]
(this handles the last 2). But, when I try to add the admin clause:
RewriteRule ^admin/ admin/index.php [L]
RewriteRule ^(.*)/(.*)\.php$ $2.php?city=$1 [L]
It messes up (the css is out of whack) etc.
Any thoughts?
Well .. if I had to do these rewrite rules, I would do them like this:
Options +FollowSymLinks -MultiViews
RewriteEngine On
# do not do anything for already existing files
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .+ - [L]
# admin rewrite
RewriteRule ^admin$ admin/index.php [L]
# rewrite /contact --> /contact.php (and similar)
# add .php extension if such file does exist
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.+)$ $1.php [L]
# OR
# alternatively specify their names directly
# plus it is more precise for the example you have provided
# (that's if you need to rewrite only specific pages)
RewriteRule ^(contact|about|something)$ $1.php [L]
# /salt-lake-city/ --> /index.php?city=salt-lake-city
RewriteRule ^([^/]+)/$ index.php?city=$1 [QSA,L]
# /salt-lake-city/deals/ --> /deals.php?city=salt-lake-city
RewriteRule ^([^/]+)/deals/$ deals.php?city=$1 [QSA,L]
To start, I have:
RewriteRule ^(.*)/(.*)\.php$ $2.php?city=$1 [L]
(this handles the last 2).
Sorry, but I do not see how "it will handle the last 2". I see no .php in the last two URL examples you have provided.
It messes up (the css is out of whack) etc.
Well -- let's see how it will work with my rules. In any case -- it may also depends how you wrote links to css/images/js.

Resources