I would like to have the following strucutre in my project:
folder
\_script_1.pl
mojolicious_ui_script.pl
HTML
\_website.html.ep
CSS
\_website.css.ep
But I'm just able to get it to work using this default strucutre:
folder
\_script_1.pl
mojolicious_ui_script.pl
templates
\_website.html.ep
website.css.ep
This is a simplified version of the mojolicious_ui_script.pl I´m using:
use utf8;
use open ':std', ':encoding(UTF-8)';
use Mojolicious::Lite;
get "/" => 'website';
get "/website\.css" => { template => 'website', format => 'css'} => 'website-css';
# app->secret('random string to turn off warnings about no secret');
# app->mode('production'); # stop debug output
app->start('daemon', '-l', 'http://*:3000');
I'm stucked finding a way to solve this, as the documentation between the lite version and normal Mojo is sometimes mixed and I don´t if something can be used on both sides, but anyway trying a lot of things with routes I have not been able to chagne this.
Related
I want to change the default logging level for the Mojolicious web server but I just cannot figure out how to do it after reading the docs. I am a fairly new Perl developer as I had to use Perl for a specific legacy use case - I typically use Go, Python, Java in day-to-day work. I figure there is some "Perl way" of doing this that I just cannot figure out due to my lack of experience.
Here's a trivial sample app:
#!/usr/bin/env perl
use strict;
use warnings;
use utf8;
use Mojolicious::Lite -signatures;
get '/ping' => sub ($c) {
$c->render( json => { 'pong' => $c->param('value'), 'number' => 1 } );
};
app->start( 'daemon', '-l', 'http://localhost:8888' );
I run that in a terminal and then, from another terminal I hit the endpoint and get a response:
curl "http://localhost:8888/ping?value=test"
{"number":1,"pong":"test"}
However, in the web server terminal, I get this trace level logging which I understand is the default logging level for Mojolicious:
[2022-01-21 14:38:04.40413] [1628] [info] Listening at "http://localhost:8888"
Web application available at http://localhost:8888
[2022-01-21 14:38:39.06480] [1628] [trace] [sLAkASlGAvjE] GET "/ping"
[2022-01-21 14:38:39.06516] [1628] [trace] [sLAkASlGAvjE] Routing to a callback
[2022-01-21 14:38:39.06552] [1628] [trace] [sLAkASlGAvjE] 200 OK (0.000718s, 1392.758/s)
I want to back off the logging level to 'info'.
You can set the log level like this:
app->log->level('error');
This example is from the main Mojolicious::Lite documentation in the app section. This was the only hit for grepping log in that document.
In your example, you could do that either at the start, or the end of the application.
# ...
use Mojolicious::Lite -signatures;
app->log->level('info');
get '/ping' => sub ($c) {
$c->render( json => { 'pong' => $c->param('value'), 'number' => 1 } );
};
app->start( 'daemon', '-l', 'http://localhost:8888' );
I have the following Mojolicious app which serving files from specific folder
use Mojolicious::Lite;
use Mojo::Log;
my $app = app;
my $static = $app->static;
push #{$static->paths} => 'c:\test';
$app->start
when I run:
perl mojo_server.pl daemon -m development
I get this:
[2021-05-18 19:46:39.22370] [29388] [info] Listening at "http://*:3000"
Server available at http://127.0.0.1:3000
and when I access a file from the web browser I am able to access the file, but there are no information on the STDERR after "Server available at http://127.0.0.1:3000"
like what is the source address and the page requested and the user agent. How can I turn mojolicious to show those info on debug mode, if this possible?
You can use after_static from HOOKS in Mojolicious:
use Mojolicious::Lite -signatures;
use Mojo::Log;
my $log = Mojo::Log->new;
hook after_static => sub ($c){
$log->debug('original_remote_address : ' => $c->tx->original_remote_address);
$log->debug('user_agent : ' => $c->tx->req->content->headers->user_agent );
$log->debug('url : ' => $c->tx->req->url->to_abs);
};
app->start;
The after_static event is triggered when a static response has been generated.
Update: If you need a more general solution which is not specifically targeted at serving static files, take a look at the AccessLog plugin.
use Mojolicious::Lite -signatures;
use Mojo::Log;
use Mojolicious::Plugin::AccessLog;
my $log = Mojo::Log->new;
plugin 'AccessLog';
app->start;
I'm trying to publish a module, and am running into a lot of weird errors, the latest of which is as follows:
C:\Shared\John\Perl\unifdef+.0.5.1>build disttest
Creating Makefile.PL
Invalid version format (non-numeric data) at C:/perl/lib/Module/Build/Compat.pm
line 134.
The code at the specified line is:
if ( my $minimum_perl = $requires->{perl} ) {
my $min_ver = version->new($minimum_perl)->numify;
print {$fh} "require $min_ver;\n";
}
so it looks like $minimum_perl is corrupted. I do have the line:
require 5.10.0;
In the code, but that should be OK according to the documentation I've read.
I tried upgrading various modules, and finally I tried a cpan upgrade, and upgraded my entire cpan, but I'm still getting the error. Can anyone tell me what I'm doing wrong? I am running perl 5.24.1
Ok, figured it out (sort of). I'm posting an answer, as I assume others will run into the same problem, and hopefully this will help them. My Build.PL script was a cut/paste/modify from an example on the web. I had the following:
use 5.010000; # NOT 5.8.8 - needed by CPAN testers
use Module::Build;
my $builder = Module::Build->new( module_name => 'code::unifdef+'
, license => 'perl'
, requires => { perl => '>= 5.10.0' } #hmm, this doesn't work...
, dist_version => '0.005.001'
, dist_author => 'John Ulvr <perldev#ulvr.com>'
, dist_abstract => 'processes conditional parts of makefiles, c/c++ and kconfig files'
, create_readme => 0
, create_makefile_pl => 'traditional'
);
$builder->create_build_script; #generate Build
The requires line was causing the problem. I'm not sure why though, as I've seen other similar examples on the web of the requires clause, so either everyone is wrong, or there's some sort of bug in in Compat.pm. Removing the requires line fixes the problem (I have requires in the .pl file itself, so it should catch out-of-date issues).
ActiveState Perl 5.12 on WinXP
I've recently become a convert to Log4perl and used it successfully where I defined a specific logger for each module that makes up my application. Example:
Upload.pm-----
my $logger = get_logger("Upload"); # specific logger
my $layout = Log::Log4perl::Layout::PatternLayout->new( "%d %p> %F{1}:%L %M - %m%n");
my $appender = Log::Log4perl::Appender->new( "Log::Dispatch::File",
filename => "Upload.log",
mode => "append"
);
$appender->layout($layout);
$logger->level($OFF); # or $INFO
$logger->add_appender($appender)
....
This works but is hard to track program flow across numerous log files ie Upload.log , Parse.log , FileRead.log etc. Quick-n-dirty solution: use same filename in all loggers.
This works much better, but only as long as the program is used serially and in sequence.
Now for the wrinkle - suppose module Upload.pm is used by several progams ie readMyFiles.pl, readHerFiles.pl and dumpAllFiles.pl . When running readMyFiles.pl I want the logger in Upload.pm to write to readMyFiles.pl.log and when runnng dumpAllFiles.pl want the logger in Upload.pm to write to dumpAllFiles.pl.log
One method might be to declare an our variable $logFileName in my .pl files and use it in all my modules like so:
filename => $logFileName,
Another might be to remove all the loggers from my .pm's and define them only in the .pl's - but then how would I reference $logger in the .pm's ?
All thoughts and suggestions are appreciated.
Still-learning Steve
Configure your logging settings in the caller, not in the module. If somebody else uses your module, they might not want to log things to the same place that you do. They might also want to format log messages differently, or use a different type of appender, or...the list goes on.
Your module should only get a logger and write messages to it:
MyModule.pm
#!/usr/bin/perl
package MyModule;
use strict;
use Log::Log4perl qw(get_logger);
sub foo {
my $logger = get_logger("Foo");
$logger->debug("Hello from MyModule");
}
1;
Your main program(s) should configure and initialize logging:
logtest
#!/usr/bin/perl
use strict;
use warnings;
use Log::Log4perl qw(get_logger);
use MyModule;
Log::Log4perl->init("log4perl.cfg");
my $logger = get_logger("Foo");
$logger->debug("Hello from main");
MyModule::foo();
I prefer to use a separate config file for Log4perl settings:
log4perl.cfg
log4perl.logger.Foo=DEBUG, Screen
log4perl.appender.Screen=Log::Dispatch::Screen
log4perl.appender.Screen.Threshold=DEBUG
log4perl.appender.Screen.layout=Log::Log4perl::Layout::PatternLayout
log4perl.appender.Screen.layout.ConversionPattern=[%r] %F %L %c - %m%n
Output:
[0] logtest 12 Foo - Hello from main
[0] MyModule.pm 11 Foo - Hello from MyModule
Note that you must initialize logging with Log::Log4perl->init in the caller before trying to get_logger in the module. If you don't, log messages from the module will be ignored and you'll get the following warning:
Log4perl: Seems like no initialization happened.
Forgot to call init()?
See the documentation for details.
I am using perl Rover module version 3 to login to the Linux/Unix server and run the script. In the ruleset if I add the full path name it copies the script to the remote server, not able to substitute the environment variable.
eg.
This works:
copy:{
put_file "/home/u1/find.sh" "/tmp/"
};
This didn't work:
copy:{
put_file "$HOME/find.sh" "/tmp/"
};
used $ENV{'HOME'}, this also didn't work.
How can I pass the environment variable?
Rover module document.
http://rover.sourceforge.net/QuickStart/Rover-QuickStart-3.html#ss3.2
http://rover.sourceforge.net/
After reviewing the source code for rover, which I never used, I determined it was not possible from the existing code.
I created a new extension for you, that has that functionality, it supports the ~ and ${HOME} syntax, (which are bash extensions and not part of the OS directly, that is why perl does not support them).
code is here:
https://github.com/h4ck3rm1k3/perl-rover/commit/2c78aefb97e819956bb665b04056763f8df1b242
I have had a hard time testing it because I never used rover before, and rover does not seem to support scp.(I read it is supported,but could not test it yet.) Anyway, let me know if you like it. I will put more work into it if reasonably requested.
Update
Here is my example ruleset :
example ruleset
[rulesets]
test:
{
put_file_from_home put_file "~/find2.sh" "/tmp/"
put_file_from_home put_file "${HOME}/find3.sh" "/tmp/"
}, ;
example output
Here is the example output, I cannot get rover to work. See the test case below.
Test output
perl -I lib t/example2.t
Local was ~/find2.sh and home was /home/mdupont at lib/Rover/CoreExtension.pm line 19.
Local now /home/mdupont/find2.sh at lib/Rover/CoreExtension.pm line 22.
Local was ${HOME}/find3.sh and home was /home/mdupont at lib/Rover/CoreExtension.pm line 19.
Local now /home/mdupont/find3.sh at lib//Rover/CoreExtension.pm line 22.
new config option for the new sshport option
[hosts]
someexample:{
os linux
username myusername
description 'myhost'
sshport 12345
ftp_method_used sftp
};
update2
Dont use quotes around the name, use a comma between the args,
To git#github.com:h4ck3rm1k3/perl-rover.git
2207417..7637741 CoreExtension -> CoreExtension
[rulesets]
test: { put_file_from_home ~/find2.sh,/tmp/ }, ;
[hosts]
localhost:{
os linux
username mdupont
description 'localhost'
ftp_methods sftp
ftp_method_used sftp };
mike
Old question but new answer, since your using Rover v3 you can just extend the Rover::Core modules by overloading it.
Add this to your ~/.rover/contrib directory:
CoreVariables.pm:
package CoreVariables;
use strict;
use Exporter;
our #ISA = qw( Exporter );
our #EXPORT = qw( put_file );
sub put_file {
my ($self, $host, $command) = #_;
$command =~ s/(\$[\w{}]+)/$1/eeg;
return Rover::Core::put_file($self, $host, $command);
}
And add the following to your ~/.rover/config [modules] section (must be after Rover::Core):
CoreVariables:{
};
And then you can store environment variables in your rover config when using put_file. Add other routines if you wish, this only extends put_file.
And since this is such an easy task I will add it to the requested feature list and include it in the next release (I am the Rover author).
The better place to ask Rover questions is on the sourceforge website of course: http://sourceforge.net/projects/rover/