DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Cover image for Laravel On Shared Hosting
Lee Mason
Lee Mason

Posted on • Originally published at leemason.co.uk

Laravel On Shared Hosting

Before we start its worth caveating this post with the message: It’s always more desirable and recommended to serve Laravel apps from bespoke hosting environment.

There are plenty to choose, from first party tools like Forge and Vapour to more general providers like Digital Ocean, AWS and GCP.

However as i find myself in a similar situation there may be times you have to deploy on a CPanel environment.

I am going to cover the usual quite simple redirect you see across the web, but more importantly a second step thats usually left out. This second step can have a massive impact on your SEO.

The Redirect

As you may of found elsewhere theres a simple redirect you can put in the root folder of your project:

# Internally rewrite all top-level requests to the public directory
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteRule ^(.*)$ public/$1 [L]
</IfModule>
Enter fullscreen mode Exit fullscreen mode

It’s very simple and just redirects everything from the root of your site public_html down into the public folder of your Laravel project.

From there the .htaccess provided with Laravel will take over and route incoming requests.

Job done? Maybe not…

The SEO Problem

The problem with the above redirect is that it doesn’t prevent access to ALL of your urls with a /public/ prefix. So both / and /public/ will server your applications homepage!

This is obviously bad for any SEO efforts your planning to make to the site as you now have duplicate pages and on top of that if someone stumbles upon those urls its not great for users.

I spent sometime trying out redirects to prevent this from the .htaccess file itself but came up blank. In my particular case this is a CPanel server with Litespeed installed. And i know from experience its not quite 100% like for like with Apache.

The Solution

With the .htaccess approach coming up blank i went with a Middleware solution. Again this isn’t ideal as its not really the applications responsibility but we are not in an ideal situation anyway.

It’s a pretty simple middleware, it looks for the public prefix and returns a 301 redirect if found. This does mean you cannot have urls that start with public but in our case this wasn’t a problem:

<?php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class RedirectPublicFolderRequests
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle(Request $request, Closure $next)
    {
        if (strpos($request->getRequestUri(), '/public') === 0) {
            return redirect()
                ->to($request->getSchemeAndHttpHost() . '/' . substr($request->getRequestUri(), 8))
                ->setStatusCode(301);
        }
        return $next($request);
    }
}
Enter fullscreen mode Exit fullscreen mode

Once again this isn’t ideal but works for our purposes.

Add this to your global middleware stack before anything else.

Note how we use the $request->getRequestUri() method and not simply $request->path(). As the path will be effected by the servers rewrites.

Now any requests for public will redirect with a 301 and you wont be serving duplicate pages.

Top comments (1)

Collapse
shahzebbbbb profile image
Shahzeb Ahmed

Hi Lee Mason,

Usually, I never comment on blogs but your article is so convincing that I couldn't stop myself to say something about it. You’re doing a great job Man, Keep it up the good work.

I have one question, Have you ever written any blog related to Laravel application on DO using Cloudways - Managed Hosting.

🌚 Browsing with dark mode makes you a better developer.

It's a scientific fact.