0
votes

I know that this question may be duplicate or answered in the past but I have read the apache.org site and have seen many other similar answers and I cannot find a proper solution to my problem so far since I am novice in the .htaccess and apache.

For simplicity reasons let's assume that the URL of my site is: https://www.example.com

The main page is index.php and there is a submit form with 3 select/dropdowns elements with names: sp, ar and in. sp is mandatory (user has to enter a value), ar and in are optionals.

When I submit the form, the file results.php is executed. When all 3 dropdowns have values, the form of the submitted URL is:

1) https://www.example.com/results.php?sp=textvalue1&ar=textvalue2&in=textvalue3

Moreover, depending if the ar and in have (or haven't) values, the other possible forms of the URL are:

2) https://www.example.com/results.php?sp=textvalue1&ar=&in= 
3) https://www.example.com/results.php?sp=textvalue1&ar=textvalue2&in= 
4) https://www.example.com/results.php?sp=textvalue1&ar=&in=textvalue3 

I want to convert these "ugly" URLs to SEO-friendly URLs.

For case 1 (all 3 dropdowns have values), I would like to submit the form and see in my browser's URL field:

(case 1) https://www.example.com/textvalue1/textvalue2/textvalue3

and get the same results (important)!

Similarly, I want the other SEO-friendly URLs to be:

(case 2) https://www.example.com/textvalue1
(case 3) https://www.example.com/textvalue1/textvalue2
(case 4) https://www.example.com/textvalue1/textvalue3

My guess is that I have to do 2 things: First, to convert the ugly URL to a SEO-friendly URL and, second, to treat the new SEO-friendly URL as if it was the old ugly one.

I have tried the following commands in my .htaccess file for case 2 so far but nothing happened:

Options +FollowSymlinks -Indexes -MultiViews
RewriteEngine On
RewriteCond %{THE_REQUEST} \s/results\.php\?sp=([a-zA-Z]+)\s [NC]
RewriteRule ^ /%1? [R=302,L]
RewriteRule ^/([[a-zA-Z]]+)$ /results.php?sp=$1 [L]
1
This won't work. Certainly you can implement redirection and rewriting rules for this. But you have, as far as I can tell, no way to decide what a URL like https://www.example.com/foo/bar actually tries to express: what is bar meant to be a value for? ar or in? - arkascha
But what about using multiple/different conditions and rules, one for each case? - dimmat
Sure, if you can name conditions to tell both meanings apart, then you can implement those. But you did not name any in your question. So what are they? - arkascha
I am a little confused by your answer. As far as I know, there is no need to name the conditions, only to use the right regex values in order to decide where to apply the RewriteRule. - dimmat
The issue is not whether you can apply a rule. You are absolutely right that you just need to have a matching regular expression. The issue I point out here is: if you have a matching regular expression for the example URL I mentioned in my first comment, then what GET argument will you assign the value bar to that you captured in the incoming request? Will you assign it to ar or to in? This is not defined in any way in your question and I cannot sport any logic for that. So again: can you name a condition or a logic by which to decide what case is actually meant by the URL? - arkascha

1 Answers

1
votes

As already discussed in the comments to the question I see an issue with the question regarding the rewriting logic. You asked to show a more simplified approach for the situation where all three request arguments are present. Here is a suggestion that also handles the case where only two arguments are specified. You don't even need conditions for that, the matching pattern is enough for such logic:

RewriteEngine on

RewriteCond %{REQUEST} !-f
RewriteCond %{REQUEST} !-d
RewriteRule ^/?([^/]+)/([^/]+)/([^/]+)$ /results.php?sp=$1&ar=$2&in=$3 [END]
RewriteRule ^/?([^/]+)/([^/]+)$ /results.php?sp=$1&ar=$2 [END]

RewriteCond ${QUERY_STRING} ^sp=(.+)&ar=(.+)&in=(.+)$  
RewriteRule ^/results\.php$ /%1/%2/%3 [R=301,END]
RewriteCond ${QUERY_STRING} ^sp=(.+)&ar=(.+)$  
RewriteRule ^/results\.php$ /%1/%2 [R=301,END]

That rule set will work likewise in the http servers host configuration and also in a dynamic configuration file (".htaccess" style file). A general remark here: you should always prefer to place such rules in the http servers host configuration instead of using dynamic configuration files (".htaccess"). Those dynamic configuration files add complexity, are often a cause of unexpected behavior, hard to debug and they really slow down the http server. They are only provided as a last option for situations where you do not have access to the real http servers host configuration (read: really cheap service providers) or for applications insisting on writing their own rules (which is an obvious security nightmare).

In case you experience an "internal server error" (http status 500) using above rule set then chances are that you operate a very old version of the apache http server. In that case replace the END flag with the L flag. You will find a specific hint on the unsupported END flag in your http servers error log file in that case.

Once more: if you can name a logic by which to decide which request argument to assign the second value captured by the second rule if it gets applied, then it would be possible to implement such a condition and handle all three cases you originally mentioned. But without you specifying such logic it is impossible to implement something.