Redirect URL and change URL parameter value - apache

I'm trying to do a .htaccess redirect with a parameter but it's not working. Seems like my regex are also wrong. :(
https://example.com/art.php?link=456
Target URL :
https://example.com/art.php?link=789
I tried:
RewriteEngine on
RewriteCond %{QUERY_STRING} link=456
RewriteRule link=789 [L,R=301]

RewriteCond %{QUERY_STRING} link=456
RewriteRule link=789 [L,R=301]
The first argument to the RewriteRule directive is the URL-path you need to match, ie. /art.php (except there is no slash prefix when used in .htaccess). You also need to specify the substitution (target URL) as the second argument (which happens to be the same: /art.php).
For example:
RewriteCond %{QUERY_STRING} ^link=456$
RewriteRule ^art\.php$ /art.php?link=789 [L,R=301]
If you've previously experimented with 310 (permanent) redirects then you'll likely need to clear your browser cache before testing. Test with 302 (temporary) redirects to avoid potential caching issues.
You can save repetition of the URL parts by using backreferences. For example:
RewriteCond %{QUERY_STRING} ^(link)=456$
RewriteRule ^art\.php$ /$0?%1=789 [L,R=301]
Where $0 is the URL-path that the entire RewriteRule pattern matches. And %1 contains the match from the parenthesised subpattern in the last matched condition.
Reference:
https://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewriterule

Related

.htaccess Rewriterule redirecting to a URL on the same domain

I am trying to redirect users to specific URLs. I want to create .htaccess rewriterules to accomplish this.
I would lke for these:
https://example.com/career_by_education
https://example.com/international_careers
https://example.com/major_careers
https://example.com/career
to transfer to:
https://example.com/career_by_education/careers-by-educational-level.php
https://example.com/international_careers/international_careers.php
https://example.com/major_careers/academic_major_careers.php
https://example.com/career/career.php
I have tried many variations of rewrite rules to get this to work, and am successful if I want it to redirect to a different domain.
For example, the following (in .htaccss):
RewriteRule career_by_education https://example2.com/career_by_education/careers-by-educational-level.php [L,R]
RewriteRule international_careers https:/example2.com/international_careers/international_careers.php [L,R]
RewriteRule major_careers https://example2.com/major_careers/academic_major_careers.php [L,R]
RewriteRule career https://example2.com/career/career.php [L,R]
Successfully transfer to (respectively):
https://example2.com/career_by_education/careers-by-educational-level.php
https://example2.com/international_careers/international_careers.php
https://example2.com/major_careers/academic_major_careers.php
https://example2.com/career/career.php
But I want the redirect to be to the same domain (example.com), so I tried this (in this order):
RewriteRule career_by_education https://example.com/career_by_education/careers-by-educational-level.php [L,R]
RewriteRule international_careers https://example.com/international_careers/international_careers.php [L,R]
RewriteRule major_careers https://example.com/major_careers/academic_major_careers.php [L,R]
RewriteRule career https://example.com/career/career.php [L,R]
When I enter any of these into the browser:
https://example.com/career_by_education
https://example.com/international_careers
https://example.com/major_careers
I always get this URL:
https://example.com/career/career.php
I tried to reverse the ordering of the RewriteRules to:
RewriteRule career https://example.com/career/career.php [L,R]
RewriteRule major_careers https://example.com/major_careers/academic_major_careers.php [L,R]
RewriteRule international_careers https://example.com/international_careers/international_careers.php [L,R]
RewriteRule career_by_education https://example.com/career_by_education/careers-by-educational-level.php [L,R]
But the resulting URL is always:
https://example.com/career/career.php
I also tried to remove the full URL for the substitution, as follows:
RewriteRule career_by_education /career_by_education/careers-by-educational-level.php [L,R]
RewriteRule international_careers /international_careers/international_careers.php [L,R]
RewriteRule major_careers /major_careers/academic_major_careers.php [L,R]
RewriteRule career /career/career.php [L,R]
But the result always redirects to this URL:
https://example.com/career/career.php
I have tried different expressions to see if it can work:
RewriteRule ^/career http://consul64.wwwaz1-ts107.a2hosted.com/career/career.php [L,R]
RewriteRule ^/major_careers http://consul64.wwwaz1-ts107.a2hosted.com/major_careers/academic_major_careers.php [L,R]
RewriteRule ^/international_careers http://consul64.wwwaz1-ts107.a2hosted.com/international_careers/international_careers.php [L,R]
RewriteRule ^/career_by_education http://consul64.wwwaz1-ts107.a2hosted.com/career_by_education/careers-by-educational-level.php [L,R]
These all result in a "403 Forbidden" error - From the command line I ensured that I have a "index.php" in the root directory, and permissions were correct, with the following:
chmod 644 ~/public_html/.htaccess
chmod 755 ~/public_html
Then I tried these:
RewriteRule .*(?=major_careers) http://consul64.wwwaz1-ts107.a2hosted.com/major_careers/academic_major_careers.php [L,R]
RewriteRule .*(?=international_careers) http://consul64.wwwaz1-ts107.a2hosted.com/international_careers/international_careers.php [L,R]
RewriteRule .*(?=career_by_education) http://consul64.wwwaz1-ts107.a2hosted.com/career_by_education/careers-by-educational-level.php [L,R]
RewriteRule .*(?=career) http://consul64.wwwaz1-ts107.a2hosted.com/career/career.php [L,R]
The resulting URL was always:
https://example.com/career/career.php
I don't understand why the pattern seems to work when redirecting to an outside URL, yet does not work if redirecting to a URL on the same domain.
Could anyone please help guide me?
RewriteRule career_by_education /career_by_education/careers-by-educational-level.php [L,R]
RewriteRule international_careers /international_careers/international_careers.php [L,R]
RewriteRule major_careers /major_careers/academic_major_careers.php [L,R]
RewriteRule career /career/career.php [L,R]
The first argument to the RewriteRule directive (the pattern) is a regular expression. This is not an "exact string match". The problem with these rules is that the pattern also matches the redirected URL so would result in an endless "redirect loop", since the "regex" career_by_education matches that string anywhere in the URL-path.
You state that it always redirects to /career/career.php (the last rule above), but that's not possible with the rules as posted - due to the redirect-loop as mentioned above. However, it would happen if you reversed these directives (which you say you had also tried), since the first rule (that matches career only) would always match - but again, that is a redirect loop.
Aside: It might not trigger a redirect loop depending on your server config, eg. if requests for .php files are proxied to a CGI PHP engine.
You need to be more specific with the regex and match only the stated URLs. ie. You need to include anchors on the regex and match career_by_education only and not career_by_education anywhere.
For example:
RewriteRule ^career_by_education$ /career_by_education/careers-by-educational-level.php [L,R]
RewriteRule ^international_careers$ /international_careers/international_careers.php [L,R]
RewriteRule ^major_careers$ /major_careers/academic_major_careers.php [L,R]
RewriteRule ^career$ /career/career.php [L,R]
The order of these directives does not matter.
You don't necessarily need the scheme+hostname (ie. an absolute URL) in the substitution if you are redirecting to the same domain, however, it can help to reduce the number of redirects in the case of domain canonicalisation.
I don't understand why the pattern seems to work when redirecting to an outside URL
Because the directives are not processed again after the redirect (you are now on a different server).
RewriteRule .*(?=major_careers) http://consul64.wwwaz1-ts107.a2hosted.com/major_careers/academic_major_careers.php [L,R]
Using the unanchored positive lookahead is effectively the same as simply major_careers.
RewriteRule ^/career http://consul64.wwwaz1-ts107.a2hosted.com/career/career.php [L,R]
RewriteRule ^/major_careers http://consul64.wwwaz1-ts107.a2hosted.com/major_careers/academic_major_careers.php [L,R]
RewriteRule ^/international_careers http://consul64.wwwaz1-ts107.a2hosted.com/international_careers/international_careers.php [L,R]
RewriteRule ^/career_by_education http://consul64.wwwaz1-ts107.a2hosted.com/career_by_education/careers-by-educational-level.php [L,R]
These all result in a "403 Forbidden" error
Because of the slash prefix, these rules would never match, so they wouldn't actually do anything.
UPDATE:
However, a "problem" with these redirects is that the URL you are redirecting from, eg. /career_by_education is also the name of the filesystem directory you are redirecting to. So, by default, mod_dir will attempt to append a trailing slash, so the rule doesn't match. The 403 likely results from the absence of a DirectoryIndex document in that directory. Strictly speaking, your URLs need to end in a trailing slash, or make the trailing slash optional in the regex (but that could result in a double redirect).
For example:
# Trailing slash is mandatory
RewriteRule ^career_by_education/$ /career_by_education/careers-by-educational-level.php [L,R]
# Trailing slash is optional
RewriteRule ^career_by_education/?$ /career_by_education/careers-by-educational-level.php [L,R]
Although it would be preferable that the URL did not match the name of the directory in the first place.

301 Redirect in htaccess for URLs having Parameter P

I need to set 301 redirect in htaccess for URLs having parameter P. One example URL is
http://www.price4india.co.in/vivo-x20-plus-ud-price-in-india-scanner-feature-real.html?p=1028
to
http://www.price4india.co.in/vivo-x20-plus-ud-price-in-india-scanner-feature-real.html
After redirect everything after .html shall get removed and the value after P=...... can be any numerical value. So far I have tried below query but it is not working. Any suggestion please...
RewriteCond %{QUERY_STRING} ^p(&|$) [NC]
RewriteRule ^ %{REQUEST_URI}? [R=301,L]
With your shown samples, please try following .htaccess rules file. Make sure to keep your .html file and .htaccess files in root path only.
Make sure to clear your browser cache before testing your URLs.
RewriteEngine ON
RewriteCond %{THE_REQUEST} \s/(.*\.html)\?p=\d+\s [NC]
RewriteRule ^ /%1? [R=301,L]
NOTE: In case you have further more rules in your .htaccess rules, which includes internal rewrite of html files then you could keep these rules above those.
RewriteCond %{QUERY_STRING} ^p(&|$) [NC]
RewriteRule ^ %{REQUEST_URI}? [R=301,L]
This is almost correct, except the regex ^p(&|$) is incorrect. This matches p&<anything> or p exactly. Whereas you need to match p=<anything> (eg. ^p=) or p=<number> (eg. ^p=\d+). This is of course assuming the p URL parameter always occurs at the start of the URL-path (as in your example).
For example:
RewriteCond %{QUERY_STRING} ^p= [NC]
RewriteRule ^ %{REQUEST_URI}? [R=301,L]

Apache Rewrite Numeric Arguments To Root

We keep finding requests coming in like:
https://www.example.com/?1537249139=
The numbers in the query string parameter appear to be random timestamps. This is costing us in our prerender budget so we would like to 301 redirect these back to root. I have tried this:
RewriteCond %{QUERY_STRING} ^([0-9]*)=$
RewriteRule / [L,R=301]
But it doesn't work. Any ideas?
RewriteRule / [L,R=301]
This won't match the example URL. You are missing the first argument (Pattern) that matches against the requested URL-path:
RewriteRule Pattern Substitution [flags]
Your example URL is for the document root only (/), so this needs to be written like the following in .htaccess:
RewriteCond %{QUERY_STRING} ^\d+=$
RewriteRule ^$ / [R=301,L]
In .htaccess, the URL-path matched by the RewriteRule Pattern does not include the slash prefix (which is why your original directive would not have matched).
Note that this is a "redirect", not a "rewrite" as stated in your question title.
However, if these are completely invalid requests (perhaps even by a bot?) then would it not be preferable to simply return a 403 or 404? For example:
RewriteRule ^$ - [F]
OR
RewriteRule ^$ - [R=404]
?
Reference:
https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html#rewriterule

Mod rewrite domains.com/some-keywords

I have urls like this:
domains.com/?page=some-keywords
I want to change to:
domains.com/some-keywords
I tried:
RewriteRule ^([^/]*)(/?)$ /?page=$1 [L]
And
RewriteRule ^([^/]*)$ /?page=$1 [L]
But this is not working, I have 5xx errors. Its working only when I put some more in rules. for example
RewriteRule ^123,([^/]*)(/?)$ /?page=$1 [L]
There is possible to have that urls on apache?
from domains.com/?page=some-keywords
to domains.com/some-keywords
RewriteEngine On
RewriteCond %{QUERY_STRING} "^page=(.*)"
RewriteRule ^/$ /%1 [QSD,R]
RewriteCond directive will detect whether a query string parameter called page exists.
RewriteRule directive will map the URL from "/" to "/{value-of-page-parameter}".
This is achieved by using "%1" token. The token "%1" contains the value captured by "(.*)" from RewriteCond.
QSD flag is used to discard the original query string.
R flag is used to redirect the old URL to the new URL.

mod_rewrite - exclude urls

I need a mod_rewrite to redirect all http requests to https, but I want do exclude some URLs
# force https
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^secure\. [NC]
RewriteCond %{REQUEST_URI} !gateway_callback [NC]
RewriteRule ^. https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,QSA]
All URLs which match gateway_callback must be excluded
This URL should not be redirected, but it does!?
http://secure.localhost/da/gateway_callback/29/
Have tried to flush DNS cache in the browser, but the URL is still redirected to https
The main problem with your config is that the REQUEST_URI variable contains everything after and including the forward slash. The third RewriteCond statement needs to be updated to something like the following:
RewriteCond %{REQUEST_URI} !^/da/gateway_callback/.*$ [NC]
This should match the example you have provided. If the URI does not always start with /da/ then you might need to put in a wildcard:
RewriteCond %{REQUEST_URI} !^/[^/]+/gateway_callback/.*$ [NC]
where the [^/]+ matches one or more characters which is not a forward slash.
I would recommend always using the regex anchors wherever possible as it removes ambiguity. The original RewriteCond attempting to match REQUEST_URI does not use them, which can confuse admins at a casual glance.
Also note that all related examples for the RewriteCond and RewriteRule directives in the official documentation use the start anchor.
Could the trailing slash be keeping you from matching? I'm never clear on whether the trailing slash is preserved or not. I suggest changing your 3rd condition to
RewriteCond %{REQUEST_URI} !/gateway_callback/\d+/?$ [NC]