2

This: example.com/test/ should redirect to: example.com/en/test/, but: example.com/es/test/ shoudn't redirect.

in this case /test/ could be anything, with any number of levels (i.e.: /test/succeeded/ or / ).

It's an apache server, with .htaccess.

...
RewriteEngine on
RewriteRule . - [E=REWRITEBASE:/]
RewriteRule ^api$ api/ [L]

RewriteRule ^api/(.*)$ %{ENV:REWRITEBASE}webservice/dispatcher.php?url=$1 [QSA,L]

RewriteRule ^images_ie/?([^/]+)\.(jpe?g|png|gif)$ js/jquery/plugins/fancybox/images/$1.$2 [L]
.... 
#At the end of the file I have some redirects:
RedirectMatch 301 ^/es/manufacturer/(.*)$ /es/bodegas/$1
RedirectMatch 301 ^/en/manufacturer/(.*)$ /en/wineries/$1

Edit: Some asked what I've tried, and at the time of the question I hadn't tried because my regex knowledge is that bad. But thanks to a response I've tried some things:

RewriteRule !^(en|es)/(.*)$ /es/$1 [R=302,L] # From the response
RedirectMatch 302 !^/(en|es)/(.*)$ /es/$1 #Tried with a redirectmatch and adding starting / didn't work either
1
  • It would be useful to add your entire .htaccess file to your question. (I assume from the ... that some parts are purposefully omitted.) Since you are seeing index.php in the redirected URL then this perhaps suggests you have a "front-controller" (mod_rewrite directives) that rewrites to index.php - this is not currently shown in the directives you've posted?
    – MrWhite
    Aug 16 '18 at 12:19
1

Try something like the following, using mod_rewrite, near the top of your .htaccess file:

RewriteEngine On
RewriteRule !^(en|es)/ /en%{REQUEST_URI} [R=302,L]

This states that for any requested URL that does not start /en/ or /es/ then redirect (302 - temporary) to /en/<requested-url>.

(Only change to a 301 - if that is what's required - once you have tested that it works OK.)

UPDATE:

Also REQUEST_URI appended index.php to the end of the url.

If you are seeing index.php in the URL then the mostly likely causes for this are either:

  • You've put the directive in the wrong place, ie. too late in the file. Any redirects need to go near the top of the file, before any existing rewrites. The order is important.

  • You have a conflict with another (possibly a mod_alias) directive.

    Since you've updated the question I see you have redirects/rewrites from both mod_rewrite (RewriteRule) and mod_alias (RedirectMatch). Different modules execute independently and at different times throughout the request. mod_rewrite will always execute first, despite the apparent order in the file. This can lead to (unexpected) conflicts. Ideally, you need to convert all your mod_alias redirects to use mod_rewrite RewriteRule instead (and make sure they are then in the correct order).

RewriteRule !^(en|es)/(.*)$ /es/$1 [R=302,L] # From the response

This would never work as expected, since you can't have capturing groups in a negated regex, they will simply never match anything and the $1 backreference will always be empty.

Aside: Also, Apache does not support line-end comments (ie. # From the response at the end of the directive on the same line). It appears to work OK in this instance because of the way Apache processes the directives (everything after a valid directive is simply ignored). But if you were to remove the 3rd argument (ie. the flags [R=302,L]) - which is still perfectly valid - then you'd get a 500 Internal Server Error. This is because Apache will then try to parse the "comment" as the flags argument which is wholly invalid.

7
  • Hey thanks for the quick answer. I've tried it and it couldn't redirect. Also REQUEST_URI appended index.php to the end of the url. I'll update the question with the .htaccess as of now.
    – gpisw
    Aug 14 '18 at 12:18
  • If you are seeing index.php in the redirected URL then it implies you've put the directive in the wrong place. Any redirects need to go near the top of your .htaccess file. The directive you added to your question (RewriteRule !^(en|es)/(.*)$ /es/$1 [R=302,L] # From the response) is very different to the directive I posted above - this will never work as you cannot have a capturing group in a negated regex (which is why I used the REQUEST_URI server variable). If you wanted to use a $1 backreference here then you would need an additional RewriteCond that checks the URL-path.
    – MrWhite
    Aug 14 '18 at 16:50
  • You also shouldn't be mixing redirects from both mod_rewrite (RewriteRule) and mod_alias (RedirectMatch) as you could get conflicts. Different modules execute at different times during the request despite their apparent order in the config file. The .htaccess file you posted also looks incomplete? It's not clear where in the file, you have placed these directives. The order is important.
    – MrWhite
    Aug 14 '18 at 16:55
  • Well, this really is a world. Just to be clear I had tried with the one supplied, and then tried some variations, but none worked. Having said that I've tried again with the supplied rule, putting it right below RewriteEngine On, and it did the same (did redirect to /en, but appended a /index.php to the end). Probably some prestashop module is messing with it. (Maybe it was important to clarify that it's a prestashop site).
    – gpisw
    Aug 16 '18 at 6:23
  • 1
    (You will need to make sure your browser cache is clear if you have previously tested with 301s.) Using RedirectMatch (part of mod_alias) is likely to cause problems in this scenario. And could well expose index.php if you have a front-controller type pattern (that Prestashop may use - although Prestashop is no different to any other CMS in this respect). As mentioned above, mixing redirects/rewrites from mod_alias and mod_rewrite could potentially result in conflicts. Just to confirm, /es and /en don't exist as physical directories on the filesystem?
    – MrWhite
    Aug 16 '18 at 11:57

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.