1

Redirection from HTTP to HTTPS happens correctly when the URL is any of the following:

  • http://example.com >> https://example.com [OK]
  • http://www.example.com >> https://example.com [OK]
  • http://www.example.com/login >> https://example.com/login [OK]

However, redirection to HTTPS fails when the URL is like this:

  • http://example.com/login >> error (see screenshot)

Screenshot of the error

Please advise on how to resolve.

Code and configuration below. Thank you, in advance...

Other Details:

  • Ubuntu 16.04
  • Apache 2.4
  • mod_rewrite is enabled
  • Laravel 5.3
  • cleared browser cache

.htaccess file

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews
    </IfModule>

    RewriteEngine On

    # Allow Blog in Sub-Directory
    RewriteCond $1 !^(blog)

    #Redirect to non-WWW
    RewriteCond %{HTTP_HOST} ^www.example.com$
    RewriteRule ^(.*) https://example.com/$1  [QSA,L,R=301]

    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)/$ /$1 [L,R=301]

    # Handle Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]

    # Handle Authorization Header
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]


</IfModule>

Virtual Host Configuration

(example.com.conf)

<VirtualHost *:80>
        ServerName example.com
        ServerAlias example.com
        ServerAdmin support@example.com
        DocumentRoot /var/www/example.com_dev/public
        <Directory "/var/www/example.com_dev/public">
                DirectoryIndex index.php
                AllowOverride All
                Order allow,deny
                Allow from all
        </Directory>
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

<VirtualHost *:80>
        ServerName example.com
        ServerAlias www.example.com
        ServerAdmin support@example.com
        DocumentRoot /var/www/example.com_dev/public
        <Directory "/var/www/example.com_dev/public">
                DirectoryIndex index.php
                AllowOverride All
                Order allow,deny
                Allow from all
        </Directory>
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

Virtual Host Configuration

(example-ssl.com.conf)

<IfModule mod_ssl.c>
    <VirtualHost _default_:443>
    ServerAdmin support@example.com
        ServerName example.com
        ServerAlias example.com
        DocumentRoot /var/www/example.com_dev/public
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
        SSLEngine on
        SSLCertificateFile /etc/apache2/ssl/example_com.crt
        SSLCertificateKeyFile /etc/apache2/ssl/example_com.key
        SSLCertificateChainFile /etc/apache2/ssl/example_com.ca-bundle
        <FilesMatch "\.(cgi|shtml|phtml|php)$">
            SSLOptions +StdEnvVars
        </FilesMatch>
        <Directory /usr/lib/cgi-bin>
            SSLOptions +StdEnvVars
        </Directory>
        <Directory "/var/www/example.com_dev/public">
            DirectoryIndex index.php
            AllowOverride All
            Order allow,deny
            Allow from all
        </Directory>
        BrowserMatch "MSIE [2-6]" \
            nokeepalive ssl-unclean-shutdown \
            downgrade-1.0 force-response-1.0
        BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
    </VirtualHost>
</IfModule>

<IfModule mod_ssl.c>
    <VirtualHost _default_:443>
    ServerAdmin support@example.com
        ServerName example.com
        ServerAlias www.example.com
        DocumentRoot /var/www/example.com_dev/public
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
        SSLEngine on
        SSLCertificateFile /etc/apache2/ssl/example_com.crt
        SSLCertificateKeyFile /etc/apache2/ssl/example_com.key
        SSLCertificateChainFile /etc/apache2/ssl/example_com.ca-bundle
        <FilesMatch "\.(cgi|shtml|phtml|php)$">
            SSLOptions +StdEnvVars
        </FilesMatch>
        <Directory /usr/lib/cgi-bin>
            SSLOptions +StdEnvVars
        </Directory>
        <Directory "/var/www/example.com_dev/public">
            DirectoryIndex index.php
            AllowOverride All
            Order allow,deny
            Allow from all
        </Directory>
        BrowserMatch "MSIE [2-6]" \
            nokeepalive ssl-unclean-shutdown \
            downgrade-1.0 force-response-1.0
        BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
    </VirtualHost>
</IfModule>

// App-Level Redirect

(app/Http/middleware/HttpsProtocol.php - Laravel 5.3)

<?php

namespace App\Http\Middleware;

use Closure;

class HttpsProtocol
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if(!$request->secure()){
            return redirect()->secure($request->getRequestUri());
        }

        return $next($request);
    }
}

App-Level HTTP Kernel

(app/Http/Kernel.php - Laravel 5.3)

<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    /**
     * The application's global HTTP middleware stack.
     *
     * These middleware are run during every request to your application.
     *
     * @var array
     */
    protected $middleware = [
        \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
    ];

    /**
     * The application's route middleware groups.
     *
     * @var array
     */
    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
            \App\Http\Middleware\HttpsProtocol::class,
        ],

        'api' => [
            'throttle:60,1',
            'bindings',
        ],
    ];

    /**
     * The application's route middleware.
     *
     * These middleware may be assigned to groups or used individually.
     *
     * @var array
     */
    protected $routeMiddleware = [
        'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
    ];
}
2

Solved. The issue turned out to be that the 000-default.conf virtual host was still active (enabled) and intercepting the requests like http://example.com/*. Once that was disabled using:

a2dissite 000-default.conf 

everything began working as expected.

0
  • http://example.com >> https://example.com [OK]
  • http://example.com/login >> error (see screenshot)

From your code dump I can't actually see where either of these situations are handled (although you say the first works OK)?

Since you appear to be doing the www redirect in .htaccess:

#Redirect to non-WWW
RewriteCond %{HTTP_HOST} ^www.example.com$
RewriteRule ^(.*) https://example.com/$1  [QSA,L,R=301]

Then you can try changing this to:

RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\.example\.com
RewriteRule (.*) https://example.com/$1  [R=301,L]

This incorporates the check for HTTP. So, if HTTP or www then redirect to HTTPS without www.

You will need to clear all caches before testing, as an erroneous 301s will have been cached hard by the browser.


You appear to have duplicated both virtual hosts for port 80 and 443? This could be contributing to your problem. You only need one VirtualHost for port 80 and one for port 443:

ServerName example.com
ServerAlias example.com

Should be:

ServerName example.com
ServerAlias www.example.com

Like you have for the duplicate. (Then delete the duplicate.)

  • Thank you for the tip about my duplicate virtual hosts. Fixed that, and also updated the htaccess file. But the problem persists... I'm stumped. You said you cannot see where the situations are handled. What info specifically other should I post that would give you and others greater context on the issue? – eric Apr 4 '17 at 10:21
  • You would usually expect this type of redirect in either VirtualHost (preferable) (or server config) or .htaccess. So, there's no other info really, except for the "unexpected" - which you seem to have found in the form of another virtual host! :) – MrWhite Apr 4 '17 at 19:34

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.