$app->secret()
by $app->secrets()
) has touched me. But the fact remains - backward compatibility is broken, often broken, and without really good reasons: for example, in the case of secret()
nothing prevented adding to the code sub secret { shift->secrets([shift]) }
or simply add support for additional parameters to the secret()
instead of adding the new function secrets()
implementing the necessary feature without breaking the compatibility at all.$self
often used, which does not add readability — there are too many classes in the framework, and not always looking at $self
it is easy to figure out which class this object is in this example. Therefore, I will use instead of $self
in the examples: $app # YourApp → Mojolicious $r # Mojolicious::Routes ($app->routes) $c # YourApp::SomeController → Mojolicious::Controller $ua # Mojo::UserAgent
$r->get("/a/b/c/d") ->to(text=>"1"); $ab = $r->route("/a")->route("/b"); $ab->get("/c") ->to(text=>"2-1"); $ab->get("/c/d") ->to(text=>"2-2"); $r->get("/a/b/c/d/e") ->to(text=>"3");
$ r {} ├─ / a / b / c / d {text => "1"} ├─ / a─── / b─┬─ / c {text => "2-1"} │ └─ / c / d {text => "2-2"} └─ / a / b / c / d / e {text => "3"}
GET / a / b => 404 Not Found GET / a / b / c => "2-1" GET / a / b / c / d => "1" GET / a / b / c / d / e => "3" GET / a / b / c / d / e / f => 404 Not Found
route()
, normal get()
, etc.) and whether the request handler is set for them ( "controller#action"
or {cb=>\&handler}
, etc.).get()
: $r->get("a", {text=>"A"})->get("b", {text=>"B"});
GET / a => 404 Not Found GET / a / b => "B"
$app->routes->to(text=>"wow");
GET / => "wow"
under()
, or an existing node can be made under by calling inline(1)
. After determining the terminal node that should process the current request, handlers of all the under-nodes will be sequentially called from the root of the tree to the terminal. These handlers must return true or false (you can even asynchronously) - if they return false, subsequent handlers, including the terminal node handler, will not be called. "/something/:name/:id"
name => ["alex","nick"], id => qr/^\d+$/
format => 0 format => ["json","xml"]
agent => qr/Firefox/
$c->stash()
when processing the requesturl_for
# defaults . $r->to("users#"); # /resource . $b = $r->route("/resource", format => 0); # $b $b # /resource. # get() , # , , .. /resource. $b->get()->over(agent=>qr/Firefox/)->to("#ff_only"); $b->get()->to("#not_ff");
$app->defaults
and through the root node $app->routes->to
(maybe some hooks work completely before routing, and then the values ​​from $app->defaults
will be available and may not be available from the root node).$r->any("/path")->to(app=>$otherapp)
, maybe there are additional nuances.over()
, to()
and via()
- they return the current value when called without parameters).$r->route()
creates a new node, parameters:$r->via()
sets the HTTP method (s)$r->over()
sets the conditions$r->to()
sets default parameters$r->under()
creates an under-nodeget()
$r->any()
creates a node for any HTTP methodsget()
$r->get()
creates a node for the HTTP GET method$r->post()
creates a node for the HTTP POST methodget()
$r->put()
creates a node for the HTTP PUT methodget()
$r->delete()
creates a node for the HTTP DELETE methodget()
$r->patch()
creates a node for the HTTP PATCH methodget()
$r->options()
creates a node for the HTTP OPTIONS methodget()
# Mojolicious $r->get("/users/:id", [ format => 0 ], agent => qr/Firefox/, { id => -1, controller => "users" }, [ id => qr/^\d+$/ ], headers => { "X-Secret" => "letmeit" }, \&cb, { action => "list" }, "my_cool_route", ); # get() $r->route("/users/:id", id => qr/^\d+$/, format => 0) ->via("GET") ->over(agent => qr/Firefox/, headers => { "X-Secret" => "letmeit" }) ->to(id => -1, controller => "users", action => "list", cb => \&cb) ->name("my_cool_route");
application/x-www-form-urlencoded
or type multipart/form-data
— but in this case only ordinary parameters are taken, except for filesmultipart/form-data
$c->param
is mentioned - let's see where the values ​​returned by this function come from (in Mojolicious up to 5.47) :scalar $c->param()
- returns undef@names = $c->param()
- returns the names of all GET, POST, UPLOAD and ROUTE parameters$value = $c->param("name")
- returns:@values = $c->param("name")
- returns:$c->param
does is already beyond good and evil (for example, if you were expecting a GET / POST parameter , and get UPLOAD, then instead of the string value , get the object Mojo :: Upload). Everything is good in moderation, even the magic sloth functions that create the wow factor that Mojolicious so much like to implement. $value = $c->stash( "name" ) # ROUTE
# HASHREF: : # - ( ) # - ( ) $params = $c->req->params->to_hash # POST, GET $params = $c->req->query_params->to_hash # GET $params = $c->req->body_params->to_hash # POST # ARRAYREF: , Mojo::Upload $uploads = $c->req->uploads # UPLOAD
@names = @{ $c->req->params->names } # POST GET @names = @{ $c->req->query_params->names } # GET @names = @{ $c->req->body_params->names } # POST @names = keys %{{ map { $_->name => 1 } @{ $c->req->uploads } }} # UPLOAD
$c->req->params->param( "name" ) # POST, GET $c->req->query_params->param( "name" ) # GET $c->req->body_params->param( "name" ) # POST $c->req->upload( "name" ) # UPLOAD
$c->req->params->every_param( "name" ) # POST, GET $c->req->query_params->every_param( "name" ) # GET $c->req->body_params->every_param( "name" ) # POST $c->req->every_upload( "name" ) # UPLOAD
$c->req->param
is the same as $c->req->params->param
$c->req->url->query
is the same as $c->req->query_params
to_hash
you can use pairs
- it returns a link to the array where the names and values ​​of all parameters go successively, and one name may occur several times, but all values ​​are scalars.$tx->res
will be available (with a 404 stub).$dom
has a root node, and the node with the html
tag (if it was in the downloaded page) is a descendant of the root node. Because of this, to_string
and content
on the root node return the same thing.$dom->child_tag_name
), the pearl throws an exception “there is no such method” - in other words, it is almost always necessary to include the parser in eval
.flatten
and compact
collections will help here."*"
means a string with CSS selector. $tx = $ua->get($url); # Mojo::Transaction::HTTP → Mojo::Transaction $tx->error # undef {message=>'…',…} $tx->success # undef $tx->res $tx->req # Mojo::Message::Request → Mojo::Message $tx->res # Mojo::Message::Response → Mojo::Message $tx->redirects # [ Mojo::Transaction::HTTP, … ] $res = $tx->res; # Mojo::Message::Response → Mojo::Message $res->error # undef {message=>'Parse error',…} $res->to_string # "…" (headers+content) $res->is_status_class(200); # bool $res->code # 404 $res->message # "Not Found" $res->headers # Mojo::Headers $res->cookies # [ Mojo::Cookie::Response, … ] $res->cookie('name') # Mojo::Cookie::Response → Mojo::Cookie $res->body # "…" $res->text # "…" (decoded body using charset) $res->dom # Mojo::DOM $res->json # Mojo::JSON $headers = $res->headers; # Mojo::Headers $headers->names # [ "Content-Type", "Server", … ] $headers->to_hash # { "Content-Type" => "…", … } $headers->header('Server') # "…" $headers->$standard_header_name # "…" (shortcuts for useful headers) $dom = $res->dom; # Mojo::DOM $dom->to_string # "…" ( , ) $dom->content # "…" ( ) $dom->type # "…" ( : root,tag,text,comment,…) $dom->tag # "…" "" ( ) $dom->attr # {name=>"val",…} $dom->attr('name') # "val" $dom->{name} # $dom->attr("name") $dom->all_text # "…" ( ) $dom->all_text(0) # "…" ( , ) $dom->text # "…" ( ) $dom->text(0) # "…" ( , ) $dom->root # Mojo::DOM ( ) $dom->parent # Mojo::DOM undef (-) $dom->next # Mojo::DOM undef ( -) $dom->next_node # Mojo::DOM undef ( -) $dom->previous # Mojo::DOM undef ( -) $dom->previous_node # Mojo::DOM undef ( -) $dom->matches('*') # true/false ( ) $dom->at('*') # Mojo::DOM undef ( ) $dom->find('*') # Mojo::Collection ( ) $dom->ancestors # Mojo::Collection (-) $dom->ancestors('*') # Mojo::Collection ( -) $dom->following # Mojo::Collection ( -) $dom->following("*") # Mojo::Collection ( -) $dom->following_nodes # Mojo::Collection ( -) $dom->preceding # Mojo::Collection ( -) $dom->preceding("*") # Mojo::Collection ( -) $dom->preceding_nodes # Mojo::Collection ( -) $dom->children # Mojo::Collection (-) $dom->children('*') # Mojo::Collection ( -) $dom->descendant_nodes # Mojo::Collection ( ) $dom->child_nodes # Mojo::Collection ( -) $dom->[0] # $dom->child_nodes->[0] $res->dom('*') # $dom->find('*')
$ua
, TCP- - — : $app
, Mojo::UserAgent, , , url, , $app
. Mojo::UserAgent::Server->app($app);
$ perl -Mojo -E 'get "/", {text=>"wow\n"}; app->start' get / wow
MOJO_
— , .. Mojolicious, :MOJO_MODE
— - , , , :$app->mode
exception
not_found
( MOJO_MODE
, . «exception.$mode.html.ep»)$app->log->level
«debug» «info» MOJO_MODE
«development»${mode}_mode()
startup()
( , ) .MOJO_LOG_LEVEL
— «warn» Mojolicious::Lite, .Source: https://habr.com/ru/post/227493/
All Articles