Mojolicious::Controller

作者: JSON_NULL | 来源:发表于2017-10-14 13:49 被阅读20次

    简介

    # 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应用程序中控制器的基类。如果你没有在Mojolicious中设置“controller_class”,Mojolicious::Controller将被作为默认的控制器类。

    属性

    Mojolicious::Controller从Mojo::Base继承所有属性,并实现以下属性。

    app

    my $app = $c->app;
    $c      = $c->app(Mojolicious->new);
    

    反向引用分配给该控制器的应用程序,通常是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);
    

    当前请求的路由结果,默认为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);
    

    正在处理的事务,通常是Mojo::Transaction::HTTP或Mojo::Transaction::WebSocket对象。

    注:此引用通常会用被消弱,因此,当你执行非阻塞操作并且底层连接可能会提前关闭时,该对象需要在别处引用。

    # 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中的所有方法,并实现以下方法。

    continue

    $c->continue;
    

    使用Mojolicious::Routes中的continue方法从 已经包装的“调度器”链中继续调度。

    cookie

    my $value = $c->cookie('foo');
    $c        = $c->cookie(foo => 'bar');
    $c        = $c->cookie(foo => 'bar', {path => '/'});
    

    获取一个“请求”中的cookie,或设置一个“响应”中的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值的数组引用。

    $ Get first cookie value
    my $first = $c->every_cookie('foo')->[0];
    

    every_param

    my $values = $c->every_param('foo');
    

    和param方法的功能类似,但返回的是一个包含所有相同名称所有param值的数组引用。

    # Get first value
    my $first = $c->every_param('foo')->[0];
    

    every_signed_cookie

    my $values = $c->every_signed_cookie('foo');
    

    和signed_cookie方法的功能类似,但返回的是一个包含相同名称所有已签名cookie值的数组引用。

    # 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!');
    

    关闭WebSocket连接或长时间轮询流,此方法将自动响应具有101响应状态的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;
    

    返回包含当前控制器对的代理对象,可以使用他调用由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对象。此方法将自动响应具有101响应状态的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 都需要加载到内存中被解析,所以需要确保它不会太大。默认情况下限制为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');
    

    准备一个302(如果当前状态吗不是3xx)状态码,使用Location头的重定向响应,参数要求与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渲染内容,并在Mojolicious中先后触发before_render和after_render事件。接收的参数必须为键值对,它们会被合并到stash中。如果无法产生一个响应,则会调用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;
    

    禁用自动渲染以延迟响应生成,只有在自动渲染会导致发送“响应”时才需要。

    # 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');
    

    尝试呈现内容,如果无法产生一个响应,也不会调用Mojolicious::Plugin::DefaultHelpers中的reply->not_found 方法。并且使用与render完全相同的参数。

    # 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');
    

    尝试渲染内容并将生成的内容包装成Mojo::BtyeStream对象返回,如果渲染失败,则返回undef。所有参数都将自动从本地获取,并且仅在此渲染操作期间可用。使用与“render”相同的参数。

    # Render inline template
    my $two = $c->render_to_string(inline => '<%= 1 + 1 %>');
    

    rendered

    $c = $c->rendered;
    $c = $c->rendered(302);
    

    在Mojolicious中完成响应,并触发after_dispatch的hook。默认使用200响应代码。

    # 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参数中自动的选择最佳的内容响应格式。默认为Mojolicious::Renderer中的default_format或呈现空的204响应。

    每种“内容类型”都可以使用一个回调函数或包含要传递给render方法的参数的哈希引用来处理。由于浏览器不会真正知道他们实际想要的是什么,所以在允许多种MIME类型的非特定的请求头Accept会被忽略,除非你使用X-Requested-With请求头在XMLHttpRequest类型的请求中进行了说明。

    # 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}
    );
    

    对于更高级的内容协商逻辑,你可以使用Mojolicious::Plubin::DefaultHelpers中的accept方法来实现。

    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非阻塞的发送消息或WebSocket帧。如果传递了一个回调函数,则在所有数据定入后会被执行。此方法将自动响应具有101响应状态的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!');
    });
    

    对于大多数空闲的WebSocket,您可能还需要在Mojolicious::Plubin::DefaultHelpers中设置inactiveivity_timeout(链接的在不活动时的等待时间),通常默认为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中的数据。所有会话数据通过Mojo::JSON进行序列化,然后后进行Base64编码,再执行HMAC-SHA1进行签名,最后把签名结果放到cookie中,以防止篡改。cookie通常有一个4096字节(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 => '/'});
    

    从“请求”中获取已经签名的cookie,或向“响应”中设置签名的cookie。如果有多个值共享一个名称,你将从这个方法中得到众值中的最后一个。你可以使用every_signed_cookie获取所有值。

    Cookies使用HMAC-SHA1加密签名,以防止篡改,并且将会自动丢弃签名验证失败的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);
    

    获取或设置为当前请求存储的非持久的数据,只能在当前请求中使用。可以使用Mojolicious中的defaults方法设置默认值。有些值具有特殊含义在此列出:action,app,cb,controller,data,extends,format,handler,inline,json,layout,namespace,path,status,template,text和variant。

    注:具有mojo.*前缀的所有存储空间都保留供Mojolicious框架内部使用。

    # 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');
    

    使用当前应用程序的信息(如: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从当前请求继承查询参数。

    # "/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对象,用于验证当前请求中的一些信息。如:文件上传,GET或POST中的参数等。

    注:“请求体”每个Parts 都需要加载到内存中被解析,所以需要确保它不会太大。默认情况下限制为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 {...});
    

    非阻塞地向响应中写入动态内容,如果参数中有回调函数,将在内容写完后执行。如果在调用此方法时没有传入一个数据库,则会处理并完成响应头,且允许稍候再写入动态内容。

    # 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;
      });
    });
    

    你可以随时调用finish方法或写入空的数据空来结束响应流。

    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来增加连接在非活动状态的保持时间,默认值为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 {...});
    

    使用分场传输的编码方式非阻塞的向响应中写入动态内容。如果参数中有回调函数,将在内容写完后执行。如果在调用此方法时没有传入一个数据库,则会处理并完成响应头,且允许稍候再写入动态内容。

    # 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!');
      });
    });
    

    你可以随时调用finish方法或写入空的数据空来结束响应流。

    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对象上调用由app提供的helpers。这包括Mojolicious::Plugin::DefaultHelpers和Mojolicious::Plugin::TagHelpers中的所有helpers。

    # Call helpers
    $c->layout('green');
    $c->title('Welcome!');
    
    # Longer version
    $c->helpers->layout('green');

    相关文章

      网友评论

        本文标题:Mojolicious::Controller

        本文链接:https://www.haomeiwen.com/subject/snzzyxtx.html