開始 Bailador
Bailador 是對(duì) Perl Dancer Web 開發(fā)框架的模仿。
安裝方法:
panda install Bailador
# or
zef install Bailador
我們來創(chuàng)建一個(gè)腳本 first.pl,打印 "hello world":
use v6;
use Bailador;
get '/' => sub {
"hello world"
}
baile;
運(yùn)行:perl6 first.pl 它會(huì)啟動(dòng)一個(gè)小型的 Web 服務(wù)器,你可以在3000端口上訪問它:
$ perl6 first.pl
Entering the development dance floor: http://0.0.0.0:3000
[2016-05-05T12:57:31Z] Started HTTP server.
在 Bailador 中,我們需要把 HTTP 請(qǐng)求方法和服務(wù)器上的路徑映射給一個(gè)匿名子例程, 這個(gè)子例程會(huì)返回它里面的內(nèi)容。在這個(gè)例子中,我們把我們告訴它的網(wǎng)站根路徑的 get HTTP 請(qǐng)求映射為返回字符串 hello world。如果你啟動(dòng)這個(gè)程序并用瀏覽器打開 http://0.0.0.0:3000/ 你就會(huì)看到這個(gè)文本。
我們還可以映射其它路徑(path-es):
get '/about' => sub {
"關(guān)于我"
}
這會(huì)把 http://0.0.0.0:3000/about url 映射為返回 「關(guān)于我」。
路徑中的占位符
路徑中的一部分可以是以冒號(hào)開頭的占位符:
get '/hello/:name' => sub ($name) {
"Hello $name!"
};
:name 部分能匹配除了斜線 / 之外的任何字符串,并且它所匹配到的值會(huì)被賦值給匿名子例程中的 $name 變量。
這樣的占位符你可以擁有多個(gè),并且占位符的實(shí)際名字是什么無關(guān)緊要。占位符所捕獲到的值會(huì)按照它們出現(xiàn)在 url 中的順序賦值給函數(shù)的參數(shù)。
get '/hello/:first/:family' => sub ($fname, $lname) {
"Hello $fname! And hi $lname"
};
在這個(gè)例子中,無論 :first 占位符捕獲到的是什么,它都會(huì)被賦值給 $fname 參數(shù),無論 :family 捕獲到的是什么,它都會(huì)被賦值給 :$lname。例如 url http://0.0.0.0:3000/hello/Foo/Bar 會(huì)生成如下響應(yīng):
Hello Foo! And hi Bar!
當(dāng)然,讓占位符的名字和參數(shù)的名字相同可能會(huì)讓代碼更易讀。這是第二個(gè)腳本的完整版本:
use v6;
use Bailador;
get '/' => sub {
"hello world"
}
get '/hello/:first/:family' => sub ($fname, $lname) {
"Hello $fname! And hi $lname"
};
baile;
使用 Bailador 回顯文本
我們來看看怎么從用戶那兒接收輸入并把輸入回顯給用戶。
使用 POST 回顯
對(duì)于這,我們必須創(chuàng)建兩個(gè)路由(routes)因?yàn)楝F(xiàn)在 Bailador 還不能處理 GET 參數(shù)。
# echo_post.p6
use v6;
use Bailador;
get '/' => sub {
'<form method="POST" action="/echo"><input name="text"><input type="submit"></form>';
}
post '/echo' => sub {
my $text = request.params<text> // '';
my $html = 'You said (in a POST request) ';
$html ~= $text;
return $html;
}
baile;

我們能看到怎么創(chuàng)建一個(gè)路由來處理 POST 請(qǐng)求。
第一個(gè)路由 get '/' => { 會(huì)發(fā)送一個(gè) GET 請(qǐng)求并且它會(huì)返回一個(gè)包含在這個(gè)腳本中的 HTML 片段。(我知道,我們很快就會(huì)使用模板了) 那個(gè) HTML 片段包含了一個(gè)帶有單個(gè)文本框的表單和一個(gè)提交按鈕。這個(gè)表單有一個(gè)通向 /echo URL 的 action,并且表單擁有 method="POST"。這意味著,當(dāng)用戶點(diǎn)擊提交按鈕時(shí),瀏覽器會(huì)發(fā)送回 POST 請(qǐng)求。
第二個(gè)路由 post '/echo' => sub { 會(huì)處理 /echo 路徑的 POST 請(qǐng)求。
Bailador 提供的 request 函數(shù)以 Bailador::Request的形式返回代表當(dāng)前請(qǐng)求的對(duì)象。
request 函數(shù)有幾個(gè)方法,其中一個(gè)是 params 方法,它返回一個(gè)散列,其中散列的鍵是參數(shù)的名字(在我們這個(gè)例子中是 text),值是提交的值。
我們把那個(gè)值保存在 $text 變量中,并且我們使用 '//' defined-or 操作符來設(shè)置變量的值為空,在用戶沒有提供任何值的情況下。然后我們連接用戶提供的值組成 "html" 字符串。最后發(fā)送回那個(gè)字符串,我們這個(gè)小小的回顯服務(wù)器就能工作啦。

使用 GET 回顯
use v6;
use Bailador;
get '/' => sub {
'<form method="GET" action="/echo"><input name="text"><input type="submit"></form>';
}
get '/echo' => sub {
return 'You said (in a GET request) ' ~ (request.params<text> // '');
}
baile;

在這個(gè)例子中,我省略了臨時(shí)變量 $text 和 $html,在之前的例子中它們也不是必要的。當(dāng)我們使用 GET 方法請(qǐng)求后,提交后回在瀏覽器的 URL 地址欄中拼接上我們的 text 字段和字段的值。
Bailador Application in a module
模板
在下面這個(gè)模板中,它把數(shù)據(jù)接收到變量 $h 中,之后使用這個(gè)變量來展示版本號(hào)和當(dāng)前時(shí)間 - 從紀(jì)元開始的秒數(shù)。
bailador/code_in_module/views/index.tt
% my ($h) = @_;
<!DOCTYPE html>
<html>
<head>
<title>Bailador App</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
</head>
<body>
<h1>Bailador App</h1>
<div>
Version <%= $h<version> %> Current time: <%= $h<date> %>
</div>
</body>
</html>
模塊
這個(gè)文件把所有代碼包含在類中:
unit class Demo;
為了擁有特定領(lǐng)域語(yǔ)言(DSL),它加載了 Bailador 以讓我們定義路由更容易。
use Bailador;
最重要的是它包含了路由。
unit class Demo;
use Bailador;
my $version = '0.01';
get '/' => sub {
template 'index.tt', { version => $version, date => time }
}
啟動(dòng)應(yīng)用程序的腳本
use Bailador;
Bailador::import();
use lib callframe(0).file.IO.dirname ~ '/lib';
use Demo;
baile;
最有意思的應(yīng)該是這段代碼:
use lib callframe(0).file.IO.dirname ~ '/lib';
它計(jì)算這個(gè)工程的根目錄 - 假設(shè) app.pl 文件在根目錄中 - 然后把 /lib 子目錄添加到 perl 將要查找額外模塊的地方。這會(huì)在 lib 子目錄下加載 Demo.pm 文件。
