简体   繁体   中英

SEO - Friendly URL redirect is not working

On my test server with Apache and php7.1 I can work with an URL like example.com/news/id/title and it redirects me to example.com/news.php but the url is still the same and I can use the Parameters after the slashes.

Now I work on a live hosting and its not working anymore. I tried to redirect with htaccess and it works for example.com/news to redirect to example.com/news.php but if I put anything after that i get an 404 error.

How can I redirect the requests from /news/id/ to news.php where I want to read out the id? And why did that work natively on my test server?

Thousand thanks for any hint.

My actual .htaccess :

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^news/(.*) /news.php/$1 [R=301,NC,L]

Sounds like you may have a conflict with MultiViews (part of mod_negotiation). You need to make sure MultiViews is disabled at the top of your .htaccess file:

Options -MultiViews

If MultiViews is enabled and you make a request for /news/id/ then mod_negotiation makes an internal subrequest for /news.php (without any additional path-info) before mod_rewrite is able to rewrite the request.

why did that work natively on my testserver?

MultiViews is disabled by default on Apache, however, a number of shared web hosts do enable it for some reason. It makes extensionless URLs "magically" work without doing anything, however, this potentially creates duplicate content (bad for SEO) and causes no end of unexpected conflicts with mod_rewrite, such as this.

UPDATE: Change your directives to something like the following instead:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^news/(.*) /news.php/$1 [L]

This internally rewrites (as opposed to _externally redirects_) all requests that start /news/ to /news.php/ - where is passed as _path-info_ to /news.php`. (I assume that passing the URL-path as path-info is the intention? You could instead use the query string or not pass anything in the directive and simply examine the requested URL in PHP? - but this might require marginally more processing in PHP.)

There's no need to check that the target file exists, since it's hardcoded in this example.

Removal of the R flag results in the internal rewrite .

You will need to clear your browser cache since the 301 (permanent) redirect will have been cached by the browser.

If you need a more generic solution that rewrites /<action>/<data> to /<action>.php/<data> then write it like this:

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^([^/]+)/(.*) /$1.php/$1 [L]

Again, no need to check that the request does not map to a file before checking that it does map to a file when .php is appended.

Note that this is not using a TestString of the form %{REQUEST_FILENAME}.php (as you had initially), as this can result in a rewrite loop (500 error) for certain requests. See my answer to the following question on ServerFault that explains this further: https://serverfault.com/questions/989333/using-apache-rewrite-rules-in-htaccess-to-remove-html-causing-a-500-error

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM