1

I am trying to write a simple rewrite rule that will change:

https://example.com/index.php?shortened_url=value

to

https://example.com/value

To acheive this, I am using the following rewrite rule:

RewriteEngine On
RewriteRule ^([^/]*)$ /index.php?shortened_url=$1 [L]

But I receive the error:

Request exceeded the limit of 10 internal redirects due to probable configuration error.

Clearly this suggests there is a looping issue somewhere but as far as I can tell my rule is quite straight forward and shouldn't cause any looping?

Syn
  • 141
  • 1
  • 4
  • I assume this must be in `.htaccess` (or a `` container)? As otherwise a pattern like `^([^/]*)$` will never match anything if used in the server config. (Note that if you don't explicitly state `.htaccess` then it's natural to assume you are talking about the server config when asking questions on ServerFault.) – MrWhite Oct 04 '17 at 13:52
  • Possible duplicate of [Redirect, Change URLs or Redirect HTTP to HTTPS in Apache - Everything You Ever Wanted to Know About Mod\_Rewrite Rules but Were Afraid to Ask](https://serverfault.com/questions/214512/redirect-change-urls-or-redirect-http-to-https-in-apache-everything-you-ever) – Jenny D Oct 05 '17 at 08:12

2 Answers2

1

First of all you misplaced the arguments for the RewriteRule command, the order is

RewriteRule WHAT WHERE [OPTIONS] (shortcut to simplify things - refer to the documentation)

There's more about RewriteRule here http://httpd.apache.org/docs/current/mod/mod_rewrite.html

And what your rule actually does is rewriting any number of slashes / to the /index.php?shortened_url=$1 if I'm not mistaken.

So your https://example.com/ is redirected to the long URL as well as https://example.com/////////

You need to brush up with your regexp skills - try this link to help you https://regexr.com/

And finally the rule that you are looking for should be something like :

RewriteRule ^/index.php\?shortened_url=(.*)$ https://example.com/$1 [L]

bocian85
  • 822
  • 5
  • 10
  • Isn't it RewriteRule PATTERN SUBSTITUTION [FLAGS] ? – Syn Oct 04 '17 at 13:13
  • I just wanted to make a simple explanation, yours is more technical, however still, the order You have used initially is totally reversed – bocian85 Oct 04 '17 at 13:19
  • "rewriting any number of slashes /" - That's not what the `([^/]*)` regex says. `[^/]` is a _negated_ character class, so it matches anything _except_ a slash, 0 or more times. So, it effectively matches the first path segment. You also can't use the `RewriteRule` _pattern_ to match the query string. In order to match the query string, you must use a `RewriteCond` directive and check against the `QUERY_STRING` server variable. – MrWhite Oct 04 '17 at 13:34
  • Yes, correct, I guess I need to brush up on my regex instead – bocian85 Oct 04 '17 at 13:44
1
RewriteRule ^([^/]*)$ /index.php?shortened_url=$1 [L]

This will result in a rewrite loop because /index.php?shortened_url=value will get further rewritten to /index.php?shortened_url=index.php (again and again).

One way to prevent this rewrite loop is to only rewrite when there is no query string (providing you aren't using the query string for other purposes on this URL). For example:

RewriteCond %{QUERY_STRING) ^$
RewriteRule ^([^/]*)$ /index.php?shortened_url=$1 [L]

Or, exclude dots from the RewriteRule pattern. For example:

RewriteRule ^([^/.]*)$ /index.php?shortened_url=$1 [L]

The important thing to note here is that the L (last) flag does not stop all processing when used in per-directory .htaccess files. It simply stops the current round of processing. The rewriting process effectively starts over until the URL passes through unchanged. You need to prevent the rewritten URL from being further rewritten.

that will change:

https://example.com/index.php?shortened_url=value

to

https://example.com/value

bocian85 certainly has a point regarding your description, as your code is doing the complete opposite. Your code rewrites https://example.com/value to https://example.com/index.php?shortened_url=value. (Presumably you have already changed the URLs in your application to be of the form https://example.com/value?)

However, the code looks like it's doing the correct thing, so I think it's just your description that is back to front. (?) (Curious... people often describe this as you have done - in the reverse order - as if they are describing the net result in the application, rather than what the directive actually does.)

MrWhite
  • 12,647
  • 4
  • 29
  • 41