.htaccess rewrite with slash - apache

I'm trying to URL rewrite using .htaccess
from
example.com/daily.php to example.com/daily (and example.com/daily/)
with the following code:
Options +FollowSymLinks
RewriteEngine on
RewriteRule daily/$ daily.php
however:
example.com/daily/ = ok
example.com/daily = not ok

RewriteRule daily/$ daily.php
In the above RewriteRule directive, daily/$ is a regular expression (regex) that matches against the URL-path in the request. This regex contains a trailing slash (/), so this will clearly not match a URL that does not end in a slash.
If you want to match both /daily/ and /daily (although I would not recommend this - see note below) then you need to make the trailing slash optional in the regex. You make this character optional by following it with ? (question mark). For example:
RewriteRule ^daily/?$ daily.php [L]
I've also included a start-of-string anchor ^, so it only matches /daily and not /<anything>daily. You will probably want the L (last) flag, if you plan on adding any more directives.
Aside: If you allow both /daily/ and /daily, which are technically two different URLs then you potentially have "duplicate content". You should choose one or the other as the canonical URL. And optionally route the non-canonical version to the other.

Related

Redirect a URL with two query string parameters to a new domain with a changed path using Apache's rewrite rules

I'm trying to do the following thing:
Transform URL: https://example.com/human/?system=jitsi&action=SYSTEM
to: https://new.example/?action=SYSTEM&system=jitsi
RewriteEngine On
RewriteCond %{REQUEST_METHOD} GET
RewriteCond "%{QUERY_STRING}" action=(.+)
RewriteRule / https://new.example/?action=SYSTEM&system=%1?
Unfortunately I can't get the expected result.
Your rules have several problems:
You aren't matching the human/ in the URL path that you are trying to remove.
Neither your condition nor your rule has regex markers for "starts with" (^) or "ends with" ($) which means that they are matching substrings rather than full strings.
Your rule starts with a slash which means that it can't be used in .htaccess, only in Apache's conf files. I recommend starting rules with an optional slash /? so that they can be used in either context.
Your query string condition is only matching one of the two parameters that you say need to be present to redirect.
(.+) in your query string condition can match too much. It would include other parameters separated by an ampersand (&). This should be changed to ([^&]+) meaning "at least one character not including ampersands"
You have an extra stray ? at the end of your target URL that would be interpreted as part of the value of the system parameter.
You don't explicitly specify flags for redirect ([R]) or last ([L]) which are best practice to include.
RewriteEngine On
RewriteCond %{REQUEST_METHOD} GET
RewriteCond %{QUERY_STRING} ^system=([^&]+)&action=([^&]+)$
RewriteRule ^/?human/$ https://new.example/?action=%2&system=%1 [R,L]

htaccess rewrite condition that uses regex

I'm a noob when it comes to regex. What I'm trying to accomplish is:
https://www.example.com/shop/product-floating-front-rotor-kit/
should redirect to
https://www.example.com/shop/product-matching-front-rotor/
product should be the name of the product, I have to do this for multiple products.
Edit: This is what I have so far, am I even close?
RewriteEngine On
RewriteRule ^/shop/([a-z]+)-floating-front-rotor-kit/ ^/shop/$1-matching-front-rotor/
RewriteRule ^/shop/([a-z]+)-floating-front-rotor-kit/ ^/shop/$1-matching-front-rotor/
This is close, except that...
In .htaccess the URL-path matched by the RewriteRule pattern (first argument) does not start with a slash.
The substitution string has an erroneous ^ prefix. This should be an "ordinary" string, not a regex.
[a-z] does not match hyphens/dashes, which you state could occur in a product name.
You have not included an end-of-string anchor ($) on the end of the RewriteRule pattern, so any trailing string will be successful and discarded. (Is that the intention?)
This is an internal "rewrite", not a "redirect" as stated. You need to include the R flag. (An internal rewrite is unlikely to work here, since the target URL requires further rewriting.)
Try the following instead. This should go at the top of the .htaccess file, immediately after the RewriteEngine directive.
RewriteRule ^shop/([a-z-]+)-floating-front-rotor-kit/$ /shop/$1-matching-front-rotor/ [R=302,L]
This is a 302 (temporary) redirect.

htaccess RewriteRule : Problem to omit all after 1st argument

Goal: Want to rewrite all URLs of type
https://www.example.com/page/1234/?/blog/foo/bar/
to
https://www.example.com/page/1234/
In .htaccess I tried many variations along the line
RewriteEngine On
RewriteBase /
RewriteRule ^page/(\d+)/(.*)$ /page/$1 [R=301,L]
Using an .htaccess tester I see that at least the matching pattern is valid.
I would expect that the rewrite would not include anything after $1, but it does, and show the complete original URL.
What am I missing?
https://www.mypage.com/page/1234/?/blog/foo/bar/
Everything after the first ? is the query string part of the URL. By default, Apache passes the query string unaltered from the request to the target URL (unless you create a new query string yourself on the RewriteRule substitution). This explains why you are seeing the same query string on the target URL, without seemingly doing anything with it.
Incidentally, the RewriteRule pattern only matches against the URL-path only - this notably excludes the query string. To match the query string in mod_rewrite you need an additional condition that checks the QUERY_STRING server variable.
On Apache 2.4+ you can use the QSD (Query String Discard) flag to remove the query string from the target URL. Or, specify an empty query string on the substitution - by including a trailing ? (the ? itself does not appear on the resulting URL).
For example (on Apache 2.4):
RewriteCond %{QUERY_STRING} .
RewriteRule ^page/(\d+)/ /page/$1/ [QSD,R=301,L]
The RewriteCond directive checks for the presence of a query string, which is necessary to prevent a redirect loop.
The trailing (.*)$ on the RewriteRule pattern was superfluous.
You had omitted the trailing slash on the end of the substitution (that is present on the example URL). This would have also prevented a redirect loop, but as mentioned, this is not as per your example. (Alternatively, you could include the slash in the captured backreference.)
If you are still on Apache 2.2 then you would need to include a trailing ? instead of the QSD flag. For example:
RewriteRule ^page/(\d+)/ /page/$1/? [R=301,L]
You will need to clear your browser cache before testing, as 301 (permanent) redirects are cached persistently by the browser. For this reason, it is often easier to first test with 302 (temporary) redirects.

.htaccess redirect for specific URL structures

I have the following URL:
https://www.site-a.xyz/tutorials/post-name/2
I need it to redirect to the following URL
https://www.site-b.xyz/post-name/2
Essentially If there is a trailing number element to the URL (in this case /2) I need the /tutorials/ part of the URL to be removed.
Note: ONLY if there is a trailing number
Try the following (using mod_rewrite) near the top of your .htaccess file at www.site-a.xyz:
RewriteEngine On
RewriteRule ^tutorials/([^/]+/\d+)$ https://www.site-b.xyz/$1 [R=302,L]
In this case, the trailing "number" can be 1 or more digits. If it is only a single digit (as in your example) then this should be simplified (change \d+ to \d). The $1 is a backreference to the captured group in the RewriteRule pattern.
Note that this is a 302 (temporary) redirect, if this is intended to be permanent then change to 301 when you are sure it's working OK. 301s are cached by the browser so can make testing problematic.
UPDATE: To allow for an optional trailing slash on the source URL then add /? near the end of the RewriteRule pattern, like so:
RewriteRule ^tutorials/([^/]+/\d+)/?$ https://www.site-b.xyz/$1 [R=302,L]
This notatably strips that optional trailing slash from the redirect target. (Thus avoiding any duplicate content issues.)

Apache URL Rewrite to domain.com/custom_url_name

Using Apache on a Red Hat server, I'm trying to rewrite the URL of a member's store on our website from:
domain.com/store.php?url=12345
to:
domain.com/12345
Using these rules, I can get it to work if I always remember to add an ending slash:
Options -Indexes
Options +FollowSymLinks
RewriteEngine on
RewriteRule ^store/url/(.*)$ store.php?url=$1
RewriteRule ^(.*)/$ store.php?url=$1
domain.com/12345/ works,
but domain.com/12345 does not work.
Removing the slash in the last line of Rewrite code breaks a lot of stuff. Is there a way to get this to work both with or without that ending slash?
What if you made the slash optional? Furthermore, you probably to to specify something more specific than (.*), because domain.com/a/b/c/d/e will match. Instead, you can use a negated character class to specify everything other than a slash.
RewriteRule ^([^/]*)/?$ store.php?url=$1
Alternately, if you only want to capture numbers, you can use the \d shorthand class (which matches any digit) along with a + which specifies that at least one digit must be present:
RewriteRule ^(\d+)/?$ store.php?url=$1
Your attempt using ^(.*)$ fails because that would match any URL path. Use a more specific pattern than .*, maybe \d+ to allow only one or more digits:
RewriteRule ^(\d+)$ store.php?url=$1