簡介
# Controller
package MyApp::Controller::Foo;
use Mojo::Base 'Mojolicious::Controller';
# Action
sub bar {
my $self = shift;
my $name = $self->param('name');
$self->res->headers->cache_control('max-age=1, no-cache');
$self->render(json => {hello => $name});
}
Mojolicious::Controller是Mojolicious應(yīng)用程序中控制器的基類。如果你沒有在Mojolicious中設(shè)置“controller_class”裆蒸,Mojolicious::Controller將被作為默認(rèn)的控制器類递胧。
屬性
Mojolicious::Controller從Mojo::Base繼承所有屬性嘁酿,并實(shí)現(xiàn)以下屬性戏仓。
app
my $app = $c->app;
$c = $c->app(Mojolicious->new);
反向引用分配給該控制器的應(yīng)用程序,通常是Mojolicious對象籽腕。
# Use application logger
$c->app->log->debug('Hello Mojo');
# Generate path
my $path = $c->app->home->child('templates', 'foo', 'bar.html.ep');
match
my $m = $c->match;
$c = $c->match(Mojolicious::Routes::Match->new);
當(dāng)前請求的路由結(jié)果爱葵,默認(rèn)為Mojo::Routes::Match對象施戴。
# Introspect
my $name = $c->match->endpoint->name;
my $foo = $c->match->endpoint->pattern->defaults->{foo};
my $action = $c->match->stack->[-1]{action};
tx
my $tx = $c->tx;
$c = $c->tx(Mojo::Transaction::HTTP->new);
正在處理的事務(wù),通常是Mojo::Transaction::HTTP或Mojo::Transaction::WebSocket對象萌丈。
注:此引用通常會用被消弱赞哗,因此,當(dāng)你執(zhí)行非阻塞操作并且底層連接可能會提前關(guān)閉時辆雾,該對象需要在別處引用肪笋。
# Check peer information
my $address = $c->tx->remote_address;
my $port = $c->tx->remote_port;
# Increase size limit for WebSocket messages to 16MiB
$c->tx->max_websocket_size(16777216) if $c->tx->is_websocket;
# Perform non-blocking operation without knowing the connection status
my $tx = $c->tx;
Mojo::IOLoop->timer(2 => sub {
$c->app->log->debug($tx->is_finished ? 'Finished' : 'In progress');
});
方法
Mojolicious::Controller繼承Mojo::Base中的所有方法,并實(shí)現(xiàn)以下方法度迂。
continue
$c->continue;
使用Mojolicious::Routes中的continue方法從 已經(jīng)包裝的“調(diào)度器”鏈中繼續(xù)調(diào)度藤乙。
cookie
my $value = $c->cookie('foo');
$c = $c->cookie(foo => 'bar');
$c = $c->cookie(foo => 'bar', {path => '/'});
獲取一個“請求”中的cookie,或設(shè)置一個“響應(yīng)”中的cookie英岭。如果有多個cookie值共享同一個名稱,使用這個方法只能獲取到最后一個湿右,如果你想獲取到所有的值可以使用every_cookie方法诅妹。
# Create response cookie with domain and expiration date
$c->cookie(user => 'sri', {domain => 'example.com', expires => time + 60});
# Create secure response cookie
$c->cookie(secret => 'I <3 Mojolicious', {secure => 1, httponly => 1});
every_cookie
my $values = $c->every_cookie('foo');
和cookie方法的功能類似,但返回的是一個包含所有相同名稱所有cookie值的數(shù)組引用毅人。
$ Get first cookie value
my $first = $c->every_cookie('foo')->[0];
every_param
my $values = $c->every_param('foo');
和param方法的功能類似吭狡,但返回的是一個包含所有相同名稱所有param值的數(shù)組引用。
# Get first value
my $first = $c->every_param('foo')->[0];
every_signed_cookie
my $values = $c->every_signed_cookie('foo');
和signed_cookie方法的功能類似丈莺,但返回的是一個包含相同名稱所有已簽名cookie值的數(shù)組引用划煮。
# Get first signed cookie value
my $first = $c->every_signed_cookie('foo')->[0];
finish
$c = $c->finish;
$c = $c->finish(1000);
$c = $c->finish(1003 => 'Cannot accept data!');
$c = $c->finish('Bye!');
關(guān)閉WebSocket連接或長時間輪詢流,此方法將自動響應(yīng)具有101響應(yīng)狀態(tài)的WebSocket握手請求缔俄,以建立WebSocket連接弛秋。
flash
my $foo = $c->flash('foo');
$c = $c->flash({foo => 'bar'});
$c = $c->flash(foo => 'bar');
只能在下一次請求中可用的持久存儲器躏,會被存儲在session中。
# Show message after redirect
$c->flash(message => 'User created successfully!');
$c->redirect_to('show_user', id => 23);
helpers
my $helpers = $c->helpers;
返回包含當(dāng)前控制器對的代理對象蟹略,可以使用他調(diào)用由app提供的helpers登失。這包括Mojolicious::Plugin::DefaultHelpers和Mojolicious::Plugin::TagHelpers中的所有helpers。
# 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;
on
my $cb = $c->on(finish => sub {...});
訂閱tx的事件挖炬,通常是Mojo::Transaction::HTTP或Mojo::Transaction::WebSocket對象揽浙。此方法將自動響應(yīng)具有101響應(yīng)狀態(tài)的WebSocket握手請求,以建立WebSocket連接意敛。
# Do something after the transaction has been finished
$c->on(finish => sub {
my $c = shift;
$c->app->log->debug('All data has been sent');
});
# Receive WebSocket message
$c->on(message => sub {
my ($c, $msg) = @_;
$c->app->log->debug("Message: $msg");
});
# Receive JSON object via WebSocket message
$c->on(json => sub {
my ($c, $hash) = @_;
$c->app->log->debug("Test: $hash->{test}");
});
# Receive WebSocket "Binary" message
$c->on(binary => sub {
my ($c, $bytes) = @_;
my $len = length $bytes;
$c->app->log->debug("Received $len bytes");
});
param
my $value = $c->param('foo');
$c = $c->param(foo => 'ba;r');
$c = $c->param(foo => 'ba;r', 'baz');
$c = $c->param(foo => ['ba;r', 'baz']);
順序訪問路徑占位符沒有被隱藏的值馅巷,文件上傳,GET和POST請求中使用application/x-www-form-urlencoded 或 multipart/form-data 格式編碼的消息體草姻。如果有多個值共享相同的名稱钓猬,使用此方法只能得到眾值中的最后一個值。如果你想訪問所有的值碴倾,則需要使用every_param方法逗噩。
注:“請求體”每個Parts 都需要加載到內(nèi)存中被解析,所以需要確保它不會太大跌榔。默認(rèn)情況下限制為16MiB异雁。
# Get first value
my $first = $c->every_param('foo')->[0];
為了更精確和方便的訪問,您可以使用以下類似方式直接訪問請求信息僧须。
# Only GET parameters
my $foo = $c->req->query_params->param('foo');
# Only POST parameters
my $foo = $c->req->body_params->param('foo');
# Only GET and POST parameters
my $foo = $c->req->param('foo');
# Only file uploads
my $foo = $c->req->upload('foo');
redirect_to
$c = $c->redirect_to('named', foo => 'bar');
$c = $c->redirect_to('named', {foo => 'bar'});
$c = $c->redirect_to('/index.html');
$c = $c->redirect_to('http://example.com/index.html');
準(zhǔn)備一個302(如果當(dāng)前狀態(tài)嗎不是3xx)狀態(tài)碼纲刀,使用Location頭的重定向響應(yīng),參數(shù)要求與url_for方法相同担平。
# Moved Permanently
$c->res->code(301);
$c->redirect_to('some_route');
# Temporary Redirect
$c->res->code(307);
$c->redirect_to('some_route');
render
my $bool = $c->render;
my $bool = $c->render(foo => 'bar', baz => 23);
my $bool = $c->render(template => 'foo/index');
my $bool = $c->render(template => 'index', format => 'html');
my $bool = $c->render(data => $bytes);
my $bool = $c->render(text => 'Hello!');
my $bool = $c->render(json => {foo => 'bar'});
my $bool = $c->render(handler => 'something');
my $bool = $c->render('foo/index');
使用Mojolicious中的renderer渲染內(nèi)容示绊,并在Mojolicious中先后觸發(fā)before_render和after_render事件。接收的參數(shù)必須為鍵值對暂论,它們會被合并到stash中面褐。如果無法產(chǎn)生一個響應(yīng),則會調(diào)用Mojolicious::Plugin::DefaultHelpers中的reply->not_found 方法取胎。
# Render characters
$c->render(text => 'I ? Mojolicious!');
# Render characters (alternative)
$c->stash(text => 'I ? Mojolicious!')->render;
# Render binary data
use Mojo::JSON 'encode_json';
$c->render(data => encode_json({test => 'I ? Mojolicious!'}));
# Render JSON
$c->render(json => {test => 'I ? Mojolicious!'});
# Render inline template
$c->render(inline => '<%= 1 + 1 %>');
# Render template "foo/bar.html.ep"
$c->render(template => 'foo/bar', format => 'html', handler => 'ep');
# Render template "test.*.*" with arbitrary values "foo" and "bar"
$c->render(template => 'test', foo => 'test', bar => 23);
# Render template "test.xml.*"
$c->render(template => 'test', format => 'xml');
# Render template "test.xml.*" (alternative)
$c->render('test', format => 'xml');
render_later
$c = $c->render_later;
禁用自動渲染以延遲響應(yīng)生成展哭,只有在自動渲染會導(dǎo)致發(fā)送“響應(yīng)”時才需要。
# Delayed rendering
$c->render_later;
Mojo::IOLoop->timer(2 => sub {
$c->render(text => 'Delayed by 2 seconds!');
});
render_maybe
my $bool = $c->render_maybe;
my $bool = $c->render_maybe(foo => 'bar', baz => 23);
my $bool = $c->render_maybe('foo/index', format => 'html');
嘗試呈現(xiàn)內(nèi)容闻蛀,如果無法產(chǎn)生一個響應(yīng)匪傍,也不會調(diào)用Mojolicious::Plugin::DefaultHelpers中的reply->not_found 方法。并且使用與render完全相同的參數(shù)觉痛。
# Render template "index_local" only if it exists
$c->render_maybe('index_local') or $c->render('index');
render_to_string
my $output = $c->render_to_string('foo/index', format => 'pdf');
嘗試渲染內(nèi)容并將生成的內(nèi)容包裝成Mojo::BtyeStream對象返回役衡,如果渲染失敗,則返回undef薪棒。所有參數(shù)都將自動從本地獲取手蝎,并且僅在此渲染操作期間可用榕莺。使用與“render”相同的參數(shù)。
# Render inline template
my $two = $c->render_to_string(inline => '<%= 1 + 1 %>');
rendered
$c = $c->rendered;
$c = $c->rendered(302);
在Mojolicious中完成響應(yīng)柑船,并觸發(fā)after_dispatch的hook帽撑。默認(rèn)使用200響應(yīng)代碼。
# Custom response
$c->res->headers->content_type('text/plain');
$c->res->body('Hello World!');
$c->rendered(200);
req
my $req = $c->req;
從tx中獲取Mojo::Message::Request對象鞍时。
# Longer version
my $req = $c->tx->req;
# Extract request information
my $method = $c->req->method;
my $url = $c->req->url->to_abs;
my $info = $c->req->url->to_abs->userinfo;
my $host = $c->req->url->to_abs->host;
my $agent = $c->req->headers->user_agent;
my $custom = $c->req->headers->header('Custom-Header');
my $bytes = $c->req->body;
my $str = $c->req->text;
my $hash = $c->req->params->to_hash;
my $all = $c->req->uploads;
my $value = $c->req->json;
my $foo = $c->req->json('/23/foo');
my $dom = $c->req->dom;
my $bar = $c->req->dom('div.bar')->first->text;
res
my $res = $c->res;
從tx中獲取Mojo::Message::Response對象亏拉。
# Longer version
my $res = $c->tx->res;
# Force file download by setting a response header
$c->res->headers->content_disposition('attachment; filename=foo.png;');
# Use a custom response header
$c->res->headers->header('Custom-Header' => 'whatever');
# Make sure response is cached correctly
$c->res->headers->cache_control('public, max-age=300');
$c->res->headers->append(Vary => 'Accept-Encoding');
respond_to
$c = $c->respond_to(
json => {json => {message => 'Welcome!'}},
html => {template => 'welcome'},
any => sub {...}
);
從Accept頭、format存儲或 GET/POST中的format參數(shù)中自動的選擇最佳的內(nèi)容響應(yīng)格式逆巍。默認(rèn)為Mojolicious::Renderer中的default_format或呈現(xiàn)空的204響應(yīng)及塘。
每種“內(nèi)容類型”都可以使用一個回調(diào)函數(shù)或包含要傳遞給render方法的參數(shù)的哈希引用來處理。由于瀏覽器不會真正知道他們實(shí)際想要的是什么锐极,所以在允許多種MIME類型的非特定的請求頭Accept會被忽略笙僚,除非你使用X-Requested-With請求頭在XMLHttpRequest類型的請求中進(jìn)行了說明。
# Everything else than "json" and "xml" gets a 204 response
$c->respond_to(
json => sub { $c->render(json => {just => 'works'}) },
xml => {text => '<just>works</just>'},
any => {data => '', status => 204}
);
對于更高級的內(nèi)容協(xié)商邏輯灵再,你可以使用Mojolicious::Plubin::DefaultHelpers中的accept方法來實(shí)現(xiàn)肋层。
send
$c = $c->send({binary => $bytes});
$c = $c->send({text => $bytes});
$c = $c->send({json => {test => [1, 2, 3]}});
$c = $c->send([$fin, $rsv1, $rsv2, $rsv3, $op, $payload]);
$c = $c->send($chars);
$c = $c->send($chars => sub {...});
通過WebSocket非阻塞的發(fā)送消息或WebSocket幀。如果傳遞了一個回調(diào)函數(shù)翎迁,則在所有數(shù)據(jù)定入后會被執(zhí)行栋猖。此方法將自動響應(yīng)具有101響應(yīng)狀態(tài)的WebSocket握手請求,以建立WebSocket連接汪榔。
# Send "Text" message
$c->send('I ? Mojolicious!');
# Send JSON object as "Text" message
$c->send({json => {test => 'I ? Mojolicious!'}});
# Send JSON object as "Binary" message
use Mojo::JSON 'encode_json';
$c->send({binary => encode_json({test => 'I ? Mojolicious!'})});
# Send "Ping" frame
use Mojo::WebSocket 'WS_PING';
$c->send([1, 0, 0, 0, WS_PING, 'Hello World!']);
# Make sure the first message has been written before continuing
$c->send('First message!' => sub {
my $c = shift;
$c->send('Second message!');
});
對于大多數(shù)空閑的WebSocket蒲拉,您可能還需要在Mojolicious::Plubin::DefaultHelpers中設(shè)置inactiveivity_timeout(鏈接的在不活動時的等待時間),通常默認(rèn)為15秒痴腌。
# Increase inactivity timeout for connection to 300 seconds
$c->inactivity_timeout(300);
session
my $session = $c->session;
my $foo = $c->session('foo');
$c = $c->session({foo => 'bar'});
$c = $c->session(foo => 'bar');
獲取或替換session中的數(shù)據(jù)雌团。所有會話數(shù)據(jù)通過Mojo::JSON進(jìn)行序列化,然后后進(jìn)行Base64編碼士聪,再執(zhí)行HMAC-SHA1進(jìn)行簽名锦援,最后把簽名結(jié)果放到cookie中,以防止篡改剥悟。cookie通常有一個4096字節(jié)(4KiB)的限制灵寺,具體取決于瀏覽器。
# Manipulate session
$c->session->{foo} = 'bar';
my $foo = $c->session->{foo};
delete $c->session->{foo};
# Expiration date in seconds from now (persists between requests)
$c->session(expiration => 604800);
# Expiration date as absolute epoch time (only valid for one request)
$c->session(expires => time + 604800);
# Delete whole session by setting an expiration date in the past
$c->session(expires => 1);
signed_cookie
my $value = $c->signed_cookie('foo');
$c = $c->signed_cookie(foo => 'bar');
$c = $c->signed_cookie(foo => 'bar', {path => '/'});
從“請求”中獲取已經(jīng)簽名的cookie懦胞,或向“響應(yīng)”中設(shè)置簽名的cookie替久。如果有多個值共享一個名稱凉泄,你將從這個方法中得到眾值中的最后一個躏尉。你可以使用every_signed_cookie獲取所有值。
Cookies使用HMAC-SHA1加密簽名后众,以防止篡改胀糜,并且將會自動丟棄簽名驗(yàn)證失敗的cookie颅拦。
stash
my $hash = $c->stash;
my $foo = $c->stash('foo');
$c = $c->stash({foo => 'bar', baz => 23});
$c = $c->stash(foo => 'bar', baz => 23);
獲取或設(shè)置為當(dāng)前請求存儲的非持久的數(shù)據(jù),只能在當(dāng)前請求中使用。可以使用Mojolicious中的defaults方法設(shè)置默認(rèn)值萌腿。有些值具有特殊含義在此列出:action路媚,app,cb廉丽,controller,data,extends讥电,format,handler轧抗,inline恩敌,json,layout横媚,namespace纠炮,path,status灯蝴,template恢口,text和variant。
注:具有mojo.*前綴的所有存儲空間都保留供Mojolicious框架內(nèi)部使用绽乔。
# Remove value
my $foo = delete $c->stash->{foo};
# Assign multiple values at once
$c->stash(foo => 'test', bar => 23);
url_for
my $url = $c->url_for;
my $url = $c->url_for(name => 'sebastian');
my $url = $c->url_for({name => 'sebastian'});
my $url = $c->url_for('test', name => 'sebastian');
my $url = $c->url_for('test', {name => 'sebastian'});
my $url = $c->url_for('/index.html');
my $url = $c->url_for('//example.com/index.html');
my $url = $c->url_for('http://example.com/index.html');
my $url = $c->url_for('mailto:sri@example.com');
my $url = $c->url_for('#whatever');
使用當(dāng)前應(yīng)用程序的信息(如:base弧蝇、path、URL折砸、route)生成一個便攜的Mojo::URL對象看疗。
# "http://127.0.0.1:3000/index.html" if application was started with Morbo
$c->url_for('/index.html')->to_abs;
# "https://127.0.0.1:443/index.html" if application was started with Morbo
$c->url_for('/index.html')->to_abs->scheme('https')->port(443);
# "/index.html?foo=bar" if application is deployed under "/"
$c->url_for('/index.html')->query(foo => 'bar');
# "/myapp/index.html?foo=bar" if application is deployed under "/myapp"
$c->url_for('/index.html')->query(foo => 'bar');
你還可以使用Mojolicious::Plugin::DefaultHelpers中的url_with從當(dāng)前請求繼承查詢參數(shù)。
# "/list?q=mojo&page=2" if current request was for "/list?q=mojo&page=1"
$c->url_with->query([page => 2]);
validation
my $validation = $c->validation;
獲取 Mojolicious::Validator::Validation對象睦授,用于驗(yàn)證當(dāng)前請求中的一些信息两芳。如:文件上傳,GET或POST中的參數(shù)等去枷。
注:“請求體”每個Parts 都需要加載到內(nèi)存中被解析怖辆,所以需要確保它不會太大。默認(rèn)情況下限制為16MiB删顶。
# Validate GET/POST parameter
my $validation = $c->validation;
$validation->required('title', 'trim')->size(3, 50);
my $title = $validation->param('title');
# Validate file upload
my $validation = $c->validation;
$validation->required('tarball')->upload->size(1, 1048576);
my $tarball = $validation->param('tarball');
write
$c = $c->write;
$c = $c->write('');
$c = $c->write($bytes);
$c = $c->write($bytes => sub {...});
非阻塞地向響應(yīng)中寫入動態(tài)內(nèi)容竖螃,如果參數(shù)中有回調(diào)函數(shù),將在內(nèi)容寫完后執(zhí)行逗余。如果在調(diào)用此方法時沒有傳入一個數(shù)據(jù)庫特咆,則會處理并完成響應(yīng)頭,且允許稍候再寫入動態(tài)內(nèi)容录粱。
# Keep connection alive (with Content-Length header)
$c->res->headers->content_length(6);
$c->write('Hel' => sub {
my $c = shift;
$c->write('lo!');
});
# Close connection when finished (without Content-Length header)
$c->write('Hel' => sub {
my $c = shift;
$c->write('lo!' => sub {
my $c = shift;
$c->finish;
});
});
你可以隨時調(diào)用finish方法或?qū)懭肟盏臄?shù)據(jù)空來結(jié)束響應(yīng)流腻格。
HTTP/1.1 200 OK
Date: Sat, 13 Sep 2014 16:48:29 GMT
Content-Length: 6
Server: Mojolicious (Perl)
Hello!
HTTP/1.1 200 OK
Connection: close
Date: Sat, 13 Sep 2014 16:48:29 GMT
Server: Mojolicious (Perl)
Hello!
對于長輪詢画拾,你還需要通過Mojolicious::Plugin::DefaultHelpers中的inactivity_timeout來增加連接在非活動狀態(tài)的保持時間,默認(rèn)值為15秒菜职。
# Increase inactivity timeout for connection to 300 seconds
$c->inactivity_timeout(300);
write_chunk
$c = $c->write_chunk;
$c = $c->write_chunk('');
$c = $c->write_chunk($bytes);
$c = $c->write_chunk($bytes => sub {...});
使用分場傳輸?shù)木幋a方式非阻塞的向響應(yīng)中寫入動態(tài)內(nèi)容青抛。如果參數(shù)中有回調(diào)函數(shù),將在內(nèi)容寫完后執(zhí)行酬核。如果在調(diào)用此方法時沒有傳入一個數(shù)據(jù)庫蜜另,則會處理并完成響應(yīng)頭,且允許稍候再寫入動態(tài)內(nèi)容嫡意。
# Make sure previous chunk has been written before continuing
$c->write_chunk('H' => sub {
my $c = shift;
$c->write_chunk('ell' => sub {
my $c = shift;
$c->finish('o!');
});
});
你可以隨時調(diào)用finish方法或?qū)懭肟盏臄?shù)據(jù)空來結(jié)束響應(yīng)流蚕钦。
HTTP/1.1 200 OK
Date: Sat, 13 Sep 2014 16:48:29 GMT
Transfer-Encoding: chunked
Server: Mojolicious (Perl)
1
H
3
ell
2
o!
0
AUTOLOAD
除了上述的屬性和方法外,你還可以在Mojolicious::Controller對象上調(diào)用由app提供的helpers鹅很。這包括Mojolicious::Plugin::DefaultHelpers和Mojolicious::Plugin::TagHelpers中的所有helpers嘶居。
# Call helpers
$c->layout('green');
$c->title('Welcome!');
# Longer version
$c->helpers->layout('green');