📜 ⬆️ ⬇️

Web Framework in Japanese - Amon2



Intro

In an interview with Japanese Tokuhiro Matsuno, the following phrase was heard:
“Some applications of our company are used by over a million people . It all works on Amon2 . ”


I did not find any information about this web framework in Russian. And I decided to try what it is for Amon2, purely for myself, and maybe someone will be interested.
')


Installation


Lets get a handle with Debian GNU / Linux 7.3 (wheezy)
Go…

# curl -L http://cpanmin.us | perl - Amon2 ................ Building and testing Amon2-6.00 ... OK Successfully installed Amon2-6.00 78 distributions installed Successfully installed Amon2-6.00 

Everything! Installation completed.

Out of the box we got:


Creation of the frame



 adduser dotcloud su - dotcloud amon2-setup.pl BBS 


Everything is going well, until ...
- Running flavor: Basic - [main] Loading asset: jQuery
[main] Loading asset: Bootstrap
[main] Loading asset: ES5Shim
[main] Loading asset: MicroTemplateJS
[main] Loading asset: StrftimeJS
[main] Loading asset: SprintfJS
[main] Loading asset: MicroLocationJS
[main] Loading asset: MicroDispatcherJS
[main] Loading asset: XSRFTokenJS
[Flavor :: Basic] writing tmpl / index.tx
[Flavor :: Basic] writing tmpl / include / layout.tx
[Flavor :: Basic] writing tmpl / include / pager.tx
[Flavor :: Basic] writing lib / BBS.pm
[Flavor :: Basic] writing lib / BBS / Web.pm
[Flavor :: Basic] writing lib / BBS / Web / Plugin / Session.pm
[Flavor :: Basic] writing lib / BBS / Web / Dispatcher.pm
[Flavor :: Basic] writing lib / BBS / Web / View.pm
[Flavor :: Basic] writing lib / BBS / Web / ViewFunctions.pm
[Flavor :: Basic] writing lib / BBS / DB.pm
[Flavor :: Basic] writing lib / BBS / DB / Schema.pm
[Flavor :: Basic] writing lib / BBS / DB / Row.pm
[Flavor :: Basic] writing script / bbs-server
[Flavor :: Basic] writing Build.PL
[Flavor :: Basic] writing minil.toml
[Flavor :: Basic] writing builder / MyBuilder.pm
[Flavor :: Basic] writing cpanfile
[Flavor :: Basic] writing static // js / jquery-2.0.3.min.js
[Flavor :: Basic] writing static // bootstrap / fonts / glyphicons-halflings-regular.eot
[Flavor :: Basic] writing static // bootstrap / css / bootstrap-theme.min.css
[Flavor :: Basic] writing static // bootstrap / fonts / glyphicons-halflings-regular.woff
[Flavor :: Basic] writing static // bootstrap / fonts / glyphicons-halflings-regular.ttf
[Flavor :: Basic] writing static // bootstrap / css / bootstrap.min.css
[Flavor :: Basic] writing static // bootstrap / js / bootstrap.min.js
[Flavor :: Basic] writing static // bootstrap / fonts / glyphicons-halflings-regular.svg
[Flavor :: Basic] writing static // bootstrap / js / bootstrap.js
[Flavor :: Basic] writing static // bootstrap / css / bootstrap.css
[Flavor :: Basic] writing static // bootstrap / css / bootstrap-theme.css
[Flavor :: Basic] writing static // js / es5-shim.min.js
[Flavor :: Basic] writing static // js / micro_template.js
[Flavor :: Basic] writing static // js / strftime.js
[Flavor :: Basic] writing static // js / sprintf-0.7-beta1.js
[Flavor :: Basic] writing static // js / micro-location.js
[Flavor :: Basic] writing static // js / micro_dispatcher.js
[Flavor :: Basic] writing static // js / xsrf-token.js
[Flavor :: Basic] writing static / img / .gitignore
[Flavor :: Basic] writing static / robots.txt
[Flavor :: Basic] writing static / js / main.js
[Flavor :: Basic] writing static / css / main.css
[Flavor :: Basic] writing db / .gitignore
[Flavor :: Basic] writing config / development.pl
[Flavor :: Basic] writing config / production.pl
[Flavor :: Basic] writing config / test.pl
[Flavor :: Basic] writing sql / mysql.sql
[Flavor :: Basic] writing sql / sqlite.sql
[Flavor :: Basic] writing t / Util.pm
[Flavor :: Basic] writing t / 00_compile.t
[Flavor :: Basic] writing t / 01_root.t
[Flavor :: Basic] writing t / 02_mech.t
[Flavor :: Basic] writing t / 03_assets.t
[Flavor :: Basic] writing t / 06_jshint.t
[Flavor :: Basic] writing xt / 01_pod.t
[Flavor :: Basic] writing xt / 02_perlcritic.t
[Flavor :: Basic] writing .gitignore
[Flavor :: Basic] writing .proverc
[Flavor :: Basic] writing static / 500.html
[Flavor :: Basic] writing static / 504.html
[Flavor :: Basic] writing static / 503.html
[Flavor :: Basic] writing static / 502.html
[Flavor :: Basic] writing static / 404.html
There is no git command.
-


 Setup script was done! You are ready to run the skelton. You need to install the dependencies by: > carton install And then, run your application server: > carton exec perl -Ilib script/bbs-server -------------------------------------------------------------- 


It seems everything is ok, but there is not enough carton and it is recommended to enter some more commands.
We put it
 cpan Carton #   carton install #     BBS!   ! 

We get the following file and directory structure:

 builder Build.PL config cpanfile cpanfile.snapshot db lib local minil.toml script sql static t tmpl xt 


Creating a web application



 cd db vim sqlite.sql 


File sqlite.sql with the following content:

 CREATE TABLE IF NOT EXISTS member ( id INTEGER NOT NULL PRIMARY KEY, name VARCHAR(255) ); CREATE TABLE IF NOT EXISTS sessions ( id CHAR(72) PRIMARY KEY, session_data TEXT ); CREATE TABLE IF NOT EXISTS entry ( entry_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, body varchar(255) not null ); 


Create a database:

 sqlite3 development.db < sqlite.sql 


Further

 cd config/ vim development.pl 


We stick this config into it:

 use File::Spec; use File::Basename qw(dirname); my $basedir = File::Spec->rel2abs(File::Spec->catdir(dirname(__FILE__), '..')); my $dbpath = File::Spec->catfile($basedir, 'db', 'development.db'); +{ 'DBI' => [ "dbi:SQLite:dbname=$dbpath", '', '', +{ sqlite_unicode => 1, } ], }; 


Trying to test run the web server.

  perl -Ilib script/bbs-server Can't locate Teng/Schema/Declare.pm in @INC (you may need to install the Teng::Schema::Declare module) (@INC contains: script/../lib lib /etc/perl /usr/local/lib/perl/5.18.1 /usr/local/share/perl/5.18.1 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.18 /usr/share/perl/5.18 /usr/local/lib/site_perl .) at script/../lib/BBS/DB/Schema.pm line 6. BEGIN failed--compilation aborted at script/../lib/BBS/DB/Schema.pm line 6. Compilation failed in require at script/../lib/BBS.pm line 7. BEGIN failed--compilation aborted at script/../lib/BBS.pm line 7. Compilation failed in require at /usr/share/perl/5.18/parent.pm line 20. BEGIN failed--compilation aborted at script/../lib/BBS/Web.pm line 5. Compilation failed in require at script/bbs-server line 9. BEGIN failed--compilation aborted at script/bbs-server line 9. 


And breaks off.
Good set
 cpan Teng::Schema::Declare cpan Module::Functions cpan Plack::Middleware::ReverseProxy cpan Plack::Handler::Starlet 


Finally saw the cherished:

 dotcloud@debian:~/BBS$ perl -Ilib script/bbs-server BBS: http://127.0.0.1:5000/ 


If you go to this address, you can see the following unearthly beauty:



Now it remains to make BBS - a bulletin board ( grandma bibisihu - do you know this? )

 vim lib/BBS/DB/Schema.pm 

And post there the following:

 package BBS::DB::Schema; use strict; use warnings; use utf8; use Teng::Schema::Declare; base_row_class 'BBS::DB::Row'; table { name 'sessions'; pk 'id'; columns qw(session_data); }; table { name 'entry'; pk 'entry_id'; columns qw(entry_id body); }; 1; 


Further:

 vim lib/BBS/Web/Dispatcher.pm 


 package BBS::Web::Dispatcher; use strict; use warnings; use Amon2::Web::Dispatcher::Lite; any '/' => sub { my ($c) = @_; my @entries = $c->db->search( entry => { }, { order_by => 'entry_id DESC', limit => 10, } ); return $c->render( "index.tx" => { entries => \@entries, } ); }; post '/post' => sub { my ($c) = @_; if (my $body = $c->req->param('body')) { $c->db->insert( entry => +{ body => $body, } ); } return $c->redirect('/'); }; 1; 


And rule template

 vim tmpl/index.tx 


 : cascade "include/layout.tx" : override content -> { <form method="post" action="<: uri_for('/post') :>"> <input type="text" name="body" /> <input type="submit" value="Send" /> </form> <ul> <: for $entries -> $entry { :> <li><: $entry.entry_id :>. <: $entry.body :></li> <: } :> </ul> : } 


Run:

 perl -Ilib script/bbs-server 


And if necessary, we reinstall the following packages.

 cpan Router::Simple cpan Router::Simple::Sinatraish cpan DBD::SQLite 


HOORAY!
Grandma Bibisikha - works!



It remains to put all this on nginx

Install nginx as a frontend



First, we do the init file, and not to run from root


 vim /etc/init.d/plackup 


 #!/bin/sh PORT=5000 WORKERS=4 AMON_DIR="/home/dotcloud/BBS" AMON_APP="$AMON_DIR/script/bbs-server" AMON_USER="dotcloud" AMON_MODE="development" website="cc_Website" plackup="/usr/local/bin/plackup " PID=$AMON_DIR/logs/plackup.$website.pid plackup_args="-E $AMON_MODE -p $PORT -s Starman --pid=$PID --workers $WORKERS -D" U=`id -un` if [ $U = root ]; then WRPERM=`find $AMON_DIR/ ! -user $AMON_USER | wc -l` if [ "$WRPERM" != 0 ]; then echo Fixing file ownership on $AMON_DIR chown -R $AMON_USER.nginx $AMON_DIR fi cd / su $AMON_USER -s /bin/sh $0 "$@" exit elif [ $U != $AMON_USER ]; then echo "Should be run under $AMON_USER or root" exit 1 fi lockfile=$AMON_DIR/logs/plackup.$website start() { [ -x $plackup ] || exit 5 [ -f $AMON_APP ] || exit 6 echo -n $"Starting $website: " $plackup $plackup_args -a $AMON_APP 2>&1 > /dev/null retval=$? if [ $retval -eq 0 ]; then echo OK touch $lockfile else failure $"Unable to start" fi echo return $retval } stop() { echo -n $"Stopping $website: OK" if [ -f $PID ]; then kill `cat $PID` > /dev/null retval=$? [ $retval -eq 0 ] && rm -f $lockfile echo return $retval fi failure $"pid $PID not found" echo return 1 } restart() { stop start } case "$1" in start) $1 ;; stop) $1 ;; restart) $1 ;; *) echo $"Usage: $0 {start|stop|restart}" exit 2 esac 


Add config to nginx

 vim /etc/nginx/conf.d/virtual.conf 


 upstream amon { server 127.0.0.1:5000; } server { listen *:80; location / { try_files /empty @backend; } location @backend { proxy_set_header Host $http_host; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://amon; } } 


All is ready!

Conclusion



As a conclusion, I will cite, again, a quote from the very interview that started it all:
Tell me about Amon2. How is it different from other Perl frameworks for the web?
Amon2 is a very simple, reliable, general-purpose web framework.

Differences from Mojolicious

Mojolicious is not bad, and I like the approach itself. Unfortunately, there is no backward compatibility. In Amon2, on the contrary. It seems to me that you can break backward compatibility only with the change of name. When I decide to seriously change something, I will release Amon3.

Differences from Catalyst

Catalyst is dependent on Moose, but Amon2 is not. This is because I want my applications to load quickly.

Differences from Dancer

Virtually no differences between Amon2 and Dancer, including Dancer2.



Author of a modest man, of course.

And now my IMHO:
  1. The framework is really very lightweight.
  2. Written by Japanese, with their thoroughness and perfectionism. This is felt in the code.
  3. Miyagawa, who wrote plackup, has two replica boots on it.
    After all, it is used and recommended just such a bunch plackup + Amon2
  4. I hope that the framework, which is used by “more than a million people” according to the author’s statement, will not be abandoned just like that, but will develop further.
  5. The framework is relatively new and modern, but there is already a huge number of modules on cpan
  6. Overall left a good impression.

Source: https://habr.com/ru/post/122611/


All Articles