1

I've got a site with SSL (Certbot) enabled and so I've setup my 301 redirects in the /etc/apache2/sites-available/example.com-le-ssl.conf file. I did it this way since the non-ssl virtual host (:80) redirects everything to :443 as far as I understand it.

Some of the redirects work, but if the URL fragment is the same (except moved into a parent URL slug) then I get a redirect loop. Also, blog posts with a GET parameter aren't being picked up at all.

Like so:

# This works
Redirect 301 /foobar https://www.example.com/slug/foo-bar/

# This loops
Redirect 301 /foo-bar https://www.example.com/slug/foo-bar/

# This doesn't seem to redirect at all
Redirect 301 /article.cfm?blogid=9 https://www.example.com/blog/pretty-name/

I can guess that the looping one redirects properly the first time, but then also sees /foo-bar at the end of the new URL and attempts another redirect. I end up with a URL in the browser bar that looks like:

https://www.example.com/slug/foo-bar///////

Until I get an error from Chrome about redirect loops.

So, I thought that the leading / right after Redirect 301 only picked up the URL fragment starting from immediately after the base of the FQDN?

And is there any reason why a 301 with a GET parameter (e.g. /article.cfm?blogid=9) doesn't work either?

I Googled around but so much of what I found is just about moving non-www to www or non-ssl to ssl. I also find the documentation a bit obtuse.

EDIT: These directives are directly inside of the <VirtualHost> and not inside of a <Directory> block. From the non-ssl config, 3 different domains are being redirected to the new, canonical domain. Rather than having a non-canonical domain redirect to https and then to the canonical, I changed the RewriteRule to direct all to the https version of the canonical. I also removed the trailing slashes from the 301 redirect lines in the ssl config file.

  • 1
    So these directives are directly inside the 443 Virtual Host container? Not inside a <Directory> wrapper? What other directives do you have? Are .htaccess enabled? Any .htaccess files? What are the URLs you are requesting? Do these map to physical files (I assume not)? – MrWhite Nov 2 '18 at 20:00
1
# This loops
Redirect 301 /foo-bar https://www.example.com/slug/foo-bar/

I can guess that the looping one redirects properly the first time, but then also sees /foo-bar at the end of the new URL and attempts another redirect.

Nope, by itself this would not cause a loop. The mod_alias Redirect directive is prefix-matching - it matches the start of the URL, not the "end of the URL".

Either...

  • You are seeing a cached redirect (since you are testing with 301 permanent redirects). Unless you are careful to disable the browser cache whilst testing, you should test with 302 (temporary) redirects until you have confirmed it works as expected.
  • There is a conflict with other directives.
  • You've not restarted the web server, after making these changes to the server config.

However, since you have omitted the trailing slash on the source URL-path (ie. /foo-bar), but you have included the trailing slash on the target URL then if you were to request /foo-bar/ (with a trailing slash) then this would result in a redirect to https://www.example.com/slug/foo-bar// (double trailing slash), but still no loop. This is because with the Redirect directive, everything after the initial match is appended to the end of the target URL.

You would see a redirect loop like the following:

https://www.example.com/slug/foo-bar///////

If you had a directive like:

Redirect 301 /slug/foo-bar https://www.example.com/slug/foo-bar/

And requested /slug/foo-bar/ (with a trailing slash). If you want a one-to-one redirect then you need to use RedirectMatch or use mod_rewrite instead.

So, I thought that the leading / right after Redirect 301 only picked up the URL fragment starting from immediately after the base of the FQDN?

Yes, that is correct.

# This doesn't seem to redirect at all
Redirect 301 /article.cfm?blogid=9 https://www.example.com/blog/pretty-name/

And is there any reason why a 301 with a GET parameter (e.g. /article.cfm?blogid=9) doesn't work either?

Yes. You can't match the query string with the Redirect directive. The Redirect directive matches against the URL-path only, which excludes the query string.

If you want to match against the query string then you need to use mod_rewrite and check against the QUERY_STRING server variable. For example:

RewriteEngine On
RewriteCond %{QUERY_STRING} ^blogid=9
RewriteRule ^/?article\.cfm https://www.example.com/blog/pretty-name/ [R,L]

"pretty-name" - However, you'll need to be careful of redirect loops, since you are presumably rewritting the "pretty-name" later in the request. (?) If this is the case, then this redirect is not strictly necessary, unless these URLs have already been indexed or linked to by external third parties.

Note also, that once you start using mod_rewrite for some redirects/rewrites then it is advisable to convert all your mod_alias redirects (Redirect and RedirectMatch) to use mod_rewrite (RewriteRule) in order to avoid unexpected conflicts. Different modules execute at different times during the request, despite their apparent order in the config file (mod_rewrite executes first).

  • 1
    Great answer! I'll digest, try some of these and see if I can report back having learned something. If it's correct, I'll mark as so - thanks for your time! – armadadrive Nov 3 '18 at 0:10
  • Is there a chance that these redirects being in the virtual host for :443 an issue? Should they be in the block for :80? – armadadrive Nov 3 '18 at 0:13
  • Oh the other thing I neglected to check is the .htaccess file wordpress generates. Because it has never caused issues before, I didn't think to. And since I have root access, I've always done my redirects in the server block level and not at the htaccess level. – armadadrive Nov 3 '18 at 0:15
  • If these redirects are only intended to redirect requests for HTTP then they should go in the :80 virtual host, otherwise having them in the :443 virtual host is fine. Presumably you have a single Redirect directive in the :80 block that just redirects everything to HTTPS? The .htaccess will only cause issues if the directives in your vHost container are also in a <Directory> container. – MrWhite Nov 3 '18 at 0:26
  • So, I've solved the Redirect loop seemingly by getting rid of the trailing / on the absolute path (the new URL). Why would this have been an issue? – armadadrive Nov 3 '18 at 12:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.