I am working on some SEO for my site, and using urls like category/this-cat.html and category/this-cat-p2.html to redirect to index.php?mode=viewCat&id=this-cat and index.php?mode=viewCat&id=this-cat&start=10 respectively.
The problem is that my RewriteRule needs a conditional to check if the -p2 part is present in the URL, and then return either 0 or the digit after p.
Current rule:
RewriteRule ^category/(.*?)\.html$ index.php?mode=viewCat&title=$1
I would have thought that the correct syntax for this would have been:
RewriteRule ^category/(.*?)(?(-p)(.*?)|0)\.html$ index.php?mode=viewCat&title=$1&start=$2
however, this causes the server to return a 500 error.
Even after having read tutorials and worked with them for the past week, I still have little grasp on them. Can anyone explain how to make a conditional like this work?
You're close. I believe what you are trying to do is not capture the optional -p# grouping, but want the digit if it exists. The non-capture flag for a group is a ?: prefix.
RewriteRule ^category/(.*?)(?:-p(\d+))?\.html$ index.php?mode=viewCat&title=$1&start=$2
Note: I used \d (digit) as it's better to be specific about what you are matching. Also start will have a digit or nothing. Your server-side code is better suited to handle the rest of the logic you described.
Related
I'm not used to regex and figure I've lost too many hours trying to resolve this, so thought I'd ask for help. I am trying to prettify the html extension.
My site will use URLs that have variable parameters. For example:
mysite.com/article/this-is-an-entry
mysite.com/article/this-is-an-entirely-different-entry
All will use .html as the extension.
In the htaccess file, I have tried
RewriteRule ^(article\/[a-z].*)$ $1.html [NC,L]
as well as slight variations of this, but cannot get this right. Thanks in advance for any assistance.
Firstly, let's look at the regex you have:
^(article/[a-z].*)$
This matches exactly the string "article/", followed by at least one letter (case insensitive due to the NC flag), followed by zero or more of anything. It's quite broad, but should match the examples you gave.
One way to test that it's matching is to add the R=temp flag to the rule, which tells Apache to redirect the browser to the new URL (I recommend using "=temp" to stop the browser caching the redirect and making later testing harder). You can then observe (e.g. in your browser's F12 debug console) the original request and the redirected one.
RewriteRule ^(article/[a-z].*)$ $1.html [NC,L,R=temp]
However, as CBroe points out, your rule will match again on the target URL, so you need to prevent that. A simple way would be to use the END flag instead of L:
Using the [END] flag terminates not only the current round of rewrite processing (like [L]) but also prevents any subsequent rewrite processing from occurring in per-directory (htaccess) context.
So:
RewriteRule ^(article/[a-z].*)$ $1.html [NC,END]
Alternatively, you can make your pattern stricter, such as changing the . ("anything") to [^.] ("anything other than a dot"):
^(article/[a-z][^.]*)$
To be even more specific, you can add a RewriteCond with an extra pattern to not apply the rule to, such as "anything ending .html".
While I'm good with many things scripting and programming, the one thing I never really got into is regex.
I'm tweaking a third party script that uses the url structure of site.com/username/p/seo-friendly-link. I want it to be site.com/username/seo-friendly-link instead
its .htaccess file has
RewriteRule ^([A-Za-z0-9_-]+)/p/(.*)$ ./dir/pages/post.php?user=$1&pid=$2
RewriteRule ^p/(.*)$ ./dir/pages/post.php?pid=$1
when I remove /p as
RewriteRule ^([A-Za-z0-9_-]+)/(.*)$ ./dir/pages/post.php?user=$1&pid=$2
I see it the error in the apache logs as
[error] [client ::1] Request exceeded the limit of 10 internal redirects due to probable configuration error. Use 'LimitInternalRecursion' to increase the limit if necessary. Use 'LogLevel debug' to get a backtrace.
I've tried adding the L to the end of the unmodified rule and it still gives the same error.
I want to learn regex, but I feel like this particular example isn't that noob friendly and it'd instead led to more confusion.
can someone explain what those two lines do, how to get what I need or why it's not as simple as it seems?
Not an expert in .htaccess configuration rules, but as far the regex is concerned the problem seems to be that ^([A-Za-z0-9_-]+)/(.*)$ covers too many possible matches because of the last (.*) group which literally matches anything.
In other words, ^([A-Za-z0-9_-]+)/(.*)$ matches both username/p/seo-friendly-link and username/seo-friendly-link. It will also match the target part dir/pages/post.php?user=$1&pid=$2, probably leading to the infinite redirects.
To restrict the regex, you should exclude the / from the second group. So instead of (.*), use [^/]* where [^/] defines a character class that matches any character except /:
RewriteRule ^([A-Za-z0-9_-]+)/([^/]*)$ ./dir/pages/post.php?user=$1&pid=$2
Change the first line to
RewriteRule ^([A-Za-z0-9_-]+)/p/(.*)$ ./dir/pages/post.php?user=$1&pid=$2 [L,NC,R]
This makes the url redirect and asserts it is the last rule to be checked.
At the moment I'm not really good in unterstanding how URL Rewrite in htaccess works (with regEex).
I want to have following Url:
example.org/lyrik/kategorien/allgemein-1/
It should go to following Url with the number at the at as parameter:
example.org/index.php?seite=kategorienDetail&kategorienId=1
I have tried different ways but they all dont work. The last I have tried was:
RewriteRule ^lyrik/kategorien/allgemein-([0-9]+)\$ index.php?seite=kategorienDetail&kategorienId=$1 [L}
This one made problems on the whole website. every page was inaccessible.
Can someone show me a Rewrite Rule that works in my case and explain the RegEx in it?
I think you have some typos in your rule. Try it this way.
RewriteRule ^lyrik/kategorien/allgemein-([0-9]+)/?$ index.php?seite=kategorienDetail&kategorienId=$1 [L]
Note that I used the ? after the / so that it can be optional. You had a backslash. Also at the end of your rule you had a curly brace instead of the bracket.
EDIT
Based on your comment. Then you can use this if part of the URI is not constant.
RewriteRule ^lyrik/kategorien/([^/]+)-([0-9]+)/?$ index.php?seite=kategorienDetail&kategorienId=$2 [L]
Also this [0-9]+ just means it has to be a number from 0-9 to match the rule and the plus sign means 1 or more basically saying it can't be empty. The * basically means any including a blank(0 or more occurrences). Because your link always ends with a number limiting it to 0-9 in the regex ensures that it won't work if any other character is used there in the URL.
You can see more about regex here.
http://www.regular-expressions.info/tutorial.html
Please try this:
RewriteRule ^lyrik/kategorien/allgemein-(.*?)/$ index.php?seite=kategorienDetail&kategorienId=$1 [QSA,L]
I am writing from the top of my head, but it should work. Let me know if it doesn't, but it should :)
Edit: Please add the QSA flag also to pass any other query parameters you might have.
Alex
I have a bunch of crawl errors on my site to pages that don't exist (and never existed). It was created from some bad code that generated JSON-LD schema.org for a search page. Basically, I have thousands of 404s that look like this
http://www.domain.com/search/%7Bsearch_term%7D%2Fpage%2F2%2Fpage%2F3%2Fpage%2F6%2Fpage%2F2%2Fpage%2F3%2Fpage%2F6%2Fpage%2F6%2Fpage%2F2%2Fpage%2F2%2Fpage%2F3%2Fpage%2F2%2Fpage%2F6%2Fpage%2F3%2Fpage%2F2%2Fpage%2F6%2Fpage%2F3%2Fpage%2F2%2Fpage%2F7%2Fpage%2F2%2Fpage%2F2%2Fpage%2F8%2Fpage%2F3
http://www.domain.com/search/%7Bsearch_term%7D%2Fpage%2F2%2Fpage%2F6%2Fpage%2F2%2Fpage%2F3%2Fpage%2F6%2Fpage%2F2%2Fpage%2F6%2Fpage%2F6%2Fpage%2F6%2Fpage%2F2%2Fpage%2F3%2Fpage%2F3%2Fpage%2F3%2Fpage%2F2%2Fpage%2F2%2Fpage%2F3%2Fpage%2F7%2Fpage%2F2%2Fpage%2F7%2Fpage%2F2%2Fpage%2F8%2Fpage%2F3
I am terrible with regex, and could use some help on figuring out how to resolve this. As a short term solution, I just want to redirect URL requests with /search/{search_term}/ in the URL to just the /search page.
Any tips on what I should be doing? This is what I have been messing around with which is obviously wrong. Sorry if this is terribly easy question, but I've been trying different things I find online, and have just beating my head without success.
RewriteRule ^/search/%7Bsearch_term%7D$ /search [R,L=301]
RewriteRule ^/search/\{search_term\}$ /search [R,L=301]
You're pretty close. You can use this rule:
RewriteRule ^search/\{search_term\} /search [R,L=302,NC]
Or if search_term is also a dynamic string then use:
RewriteRule ^search/\{[^}]+\} /search [R,L=302,NC]
EDIT: You will need this directive in your Apache or vhost config:
AllowEncodedSlashes On
otherwise Apache rejects requests with these special characters without giving you any chance to handle them in mod_rewrite.
Just off the top of my head, this should do it:
RewriteRule ^search\/(.+) http://www.yourdomain.com/search [R=302]
Explanation of the syntax above:
^ indicates the start of the match
\ is the escape character, so \/ means escape the forward slash (probably unnecessary, but does no harm)
() is a capture group
. means any character
+ means one or more of
So the whole regex means:
starting at the current position in the folder hierarchy, match
search/
followed by one or more characters.
N.B. Importantly, it is the R flag which indicates the type of redirect, so you need R=302, (not L=302, which doesn't exist)
I've been working out an htaccess redirect directive for (example) an online shop.
Products are displayed on product.php, with an ID parameter passed in.
What I'm aiming for is to have
products/someValue/someID
map to
product.php?param1=someValue¶m2=someID
Here's where I'm at so far. This mostly works, but a couple of things are not quite what I want. I need it to basically separate everything after products/ by forward slashes and use each of those as a parameter, regardless of how many or few. also, a trailing slash is optional - my rule throws a 404 if it's not included. Can anyone point me in the right direction?
RewriteRule ^products/(.*)/(.*)/.*$ /product.php?param1=$1¶m2=$2
Your current regex is greedy. Quantifiers are greedy by default. Adding a ? makes them ungreedy. Or you can change your regex to match anything except / Either of these should work:
RewriteRule ^products/(.*?)/(.*?)(/.*)?$ /product.php?param1=$1¶m2=$2
RewriteRule ^products/([^/]*)/([^/]*)(/.*)?$ /product.php?param1=$1¶m2=$2
Read up on greediness in regexes to understand this better.
Try changing the regex to non-greedy:
RewriteRule ^products/(.*?)/(.*?)/.*$ /product.php?param1=$1¶m2=$2
or:
RewriteRule ^products/([^/]+)/([^/]+)/.*$ /product.php?param1=$1¶m2=$2