Search code examples
laravelapache.htaccessmod-rewrite

htaccess Block all the request if request does not contains specific string patterns


I have a Laravel web site with the localization, for that web site I need to allow the requests with the URL patterns mentioned below. If not match with this URL pattern, need to navigate to the 404 page.

https://www.sampledomain.ch/
https://www.sampledomain.ch/some_text/de
https://www.sampledomain.ch/some_text/it
https://www.sampledomain.ch/some_text/fr
https://www.sampledomain.ch/de
https://www.sampledomain.ch/it
https://www.sampledomain.ch/fr

Can anyone guide me to do this by htaccess file?


Solution

  • 1.) With .htaccess

    Code with comments

    # Run this code IF "mod_rewrite" module was enabled
    <IfModule mod_rewrite.c>
        # Enable server-side redirects
        RewriteEngine On
    
        # If the part after the domain is existed (so not just domain)
        #
        # %{REQUEST_URI}: the part after the domain
        # !^/*$: not empty after "/"
        #
        RewriteCond %{REQUEST_URI} !^/*$
        # AND
        # If the part after the domain not end with de, it, or fr
        #
        # %{REQUEST_URI}: the part after the domain
        # !: not
        # /(de|it|fr): /de or /it or /fr
        # $: need end of url after (de or it or fr)
        # [NC]: treats lowercase and uppercase letters equally
        #
        RewriteCond %{REQUEST_URI} !/(de|it|fr)$ [NC]
        # In that case, it returns a 404 error
        RewriteRule ^ - [R=404,L]
    </IfModule>
    

    Code

    <IfModule mod_rewrite.c>
        RewriteEngine On
    
        RewriteCond %{REQUEST_URI} !^/*$
        RewriteCond %{REQUEST_URI} !/(de|it|fr)$ [NC]
        RewriteRule ^ - [R=404,L]
    </IfModule>
    

    Test Cases

    https://www.sampledomain.ch/ # OK (not redirected)
    https://www.sampledomain.ch/some_text/de # OK (not redirected)
    https://www.sampledomain.ch/some_text/it # OK (not redirected)
    https://www.sampledomain.ch/some_text/fr # OK (not redirected)
    https://www.sampledomain.ch/some_text/some_text/de # OK (not redirected)
    https://www.sampledomain.ch/some_text/some_text/it # OK (not redirected)
    https://www.sampledomain.ch/some_text/some_text/fr # OK (not redirected)
    https://www.sampledomain.ch/de # OK (not redirected)
    https://www.sampledomain.ch/it # OK (not redirected)
    https://www.sampledomain.ch/fr # OK (not redirected)
    
    https://www.sampledomain.ch/some_text/DE # OK (not redirected)
    https://www.sampledomain.ch/some_text/It # OK (not redirected)
    https://www.sampledomain.ch/some_text/rF # OK (not redirected)
    https://www.sampledomain.ch/De # OK (not redirected)
    https://www.sampledomain.ch/iT # OK (not redirected)
    https://www.sampledomain.ch/FR # OK (not redirected)
    
    https://www.sampledomain.ch/FR123 # 404 error
    https://www.sampledomain.ch/fr/test # 404 error
    https://www.sampledomain.ch/a # 404 error
    
    etc.
    

    2.) Using Laravel Route (better option)

    However, if you are using Laravel, it is worth reconsidering the use of the built-in router as well!

    The example, however, requires that we move the language code to the beginning of the URL, which is generally a common practice.

    1. domain 2. language 3. any other parameters

    Route::get('/{language}/{any}', function ($language, $any) {
        // Handle the request in this function.
        // The $language variable contains the language value,
        // and the $any variable contains any part of the URL.
    })->where('any', '.*');
    

    Your task now is to handle the allowed languages.

    Route::get('/{language}/{any}', function ($language, $any) {
        $allowedLanguages = ['de', 'en', 'fr'];
    
        if (!in_array(Str::lower($language), $allowedLanguages)) {
            abort(404);
        }
    
        // If the language is valid, we can continue with the processing.
    })->where('any', '.*');
    

    More information here: Laravel Documentation - Route Parameters Encoded Forward Slashes