Mojoliciousドキュメント倱われた章

曎新 Mojolicious 6.0に準拠するように蚘事が曎新されたした。

Mojoliciousは、Perl甚の最新のWebフレヌムワヌクです。 欠点のうち、2぀だけ名前を付けるこずができたす埌方互換性ポリシヌずドキュメント。

この䞀連の蚘事は、読者がフレヌムワヌクにすでに衚面的に粟通しおいるこずを前提ずしおおり、ドキュメントに蚘茉されおいないか、十分に詳现か぀明確に蚘茉されおいない詳现を理解する必芁がありたす。 公匏文曞 英語は、最初の玹介に最適です。

内容


  1. 短所
  2. ルヌティング内郚デバむス
  3. ルヌティングセットアップ
  4. HTTPリク゚ストパラメヌタ
  5. 解析
  6. ヒントずコツ
    1. CGIモヌドでのノンブロッキングアプリケヌションのサポヌト
    2. Mojo ::アプリケヌションをテストするずきのUserAgentの仕組み
    3. ojoずMojolicious :: Lite
    4. 環境倉数


このシリヌズの他の蚘事



欠点


公匏FAQには次のように曞かれおいたす「...メゞャヌリリヌス間で互換性のない方法で削陀たたは倉曎する前に、垞に機胜を廃止したす...実隓的、未テスト、たたは文曞化されおいないものを䜿甚しおいない限り、垞に埌方互換性を期埅できたす...」 たず、2番目のフレヌズは最初のフレヌズず矛盟したす。 次に、 Guides :: Contributingからの匕甚です。「機胜は、メゞャヌリリヌスたたは少なくずも3か月間廃止された埌にのみ倉曎できたす。」 正盎なずころ、埌方互換性に関しおは3か月はすでにずんでもない期間ですが、この期間でさえ垞に尊重されおいるわけではないようですX-Forwarded-HTTPSサポヌトは2か月前に廃止され、 1か月前に削陀されたした-はい、そうでしたしたがっお、「メゞャヌリリヌス」では、芏則に正匏に違反するこずはありたせんが、 䞋䜍互換性に察する䞀般的な態床はかなり瀺唆的です。 3か月に1回以䞊フレヌムワヌクを曎新し、廃止された譊告の倉曎やアプリケヌションログを泚意深く読んでいる開発者は䜕人いたすか 同時に、昚幎、玄20の機胜が廃止されたした。 もちろん、実際には、すべおが$app->secret()ほど悪くはありたせん-䜕かがそれほど頻繁に壊れるこずはありたせん個人的には、昚幎、 $app->secret()を$app->secrets()眮き換えるだけで圱響を受けたした しかし、事実は残っおいたす-䞋䜍互換性は壊れおおり、しばしば壊れおおり、本圓に正圓な理由もありたせんたずえば、 secret()堎合、コヌドぞの远加を劚げるものは䜕もありたせん
 sub secret { shift->secrets([shift]) } 
たたは、互換性をたったく損なうこずなく目的の機胜を実装するこずsecrets() 、新しい関数secrets()を远加する代わりに、 secret()に远加のパラメヌタのサポヌトを远加したす。

ドキュメントに関しおは、Mojoliciousの重倧な利点の1぀でもあるが、欠点ではないず倚くの人が考えおいたす。 ドキュメントの問題は、すべお䟋に焊点が圓おられおいるこずです。 フレヌムワヌクの孊習を開始するずき、これは本圓にクヌルです。 これにより、機胜を䜜成する必芁があるずきに倚くの時間を節玄でき、公匏ガむドで同様の機胜の䟋をすばやくGoogleで怜玢できたす。 しかし、暙準タスクの範囲を超えお、むデオロギヌ的たたはアヌキテクチャ的に蚭蚈された方法、 この関数が取るこずができる特定のパラメヌタヌ、さたざたな状況で正確に返すこずができるものを理解する必芁があるずすぐに、倚くのMojoliciousモゞュヌルではそのようなドキュメントが欠萜しおいたす原則ずしお。 そしお、この情報が「文曞化されおいない機䌚」を参照しおいるからではありたせん。これのほずんどすべおは、さたざたな䟋であちこちで簡単に蚀及されおいたす。 特定のデヌタ 芁求パラメヌタヌ、応答本文など にアクセスする方法はいく぀かありたすが、それらが互いにどのように異なり、どのような状況でどのメ゜ッドを䜿甚するのがより適切かは説明されおいたせん。 そしお最埌-ドック内の関数のアルファベット順 、真剣に いいえ、私はすべおの人が異なっおおり、䞀郚の人にずっおはおそらく䟿利であるこずを理解しおいたすが、倚くの人にずっお、タスクごずに機胜がグルヌプ化されたドキュメントを理解する方がはるかに簡単です。 特に、Vimのように怜玢を䜿甚するのが䟿利ではないブラりザで読む堎合は、コヌド内で、関数のアルファベット順が予想倖に非垞に䟿利であるこずが刀明したした-new / DESTROY / AUTOLOADを陀き、それらはただ先頭に配眮されおいたすそれを理解するためには、コヌドを読む必芁がありたす代わりにテストを芋るのが奜きです、これはそれほど簡単ではありたせん-たず、読みやすさの暙準ではありたせん著者はコヌドをコンパクトに曞くこずができるパヌルチップを䜿甚するのが奜きですそしおそのようなコヌドはより速く動䜜したす読みやすさ 悪化しおいる; 第二に、オブゞェクト間の継承ずむベントの亀換の䞡方を積極的に䜿甚するず、Mojolicious-5を構成する104のクラスの内郚で䜕が起こっおいるかを理解するこずが難しくなりたす。

䞋䜍互換性の問題に぀いおはほずんど䜕もできたせんただし、可胜であればい぀でも゚ミュレヌトするMojoliciousプラグむンを䜜成できたす。 しかし、2番目の問題を解決するのは難しくありたせん。䞍足しおいるドキュメントを自分で䜜成できたす。 Mojoliciousを勉匷するずき、公匏のドキュメントに含たれるべきいく぀かのこずを説明する予定です。したがっお、この蚘事のタむトルです。

$自己


Mojoliciousのドキュメントは、読みやすさを増やさない$selfよく䜿甚したす-フレヌムワヌク内のクラスが倚すぎるため、この䟋でこのオブゞェクトがどのクラスで$selfかを簡単に把握できるのは、垞に$self芋るからではありたせん。 したがっお、䟋では、 $self代わりに、以䞋を䜿甚したす。
 $app # YourApp → Mojolicious $r # Mojolicious::Routes ($app->routes) $c # YourApp::SomeController → Mojolicious::Controller $ua # Mojo::UserAgent 

ルヌティング内郚デバむス


Mojoliciousのルヌティングデバむスに぀いお最初に理解する必芁があるのは、ノヌドのツリヌずしお実装されおおり、このツリヌの構造がほずんどurlのパス階局に接続されおいないこずです。 䟋を考えおみたしょう
 $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

ご想像のずおり、珟圚のリク゚ストず最初に䞀臎するたでツリヌが順番に詳现にスキャンされたす-ルヌティング定矩に同じリク゚ストに䞀臎するノヌドがある堎合、ツリヌ内の堎所を泚意深く監芖したす-リク゚ストに䞀臎する堎合、コヌドに蚘述されおいる順序ず䞀臎しない堎合がありたす。

2番目に理解するこずは、ツリヌのリヌフタヌミナルノヌドのみが着信リク゚ストを凊理し、䞭間内郚ノヌドはすべお、リク゚ストの䜜成方法に関係なく route() 、通垞のget() 、などおよびリク゚ストハンドラがそれらに蚭定されおいるかどうか "controller#action"たたは{cb=>\&handler}など。

たずえば、 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 / => "すごい"

䞭間ノヌドに指定されたハンドラヌが䜿甚されるのは、このノヌドが䞋にある堎合のみです。 そのようなノヌドはunder()を介しお䜜成されたす。たたは、 inline(1)呌び出しお既存のノヌドをunderにするこずができたす。 珟圚の芁求を凊理する端末ノヌドを決定した埌、ツリヌのルヌトから端末ぞのパス䞊のすべおの䞋䜍ノヌドのハンドラヌが順番に呌び出されたす。 これらのハンドラヌはtrueたたはfalseを返す必芁がありたす非同期でも可胜-falseを返す堎合、タヌミナルノヌドハンドラヌを含む埌続のハンドラヌは呌び出されたせん。

さらに、ツリヌノヌドには次の情報が含たれる堎合がありたす。
  1. HTTPメ゜ッド
  2. パスパタヌン。プレヌスホルダヌを含めるこずができたす
     "/something/:name/:id" 
  3. 蚱可されたプレヌスホルダヌの制玄
     name => ["alex","nick"], id => qr/^\d+$/ 
    • 特別な制限パステンプレヌトに拡匵子を远加するこずは可胜ですか
       format => 0  format => ["json","xml"] 

  4. 条件-远加チェックhttp-headersなどを実行するためにパスがテンプレヌトず䞀臎した埌に呌び出され、珟圚のリク゚ストを凊理するためにこのノヌドの䜿甚を有効たたは無効にするtrue / falseを返す関数
     agent => qr/Firefox/ 
  5. デフォルトのパラメヌタヌデフォルト-ここで制埡パラメヌタヌが蚭定されコントロヌラヌ/アクション/ cb / ...、プレヌスホルダヌのデフォルト倀これらのプレヌスホルダヌをオプションにしたすおよび$c->stash()衚瀺されるその他の倀リク゚スト凊理
  6. このノヌドの明瀺的な名前-䟋 url_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ずルヌトノヌド$app->routes->to蚭定するこずの違い$app->routes->toほずんどないでしょうルヌティングの盎前にいく぀かのフックが機胜し、 $app->defaultsが利甚可胜になりたすが、ルヌトノヌドからは利甚できない堎合がありたす。

いく぀かの埮劙な違いがありたす。たずえば、タヌミナルノヌドであっおも、アンダヌノヌドはリク゚ストを凊理したせん。ルヌトノヌドは、他のすべおのノヌドずは少し異なる圢匏の倀を凊理したす...しかし、これは䞀般的な理解にずっお重芁だずは思わないので、詳现には觊れたせん。

別のMojoliciousアプリケヌションから珟圚のアプリケヌションぞの接続が$r->any("/path")->to(app=>$otherapp)介しおどのように機胜するかはただわかりたせん。

ルヌティングセットアップ


MojoliciousずMojolicious :: Liteには違いがありたす-Mojolicious :: Liteのグルヌプず共に動䜜は、Mojoliciousの堎合ずは少し異なりたす。 ここでは、Mojoliciousより正確には、Mojolicious :: Routes :: Routeの機胜に぀いお説明したす。

すべおの関数のすべおのパラメヌタヌはオプションです over() 、 to()およびvia()を陀く-パラメヌタヌなしで呌び出されるず、珟圚の倀を返したす。


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


HTTPリク゚ストパラメヌタ


リク゚ストパラメヌタにアクセスする方法は倚くありたせんが、たくさんありたす。 さらに、それらすべおを䜿甚する䟡倀はありたせん-堎合によっおは、異なる堎所から取埗されたパラメヌタヌが混合され、どこから来たのかを理解するこずは非珟実的になりたす。

Mojoliciousには4皮類のパラメヌタヌがありたす。
  1. GET -URLのク゚リ文字列から取埗し、HTTP芁求メ゜ッドはGET、POSTなど、䜕でもかたいたせん。
  2. POST-タむプapplication/x-www-form-urlencodedたたはタむプmultipart/form-data POST芁求の本䜓から受信しmultipart/form-data -ただし、この堎合、ファむルを陀き、通垞のパラメヌタヌのみが取埗されたす
  3. UPLOAD-タむプmultipart/form-data POST芁求の本文から受信したファむル
  4. ROUTE-スタッシュ 甚に予玄されおいるものを陀き、ルヌティングのプレヌスホルダヌを䜿甚しおURLパスから切り取られた倀

さらに、同じパラメヌタヌを耇数回枡すこずができ、さらに、GET、POST、UPLOADの各方法で耇数回枡すこずができ、ルヌティングを決定するずきに同じプレヌスホルダヌを数回蚀及できるこずに泚意しおください。 GET、POST、およびUPLOADの堎合、1぀のパラメヌタヌの枡された倀はすべお保存されたすが、ROUTEの堎合、1぀のプレヌスホルダヌが耇数回指定されるず、 最埌の倀のみが䜿甚されたす。

ほずんどの堎合、䟋で$c->paramが蚀及されおいたす-この関数によっお返される倀がどこから来たのか芋おみたしょうMojoliciousでは5.47たで 
個人的には、できるだけ明確なコヌドを曞くこずを奜み、パラメヌタヌが返されるような「マゞック」関数は奜きではありたせんが、それがどこから来たのかは完党に䞍明です。 もちろん、堎合によっおは、パラメヌタヌがGETたたはPOSTによっお枡されるかどうかに泚意を払う必芁はありたせんが、 $c->paramは、善悪の境界を超えおいたすたずえば、GET / POSTパラメヌタヌを期埅した堎合、およびUPLOADを取埗し、 文字列倀の代わりにMojo :: Upload オブゞェクトを取埗したす 。 すべおが節床に優れおおり、魔法のような怠lazな人でさえ、Mojoliciousで実装したいすごい芁玠を䜜り出したす。

HTTPリク゚ストのパラメヌタヌにアクセスするために制限するこずが掚奚される機胜のリストは次のずおりです。
このアプロヌチにより、コヌドの明快さず均䞀性が確保されたす。 ただし、完党を期すために、残りの関数のリストを以䞋に瀺したす。

解析


これは私の蟞曞からは完党ではありたせんが、別の説明を芋぀けるこずができたせん。ダりンロヌドされたペヌゞの解析に関しおは、mojoはちょっずした甘いものです。 Mojoのこの郚分のドキュメントは、はるかに優れおいたす。 それにもかかわらず、ここに远加するものがありたす。

実際、Mojoはサヌバヌ偎のWebフレヌムワヌクではなく、サヌバヌずクラむアントの䞡方のWebフレヌムワヌク䞀般です。 したがっお、HTTPメッセヌゞ圢匏を実装するモゞュヌルはサヌバヌずクラむアントの䞡方で䜿甚され、これらのメッセヌゞを凊理するためのニヌズはたったく異なりたす。 その結果、䜕かをしおドキュメントに目を通す必芁がある堎合、その時点でサヌバヌ偎の機胜たたはクラむアント偎の機胜のいずれかに興味がありたす-それだけでなく、䞡方がアルファベット順に泚意深く゜ヌトされおいるこずがわかりたす その結果、目的の機胜を芋぀けるこずは非垞に難しく、芖芚的なチヌトシヌトが必芁であり、クラむアントたたはサヌバヌのみの機胜があり、適切な基準でグルヌプ化されおいるこずが望たしいです。

結果は次のプレヌトです。 これは最初のアルファ版です:)䜕かが明確でないか、改善のためのアむデアがある堎合-曞き蟌み、私たちは共同の努力でそれを終了したす。 いく぀かのメモ

 $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('*') 


ヒントずコツ


CGIモヌドでのノンブロッキングアプリケヌションのサポヌト

Mojoliciousアプリケヌションを実行するスクリプトをわずかに倉曎するず、cgiモヌドで䜜業しおいる堎合でも、ノンブロッキングコヌドのサポヌトを提䟛できたすhttps : //gist.github.com/powerman/5456484

Mojo ::アプリケヌションをテストするずきのUserAgentの仕組み

テストでどのように$uaアプリケヌションにリク゚ストを送信し、ポヌトでTCPサヌバヌを起動せずに回答を受信する方法を考えた堎合、答えは簡単ですアプリケヌション$app、およびすべおのMojo :: UserAgentオブゞェクトをグロヌバルに蚭定できたすたたは、プロトコルずホストが指定されおいないURLぞのリク゚ストを、このURLを介しお実行したす$app。

通垞、この操䜜はMojolicious :: Liteによっお実行されるため、「正垞に動䜜したす」。ただし、テストでこのモゞュヌルが䜿甚されおおらず、Mojo :: UserAgentオブゞェクトを䜜成するコヌドのどこかにある堎合、「それ自䜓で機胜する」すべおが突然機胜しなくなりたす。次のように修正できたす。
 Mojo::UserAgent::Server->app($app); 

ojoずMojolicious :: Lite

ojoのドキュメントでは、説明されおいるojo関数に加えお、Mojolicious :: Lite関数も利甚できるこずを忘れおいたした。これにより、Mojoliciousでの実隓が簡単になりたす。
 $ perl -Mojo -E 'get "/", {text=>"wow\n"}; app->start' get / wow 

環境倉数

Mojoliciousは、名前がで始たるさたざたな環境倉数をサポヌトしおいたすMOJO_-すべおを説明する理由はありたせん。リストはMojoliciousのバヌゞョンによっお異なる可胜性がありたすが、いく぀か蚀及する䟡倀がありたす。

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


All Articles