3

I'm using a Pi 3 for the Apache server but I can't figure out how to setup .htaccess. Previously I used IIS with which it is easy to implement SEO-friendly URLs. Linux .htaccess is very different and I still can't figure it out.

First I created .htaccess in the root folder with the contents:

RewriteRule ^post/article\.php$    {C:1}/{C:2}/{C:3}/{C:4}
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/([^/]+)/?$    post/article.php?a=$1&b=$2&c=$3&id=$4
RewriteRule ^sitemap\.xml?$    sitemap.php

Which is supposed to make example.in/?a=*,b=*,c=*,id=* shown as example.in/a/b/c/id. However, that never happens.

Then I tried these changes to the virtual host. Do I have to change the configuration in the virtual host to get it to work?

<VirtualHost *:80>
    Documentroot /------
    ServerName example.in
    ServerAlias www.example.in
    RewriteEngine On
    RewriteRule ^post/article\.php$    {C:1}/{C:2}/{C:3}/{C:4}
    RewriteRule ^([^/]+)/([^/]+)/([^/]+)/([^/]+)/?$    post/article.php?a=$1&b=$2&c=$3&id=$4
    RewriteRule ^sitemap\.xml?$    sitemap.php
</VirtualHost>

Is anyone able to suggest how can I put rewrite so it actually works?

I also follow guide How to enable use of .htaccess in Apache on Ubuntu? but I could not get it to work.

3
  • 1
    {C:1}/{C:2}/{C:3}/{C:4} - That's an IIS thing. I assume here you are trying to canonicalise any direct request for /post/article.php?a= etc.? ^sitemap\.xml?$ - I assume the trailing l should not be optional?
    – MrWhite
    Mar 15, 2021 at 23:23
  • "I use IIS which is totally easy to complete SEO-friendly tag" - Nooo, Apache is better! ;)
    – MrWhite
    Mar 15, 2021 at 23:33
  • easy to implement you just mention your link there and it just do it itself Mar 25, 2021 at 9:13

1 Answer 1

4
RewriteRule ^post/article\.php$    {C:1}/{C:2}/{C:3}/{C:4}
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/([^/]+)/?$    post/article.php?a=$1&b=$2&c=$3&id=$4
RewriteRule ^sitemap\.xml?$    sitemap.php

If used in .htaccess these directives would result in a malformed internal rewrite - possibly a rewrite-loop (500 Internal Server Error response).

If used in a VirtualHost context they simply won't match so won't actually do anything.

In the <VirtualHost>

To write this in a VirtualHost context (not .htaccess), you would need to do it like the following instead...

Note that if you have implemented an SSL cert and are using HTTPS only (ie. redirecting from HTTP to HTTPS in the <VirtualHost *:80> container) then these directives need to go in the <VirtualHost *:443> container. The <VirtualHost *:80> can be relatively empty.

Your 2nd rule is close as you are really just missing some slash prefixes and flags.

In a server or virtualhost context, the URL-path matched by the RewriteRule pattern is always the full root-relative URL-path, starting with a slash. And the substitution string (target URL) cannot be relative.

Options FollowSymLinks

RewriteEngine On

# Redirect direct requests for "/post/article.php?a=<a>&b=<b>&c=<c>&id=<id>"
# to the canonical URL: "/<a>/<b>/<c>/<id>"
RewriteCond %{THE_REQUEST} \?a=([^&]+)&b=([^&]+)&c=([^&]+)&id=([^&]+)\s
RewriteRule ^/post/article\.php$ /%1/%2/%3/%4 [QSD,NE,R=301,L]

# Rewrite "/<a>/<b>/<c>/<id>" to the underlying filesystem path
RewriteRule ^/([^/]+)/([^/]+)/([^/]+)/([^/]+)$ /post/article.php?a=$1&b=$2&c=$3&id=$4 [L]

# Rewrite "/sitemap.xml" to "/sitemap.php"
RewriteRule ^/(sitemap)\.xml$ /$1.php [L]

The NE flag may be required on the first rule if you have any %-encoded values in the query string, in order to prevent these from being doubly encoded when redirecting to the corresponding URL-path.

The QSD flag discards the query string from the initial request, otherwise, the query string is copied through to the target.

The %1 - %4 backreferences contain the values of the captured groups in the last matched CondPattern (RewriteCond directive).

In .htaccess

To do this in .htaccess you first need to enable .htaccess overrides in the VirtualHost using the AllowOverride directive - otherwise the .htaccess file is going to be ignored. (And note the spelling, you've spelt it wrong 3 times in your question, in varying ways.)

For example:

<VirtualHost *:80>
    ServerName example.in
    ServerAlias www.example.in

    DocumentRoot /path/to/document/root

    <Directory /path/to/document/root>
        Options FollowSymLinks
        Require all granted
        AllowOverride All
    </Directory>
</VirtualHost>

Then, in .htaccess you can write the directives as follows. They are very similar, except there is no slash prefix on the RewriteRule pattern and the substitution string also does not need the slash prefix.

In a directory or .htaccess context, the URL-path matched by the RewriteRule pattern is less the directory-prefix so never starts with a slash. And the substitution string (target URL) can be a relative filesystem path.

For example, in .htaccess:

RewriteEngine On

# Redirect direct requests for "/post/article.php?a=<a>&b=<b>&c=<c>&id=<id>"
# to the canonical URL: "/<a>/<b>/<c>/<id>"
RewriteCond %{THE_REQUEST} \?a=([^&]+)&b=([^&]+)&c=([^&]+)&id=([^&]+)\s
RewriteRule ^post/article\.php$ /%1/%2/%3/%4 [QSD,NE,R=301,L]

# Rewrite "/<a>/<b>/<c>/<id>" to the underlying filesystem path
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/([^/]+)$ post/article.php?a=$1&b=$2&c=$3&id=$4 [L]

# Rewrite "/sitemap.xml" to "/sitemap.php"
RewriteRule ^(sitemap)\.xml$ $1.php [L]

Test with 302 (temporary) redirects to avoid potential caching issues.

3
  • still having no result I was try most of thing that you mention try with log so caught any error in acess.log or error.log but nothing again but due to your answer and httpd.apache.org/docs/current/rewrite/flags.html#flag_qsa give me some direction Mar 25, 2021 at 8:37
  • 1
    I have to use it on 443 port that is where first i go wrong Mar 25, 2021 at 9:19
  • Yes, if you have an SSL cert installed and using HTTPS only then this needs to be in the <VirtualHost *:443>, not port 80. (The vHost for port 80 should then be a simple redirect to HTTPS.) If you are using .htaccess then this is not relevant.
    – MrWhite
    Mar 25, 2021 at 11:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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