perlmojoliciousmojolicious-lite

Mojolicious base URL when running Mojolicious Lite app on Apache under subdirectory


I'm trying to run a tiny Mojolicious Lite app on Apache (shared hosting) in a subdirectory: http://www.example.com/mymojoapp/. And I mostly tried to follow this guide.

The mymojoapp is an actual directory on the server, and app structure as follows:

mymojoapp
|- .htaccess
|- app.pl
|- public
|  +- images
|  |  +- ... (image files) ...
|  +- css
|  |  +- ... (css files) ...
|  +- js
|     +- ... (js files) ...
+- templates
   |- layouts
   |  |- index-layout.html.ep
   |  +- other-page-layout.html.ep
   |- index.html.ep
   +- other-page.html.ep

.htaccess contents:

AddHandler cgi-script .pl
Options +ExecCGI

IndexIgnore *

RewriteEngine on

RewriteCond %{DOCUMENT_ROOT}/public/%{REQUEST_URI} -f
RewriteRule ^(.*)$ public/$1 [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.*)$ app.pl/$1 [L]

app.pl contents (perlml is perl + paths to user-installed modules, including Mojolicious):

#!/usr/bin/perlml

use Mojolicious::Lite;

hook before_dispatch => sub {
    my $c = shift;
    $c->req->url->base(Mojo::URL->new(q{http://www.example.com/mymojoapp/}));
};

get '/' => 'index';

get '/u/:username' => sub {
    my $self = shift;
    $self->stash(profile => $self->stash('username'));
} => 'user-profile-page';

app->secrets(['app','secrets']);
app->start;

In both index-layout.html.ep and other-page-layout.html.ep I refer to css (and images) as <link rel="stylesheet" href="<%= url_for %>/css/styles.css">. When I access base URL (http://www.example.com/mymojoapp/) the page is displayed with proper styling, because the url_for gives me /mymojoapp/ making path to the stylesheet = /mymojoapp/css/normalize.css. But when I access http://www.example.com/mymojoapp/u/someuser, the CSS path is /mymojoapp/u/someuser/css/normalize.css and styles are not applied.

I feel I'm missing some re-write rules, or it's probably can be fixed in before_dispatch hook, but so far I couldn't figure it out.

How can I make sure all pages generated in my app get the correct base URL?


Solution

  • Received the answer over at #mojo in IRC from @jabberwok:

    Instead of <%= url_for %>/css/styles.css I needed to use <%= url_for('/css/styles.css') %>.