Route to static file in Mojo
Asked Answered
C

3

6

I have small app based on mojolicious. And I have index.html in public dir. I want to have route to this file when user asks for '/'.

I wrote two solution, but I don't like them.

First solution - add simple controller.

sub stratup {
  //...
  $r->get('/')->to('general#index_html');
  //...
}

package MyPackage::General;

use Mojo::Base 'Mojolicious::Controller';

use strict;
use warnings;

sub index_html {
    my $self = shift;
    $self->render_static('index.html');
    return;
}

1;

Second solution - add hook

sub startup {
    my $self = shift;

    $self->hook(before_dispatch => sub {
            my $self = shift;
            if ($self->req->url eq '/') {
                $self->req->url( Mojo::URL->new('/index.html') );
            }
        });

What I want:

$r->get('/')->to('/index.html');

or something like that.

P.S. I know, than usualy nginx/apache do it, but I use morbo to run code.

Chaumont answered 5/3, 2015 at 14:49 Comment(0)
S
1

You want:

$r->get('...')->to(cb => sub {  
     my $c = shift;                                   
     $c->reply->static('index.html')                
}); 

(As long as you're after Mojolicous 5.45 2014-09-26)

Segno answered 28/2, 2016 at 16:40 Comment(0)
T
0

By far the simplest way is

get "/" => "index";

Trammel answered 5/3, 2015 at 15:23 Comment(6)
it is looks like Mojo::Lite. I rewrite it like $r->get('/')->to('index'); but it does not work.Chaumont
Have you tried the second approach? The first only works if index.html is in your templates directory.Trammel
Second solution is "too big". It shold work, but my solution with hook is smaller.Chaumont
There's also a very serious security vulnerability in the second approach, because you are not protecting against path traversal. A filename like (for example) ../../../../../../../../../../etc/passwd would serve up something you don't want to serve up, not through any defect in Mojolicious, but because the OS would do what you asked.Arlie
@Michael-sqlbot Thanks for pointing that out! I have removed the offending code so no one else uses it without knowing the consequences.Trammel
$r->get('/' => { template => 'index' });Histology
C
0

I'll dig this up from the graveyard, why not.

I found myself similarly trying to serve a static html file in a docker container that I had using to serve both a Mojolicious REST API and a Vue.js front end. After searching around and piecing sporadic information together, this is what seems to work for me.

** disclaimer: I have not fully tested this with Vue routing and other aspects as yet.

My directory structure:

/app
/app/script
/app/modules/ui
/app/modules/ui/dist

From the command line the app directory, using morbo to test:
morbo script/ui.pl

ui.pl script

#!/usr/bin/env perl
use Mojolicious::Lite -signatures;
use Mojo::File qw(curfile);
use v5.25;

my $app = app;
my $static = $app->static;

push @{$static->paths}, curfile->dirname->sibling('modules/ui/dist')->to_string;


any '/' => sub {
    my $c = shift;
    my $content = $static->file("/index.html")->slurp;
    $c->render(text => $content);
};

$app->start;

Using a combo of information from https://metacpan.org/pod/Mojolicious::Static and basic routing information at https://docs.mojolicious.org/Mojolicious/Lite, I could get the vue.js index page to render as expected.

** UPDATED A DAY LATER **

As it turns out, there is an easier way, though not clearly documented. If you place the static files inside your public folder, you can use the default helpers included with Mojolicious to render the files. The documentation refers to it here, https://docs.mojolicious.org/Mojolicious/Guides/Rendering#Serving-static-files, but it's not very clear on how to make it happen.

I tooled around some, but it took browsing the code of Controller.pm of for Mojolicious to sort it out. This section of the POD led me to determine how to get the reply object:

=head2 helpers

my $helpers = $c->helpers;

Return a proxy object containing the current controller object and on which helpers provided by /app can be called. This includes all helpers from Mojolicious::Plugin::DefaultHelpers and Mojolicious::Plugin::TagHelpers.

# Make sure to use the "title" helper and not the controller method
$c->helpers->title('Welcome!');

# Use a nested helper instead of the "reply" controller method
$c->helpers->reply->not_found;

Based on this, I can drop my files into the public folder:
/app/public/index.html

Then modify my controller to match:

# https://docs.mojolicious.org/Mojolicious/Guides/Rendering#Serving-static-files
any '/' => sub {
    my $c = shift;
    $c->helpers->reply->static('index.html');
};
Chianti answered 29/11, 2021 at 19:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.