Mark
Mark

Reputation: 347

.htaccess - Recursively mapping slashes to underscores (internal redirect)

Related to a previous Question: .htaccess - Recursively mapping slashes to underscores

The code that was listed as the "full solution" worked for 12 months. Then stopped working. The .htaccess code wasn't changed either - just to make things harder.

The Question

Can anyone help me achieve The Desired Outcome?

The Desired Outcome

Take https ://domain.com/this/is/mah/page/structure and show the file /this_is_mah_page_strucutre.php which lives in the root of the website.

The Code Currently

The below is contents from the file

<IfModule mod_negotiation.c>
Options -MultiViews
Options All -Indexes
</IfModule>

<IfModule mod_rewrite.c>
    RewriteEngine on
    DirectorySlash off

    # Error Redirects
        ErrorDocument 404 /incs/404.php

        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME}.php !-f
        RewriteRule ^ - [R=404,L]

    # remove .php
        RewriteCond %{THE_REQUEST} \s/+(.+?)\.php[\s?] [NC]
        RewriteRule ^ /%1 [R=302,NE,L]

        # map the .php extension
        RewriteRule ^([^.]+?)/?$ $1.php [L]

    # map the slashes to underscores
        # when there are more than one / then "recursively" replace it by _
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d

# This next line appears to be the problem
        RewriteRule ^([^/]+)/([^/]+/.+)$ $1_$2 [N,DPI]


# This next section appears to be doubling up, but was originally meant to catch anything that missed the previous block
        # when there is only one / then replace it by _ and redirect
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteRule ^([^/]+)/([^/]+)$ /$1_$2 [L]

</IfModule>

The Possible Problem

As noted, RewriteRule ^([^/]+)/([^/]+/.+)$ $1_$2 [N,DPI] doesn't seem to work as intended.

If https://htaccess.madewithlove.be/?share=9bd3c5a0-4002-4324-a82e-0065b7286f82 is to be believed, then what is happening is that the [N] isn't causing the recursion (a) I require, and (b) it used to provide.

The MadeWithLove tester outcome states that /this/is/mah/page/structure is becoming /this_is/mah/page/structure.

I have tried rejiggering the PCRE RegEx, and so has @anubhava - but have been unable to get it working.

The Server

The server is using version 2.4.37-30.module_el8.3.0+561+97fdbbcc for httpd and is running on CentOS 8. The code in question was migrated from CentOS 7 about 5 months go, and it's been working happily till about the last 7 days.

As far as the Apache settings and .htaccess file, nothing has changed within the last two weeks.

Upvotes: 1

Views: 62

Answers (2)

anubhava
anubhava

Reputation: 785276

Have it this way:

<IfModule mod_negotiation.c>
Options All -Indexes -MukltiViews
</IfModule>

<IfModule mod_rewrite.c>
    RewriteEngine on
    DirectorySlash off
    # Error Redirects
    ErrorDocument 404 /incs/404.php

    RewriteCond %{REQUEST_FILENAME} -d [OR]
    RewriteCond %{REQUEST_FILENAME} -f
    RewriteRule ^ - [L]

    # remove .php
    RewriteCond %{THE_REQUEST} \s/+(.+?)\.php[\s?] [NC]
    RewriteRule ^ /%1 [R=301,NE,L]

    # map the slashes to underscores
    # when there are more than one / then "recursively" replace it by _
    # This next line appears to be the problem
    RewriteRule ^([^/]+)/(.+)$ $1_$2 [N,DPI]

    # map the .php extension
    RewriteCond %{DOCUMENT_ROOT}/$1.php -f
    RewriteRule ^([^.]+?)/?$ $1.php [L]
</IfModule>

Upvotes: 2

Example person
Example person

Reputation: 3346

Try:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^(.+)\/(.*)$
RewriteRule ^ %1_%2 [L]

So, your full htaccess be:

<IfModule mod_negotiation.c>
Options -MultiViews
Options All -Indexes
</IfModule>

<IfModule mod_rewrite.c>
    RewriteEngine on
    DirectorySlash off

    # Error Redirects
        ErrorDocument 404 /incs/404.php

        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME}.php !-f
        RewriteRule ^ - [R=404,L]

    # remove .php
        RewriteCond %{THE_REQUEST} \s/+(.+?)\.php[\s?] [NC]
        RewriteRule ^ /%1 [R=302,NE,L]

        # map the .php extension
        RewriteRule ^([^.]+?)/?$ $1.php [L]

        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteCond %{REQUEST_URI} ^(.+)\/(.*)$
        RewriteRule ^ %1_%2 [L]

</IfModule>

Upvotes: 1

Related Questions