Hello community, here is the log from the commit of package perl-Mojolicious for openSUSE:Factory checked in at 2016-01-28 17:23:47 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/perl-Mojolicious (Old) and /work/SRC/openSUSE:Factory/.perl-Mojolicious.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "perl-Mojolicious" Changes: -------- --- /work/SRC/openSUSE:Factory/perl-Mojolicious/perl-Mojolicious.changes 2016-01-22 01:09:55.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.perl-Mojolicious.new/perl-Mojolicious.changes 2016-01-28 17:24:40.000000000 +0100 @@ -1,0 +2,18 @@ +Mon Jan 25 16:55:00 UTC 2016 - [email protected] + +- updated to 6.42 + see /usr/share/doc/packages/perl-Mojolicious/Changes + + 6.42 2016-01-24 + - Fixed use of deprecated Perl feature in Mojo::JSON. + - Fixed validation filter bugs in Mojolicious::Validator::Validation. + + 6.41 2016-01-20 + - Added support for validation filters. + - Added filters attribute to Mojolicious::Validator. + - Added add_filter method to Mojolicious::Validator. + - Added filter arguments to optional and required methods in + Mojolicious::Validator::Validation. + - Fixed MOJO_WEBSOCKET_DEBUG environment variable. (jberger) + +------------------------------------------------------------------- Old: ---- Mojolicious-6.40.tar.gz New: ---- Mojolicious-6.42.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ perl-Mojolicious.spec ++++++ --- /var/tmp/diff_new_pack.COY4ue/_old 2016-01-28 17:24:41.000000000 +0100 +++ /var/tmp/diff_new_pack.COY4ue/_new 2016-01-28 17:24:41.000000000 +0100 @@ -17,7 +17,7 @@ Name: perl-Mojolicious -Version: 6.40 +Version: 6.42 Release: 0 %define cpan_name Mojolicious Summary: Real-time web framework ++++++ Mojolicious-6.40.tar.gz -> Mojolicious-6.42.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/Changes new/Mojolicious-6.42/Changes --- old/Mojolicious-6.40/Changes 2016-01-13 19:13:50.000000000 +0100 +++ new/Mojolicious-6.42/Changes 2016-01-24 23:00:27.000000000 +0100 @@ -1,4 +1,16 @@ +6.42 2016-01-24 + - Fixed use of deprecated Perl feature in Mojo::JSON. + - Fixed validation filter bugs in Mojolicious::Validator::Validation. + +6.41 2016-01-20 + - Added support for validation filters. + - Added filters attribute to Mojolicious::Validator. + - Added add_filter method to Mojolicious::Validator. + - Added filter arguments to optional and required methods in + Mojolicious::Validator::Validation. + - Fixed MOJO_WEBSOCKET_DEBUG environment variable. (jberger) + 6.40 2016-01-13 - Removed client_challenge, client_handshake, server_handshake and server_open methods from Mojo::Transaction::WebSocket. (batman, sri) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/META.json new/Mojolicious-6.42/META.json --- old/Mojolicious-6.40/META.json 2016-01-13 21:07:28.000000000 +0100 +++ new/Mojolicious-6.42/META.json 2016-01-24 23:01:37.000000000 +0100 @@ -58,5 +58,5 @@ }, "x_IRC" : "irc://irc.perl.org/#mojo" }, - "version" : "6.40" + "version" : "6.42" } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/META.yml new/Mojolicious-6.42/META.yml --- old/Mojolicious-6.40/META.yml 2016-01-13 21:07:28.000000000 +0100 +++ new/Mojolicious-6.42/META.yml 2016-01-24 23:01:37.000000000 +0100 @@ -31,4 +31,4 @@ homepage: http://mojolicious.org license: http://www.opensource.org/licenses/artistic-license-2.0 repository: https://github.com/kraih/mojo.git -version: '6.40' +version: '6.42' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/README.md new/Mojolicious-6.42/README.md --- old/Mojolicious-6.40/README.md 2016-01-09 05:25:41.000000000 +0100 +++ new/Mojolicious-6.42/README.md 2016-01-24 04:33:27.000000000 +0100 @@ -11,23 +11,25 @@ ## Features - * An amazing real-time web framework, allowing you to easily grow single + * An amazing **real-time web framework**, allowing you to easily grow single file prototypes into well-structured web applications. * Powerful out of the box with RESTful routes, plugins, commands, Perl-ish templates, content negotiation, session management, form validation, testing framework, static file server, CGI/[PSGI](http://plackperl.org) detection, first class Unicode support and much more for you to discover. + * A powerful **web development toolkit**, that you can use for all kinds of + applications, independently of the web framework. + * Full stack HTTP and WebSocket client/server implementation with IPv6, TLS, + SNI, IDNA, HTTP/SOCKS5 proxy, Comet (long polling), keep-alive, connection + pooling, timeout, cookie, multipart, and gzip compression support. + * Built-in non-blocking I/O web server, supporting multiple event loops as + well as optional preforking and hot deployment, perfect for building + highly scalable web services. + * JSON and HTML/XML parser with CSS selector support. * Very clean, portable and object-oriented pure-Perl API with no hidden magic and no requirements besides Perl 5.22.0 (versions as old as 5.10.1 can be used too, but may require additional CPAN modules to be installed) - * Full stack HTTP and WebSocket client/server implementation with IPv6, TLS, - SNI, IDNA, HTTP/SOCKS5 proxy, Comet (long polling), keep-alive, connection - pooling, timeout, cookie, multipart, and gzip compression support. - * Built-in non-blocking I/O web server, supporting multiple event loops as - well as optional preforking and hot deployment, perfect for building - highly scalable web services. - * JSON and HTML/XML parser with CSS selector support. * Fresh code based upon years of experience developing [Catalyst](http://www.catalystframework.org), free and open source. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/lib/Mojo/Base.pm new/Mojolicious-6.42/lib/Mojo/Base.pm --- old/Mojolicious-6.40/lib/Mojo/Base.pm 2016-01-09 05:25:41.000000000 +0100 +++ new/Mojolicious-6.42/lib/Mojo/Base.pm 2016-01-19 19:23:42.000000000 +0100 @@ -115,7 +115,7 @@ use Mojo::Base -base; has name => 'Nyan'; - has [qw(age weight)] => 4; + has ['age', 'weight'] => 4; package Tiger; use Mojo::Base 'Cat'; @@ -181,11 +181,11 @@ =head2 has has 'name'; - has [qw(name1 name2 name3)]; + has ['name1', 'name2', 'name3']; has name => 'foo'; has name => sub {...}; - has [qw(name1 name2 name3)] => 'foo'; - has [qw(name1 name2 name3)] => sub {...}; + has ['name1', 'name2', 'name3'] => 'foo'; + has ['name1', 'name2', 'name3'] => sub {...}; Create attributes for hash-based objects, just like the L</"attr"> method. @@ -197,11 +197,11 @@ $object->attr('name'); SubClass->attr('name'); - SubClass->attr([qw(name1 name2 name3)]); + SubClass->attr(['name1', 'name2', 'name3']); SubClass->attr(name => 'foo'); SubClass->attr(name => sub {...}); - SubClass->attr([qw(name1 name2 name3)] => 'foo'); - SubClass->attr([qw(name1 name2 name3)] => sub {...}); + SubClass->attr(['name1', 'name2', 'name3'] => 'foo'); + SubClass->attr(['name1', 'name2', 'name3'] => sub {...}); Create attribute accessor for hash-based objects, an array reference can be used to create more than one at a time. Pass an optional second argument to set diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/lib/Mojo/Headers.pm new/Mojolicious-6.42/lib/Mojo/Headers.pm --- old/Mojolicious-6.40/lib/Mojo/Headers.pm 2016-01-13 18:52:30.000000000 +0100 +++ new/Mojolicious-6.42/lib/Mojo/Headers.pm 2016-01-23 01:38:17.000000000 +0100 @@ -482,7 +482,7 @@ my $names = $headers->names; -Return a list of all currently defined headers. +Return an array reference with all currently defined headers. # Names of all headers say for @{$headers->names}; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/lib/Mojo/IOLoop/Delay.pm new/Mojolicious-6.42/lib/Mojo/IOLoop/Delay.pm --- old/Mojolicious-6.40/lib/Mojo/IOLoop/Delay.pm 2016-01-09 05:25:41.000000000 +0100 +++ new/Mojolicious-6.42/lib/Mojo/IOLoop/Delay.pm 2016-01-19 19:37:41.000000000 +0100 @@ -224,8 +224,8 @@ my $hash = $delay->data; my $foo = $delay->data('foo'); - $delay = $delay->data({foo => 'bar'}); - $delay = $delay->data(foo => 'bar'); + $delay = $delay->data({foo => 'bar', baz => 23}); + $delay = $delay->data(foo => 'bar', baz => 23); Data shared between all L</"steps">. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/lib/Mojo/JSON.pm new/Mojolicious-6.42/lib/Mojo/JSON.pm --- old/Mojolicious-6.40/lib/Mojo/JSON.pm 2016-01-09 05:25:41.000000000 +0100 +++ new/Mojolicious-6.42/lib/Mojo/JSON.pm 2016-01-24 19:03:27.000000000 +0100 @@ -1,6 +1,7 @@ package Mojo::JSON; use Mojo::Base -strict; +use B; use Carp 'croak'; use Exporter 'import'; use JSON::PP (); @@ -248,10 +249,9 @@ # Null return 'null' unless defined $value; - # Number (bitwise operators change behavior based on the internal value type) - my $check = (my $dummy = "0") & $value; + # Number return $value - if (!($check ^ $check) && length $check) + if B::svref_2object(\$value)->FLAGS & (B::SVp_IOK | B::SVp_NOK) && 0 + $value eq $value && $value * 0 == 0; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/lib/Mojo/Parameters.pm new/Mojolicious-6.42/lib/Mojo/Parameters.pm --- old/Mojolicious-6.40/lib/Mojo/Parameters.pm 2016-01-13 19:03:30.000000000 +0100 +++ new/Mojolicious-6.42/lib/Mojo/Parameters.pm 2016-01-23 01:38:38.000000000 +0100 @@ -283,7 +283,7 @@ my $names = $params->names; -Return a list of all parameter names. +Return an array reference with all parameter names. # Names of all parameters say for @{$params->names}; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/lib/Mojo/Server/Daemon.pm new/Mojolicious-6.42/lib/Mojo/Server/Daemon.pm --- old/Mojolicious-6.40/lib/Mojo/Server/Daemon.pm 2016-01-13 07:05:52.000000000 +0100 +++ new/Mojolicious-6.42/lib/Mojo/Server/Daemon.pm 2016-01-19 19:28:55.000000000 +0100 @@ -364,7 +364,7 @@ $daemon->listen(['http://*:8080?reuse=1']); # Listen on two ports with HTTP and HTTPS at the same time - $daemon->listen([qw(http://*:3000 https://*:4000)]); + $daemon->listen(['http://*:3000', 'https://*:4000']); # Use a custom certificate and key $daemon->listen(['https://*:3000?cert=/x/server.crt&key=/y/server.key']); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/lib/Mojo/Transaction/HTTP.pm new/Mojolicious-6.42/lib/Mojo/Transaction/HTTP.pm --- old/Mojolicious-6.40/lib/Mojo/Transaction/HTTP.pm 2016-01-13 18:56:08.000000000 +0100 +++ new/Mojolicious-6.42/lib/Mojo/Transaction/HTTP.pm 2016-01-23 01:39:01.000000000 +0100 @@ -305,8 +305,8 @@ my $redirects = $tx->redirects; -Return a list of all previous transactions that preceded this follow-up -transaction. +Return an array reference with all previous transactions that preceded this +follow-up transaction. # Paths of all previous requests say $_->req->url->path for @{$tx->redirects}; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/lib/Mojo/Transaction/WebSocket.pm new/Mojolicious-6.42/lib/Mojo/Transaction/WebSocket.pm --- old/Mojolicious-6.40/lib/Mojo/Transaction/WebSocket.pm 2016-01-13 18:57:55.000000000 +0100 +++ new/Mojolicious-6.42/lib/Mojo/Transaction/WebSocket.pm 2016-01-19 20:32:28.000000000 +0100 @@ -136,8 +136,8 @@ my $self = shift; my %protos = map { trim($_) => 1 } split ',', - $self->req->headers->sec_websocket_protocol; - return undef unless my $proto = first { $protos{$_} } @_; + $self->req->headers->sec_websocket_protocol // ''; + return undef unless defined(my $proto = first { $protos{$_} } @_); $self->res->headers->sec_websocket_protocol($proto); return $proto; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/lib/Mojo/UserAgent/Proxy.pm new/Mojolicious-6.42/lib/Mojo/UserAgent/Proxy.pm --- old/Mojolicious-6.40/lib/Mojo/UserAgent/Proxy.pm 2016-01-09 05:25:41.000000000 +0100 +++ new/Mojolicious-6.42/lib/Mojo/UserAgent/Proxy.pm 2016-01-19 19:28:23.000000000 +0100 @@ -75,7 +75,7 @@ =head2 not my $not = $proxy->not; - $proxy = $proxy->not([qw(localhost intranet.mojolicious.org)]); + $proxy = $proxy->not(['localhost', 'intranet.mojolicious.org']); Domains that don't require a proxy server to be used. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/lib/Mojo/UserAgent/Transactor.pm new/Mojolicious-6.42/lib/Mojo/UserAgent/Transactor.pm --- old/Mojolicious-6.40/lib/Mojo/UserAgent/Transactor.pm 2016-01-12 21:25:33.000000000 +0100 +++ new/Mojolicious-6.42/lib/Mojo/UserAgent/Transactor.pm 2016-01-19 19:28:02.000000000 +0100 @@ -114,8 +114,8 @@ # Generator if (@_ > 1) { - return $tx unless my $generator = $self->generators->{shift()}; - $self->$generator($tx, @_); + my $cb = $self->generators->{shift()}; + $self->$cb($tx, @_); } # Body @@ -328,6 +328,11 @@ Register a content generator. + $t->add_generator(foo => sub { + my ($t, $tx, @args) = @_; + ... + }); + =head2 endpoint my ($proto, $host, $port) = $t->endpoint(Mojo::Transaction::HTTP->new); @@ -411,7 +416,8 @@ An array reference can be used for multiple form values sharing the same name. # POST request with form values sharing the same name - my $tx = $t->tx(POST => 'http://example.com' => form => {a => [qw(b c d)]}); + my $tx = $t->tx( + POST => 'http://example.com' => form => {a => ['b', 'c', 'd']}); A hash reference with a C<content> or C<file> value can be used to switch to the C<multipart/form-data> content type for file uploads. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/lib/Mojo/WebSocket.pm new/Mojolicious-6.42/lib/Mojo/WebSocket.pm --- old/Mojolicious-6.40/lib/Mojo/WebSocket.pm 2016-01-13 18:57:11.000000000 +0100 +++ new/Mojolicious-6.42/lib/Mojo/WebSocket.pm 2016-01-19 16:57:09.000000000 +0100 @@ -3,7 +3,7 @@ use Config; use Exporter 'import'; -use Mojo::Util qw(b64_encode sha1_bytes xor_encode); +use Mojo::Util qw(b64_encode dumper sha1_bytes xor_encode); use constant DEBUG => $ENV{MOJO_WEBSOCKET_DEBUG} || 0; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/lib/Mojo.pm new/Mojolicious-6.42/lib/Mojo.pm --- old/Mojolicious-6.40/lib/Mojo.pm 2016-01-09 05:25:41.000000000 +0100 +++ new/Mojolicious-6.42/lib/Mojo.pm 2016-01-24 06:10:28.000000000 +0100 @@ -31,7 +31,7 @@ =head1 NAME -Mojo - Duct tape for the HTML5 web! +Mojo - Web development toolkit =head1 SYNOPSIS @@ -58,9 +58,11 @@ =head1 DESCRIPTION -A flexible runtime environment for Perl real-time web frameworks, with all the -basic tools and helpers needed to write simple web applications and higher -level web frameworks, such as L<Mojolicious>. +A powerful web development toolkit, with all the basic tools and helpers needed +to write simple web applications and higher level web frameworks, such as +L<Mojolicious>. Some of the most commonly used tools are L<Mojo::UserAgent>, +L<Mojo::DOM>, L<Mojo::JSON>, L<Mojo::Server::Daemon>, L<Mojo::Server::Prefork>, +L<Mojo::IOLoop> and L<Mojo::Template>. See L<Mojolicious::Guides> for more! @@ -115,8 +117,8 @@ my $hash = $app->config; my $foo = $app->config('foo'); - $app = $app->config({foo => 'bar'}); - $app = $app->config(foo => 'bar'); + $app = $app->config({foo => 'bar', baz => 23}); + $app = $app->config(foo => 'bar', baz => 23); Application configuration. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/lib/Mojolicious/Controller.pm new/Mojolicious-6.42/lib/Mojolicious/Controller.pm --- old/Mojolicious-6.40/lib/Mojolicious/Controller.pm 2016-01-12 21:50:53.000000000 +0100 +++ new/Mojolicious-6.42/lib/Mojolicious/Controller.pm 2016-01-20 06:04:52.000000000 +0100 @@ -575,7 +575,7 @@ my $value = $c->param('foo'); $c = $c->param(foo => 'ba;r'); - $c = $c->param(foo => qw(ba;r baz)); + $c = $c->param(foo => 'ba;r', 'baz'); $c = $c->param(foo => ['ba;r', 'baz']); Access route placeholder values that are not reserved stash values, file @@ -866,8 +866,8 @@ my $hash = $c->stash; my $foo = $c->stash('foo'); - $c = $c->stash({foo => 'bar'}); - $c = $c->stash(foo => 'bar'); + $c = $c->stash({foo => 'bar', baz => 23}); + $c = $c->stash(foo => 'bar', baz => 23); Non-persistent data storage and exchange for the current request, application wide default values can be set with L<Mojolicious/"defaults">. Some stash @@ -929,7 +929,7 @@ # Validate GET/POST parameter my $validation = $c->validation; - $validation->required('title')->size(3, 50); + $validation->required('title', 'trim')->size(3, 50); my $title = $validation->param('title'); # Validate file upload diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/lib/Mojolicious/Guides/Contributing.pod new/Mojolicious-6.42/lib/Mojolicious/Guides/Contributing.pod --- old/Mojolicious-6.40/lib/Mojolicious/Guides/Contributing.pod 2016-01-09 05:25:41.000000000 +0100 +++ new/Mojolicious-6.42/lib/Mojolicious/Guides/Contributing.pod 2016-01-24 04:16:08.000000000 +0100 @@ -88,9 +88,9 @@ =head2 Mission statement -L<Mojo> is a runtime environment for Perl real-time web frameworks. It provides -all the basic tools and helpers needed to write simple web applications and -higher level web frameworks, such as L<Mojolicious>. +L<Mojo> is a web development toolkit, with all the basic tools and helpers +needed to write simple web applications and higher level web frameworks, such as +L<Mojolicious>. All components should be reusable in other projects, and in a UNIXish way only loosely coupled. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/lib/Mojolicious/Guides/Rendering.pod new/Mojolicious-6.42/lib/Mojolicious/Guides/Rendering.pod --- old/Mojolicious-6.40/lib/Mojolicious/Guides/Rendering.pod 2016-01-13 19:13:08.000000000 +0100 +++ new/Mojolicious-6.42/lib/Mojolicious/Guides/Rendering.pod 2016-01-19 19:18:41.000000000 +0100 @@ -301,7 +301,7 @@ through the L<Mojolicious::Controller/"stash">. $c->stash(description => 'web framework'); - $c->stash(frameworks => [qw(Catalyst Mojolicious)]); + $c->stash(frameworks => ['Catalyst', 'Mojolicious']); $c->stash(spinoffs => {minion => 'job queue'}); %= $description diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/lib/Mojolicious/Guides/Routing.pod new/Mojolicious-6.42/lib/Mojolicious/Guides/Routing.pod --- old/Mojolicious-6.40/lib/Mojolicious/Guides/Routing.pod 2016-01-09 05:25:41.000000000 +0100 +++ new/Mojolicious-6.42/lib/Mojolicious/Guides/Routing.pod 2016-01-19 19:19:46.000000000 +0100 @@ -156,7 +156,7 @@ =head2 Minimal route The attribute L<Mojolicious/"routes"> contains a router you can use to generate -route structures, they match in the same order in which they were defined. +route structures. # Application package MyApp; @@ -175,7 +175,9 @@ 1; The minimal route above will load and instantiate the class -C<MyApp::Controller::Foo> and call its C<welcome> method. +C<MyApp::Controller::Foo> and call its C<welcome> method. Routes are usually +configured in the C<startup> method of the application class, but the router can +be accessed from everywhere (even at runtime). # Controller package MyApp::Controller::Foo; @@ -191,8 +193,11 @@ 1; -Routes are usually configured in the C<startup> method of the application -class, but the router can be accessed from everywhere (even at runtime). +All routes match in the same order in which they were defined, and matching +stops as soon as a suitable route has been found. So you can improve the routing +performance by declaring your most frequently accessed routes first. A routing +cache will also be used automatically to handle sudden traffic spikes more +gracefully. =head2 Routing destination @@ -224,7 +229,7 @@ $r->post('/hello')->to(controller => 'foo', action => 'hello'); # GET|POST /bye -> {controller => 'foo', action => 'bye'} - $r->any([qw(GET POST)] => '/bye')->to(controller => 'foo', action => 'bye'); + $r->any(['GET', 'POST'] => '/bye')->to(controller => 'foo', action => 'bye'); # * /whatever -> {controller => 'foo', action => 'whatever'} $r->any('/whatever')->to(controller => 'foo', action => 'whatever'); @@ -302,6 +307,10 @@ $cats->get('/nyan')->to(action => 'nyan'); $cats->get('/lol'); +With a few common prefixes you can also greatly improve the routing performance +of applications with many routes, because children are only tried if the prefix +matched first. + =head2 Special stash values When the dispatcher sees C<controller> and C<action> values in the stash it @@ -500,7 +509,7 @@ # /fry -> undef # /bender -> {controller => 'foo', action => 'bar', name => 'bender'} # /leela -> {controller => 'foo', action => 'bar', name => 'leela'} - $r->get('/:name' => [name => [qw(bender leela)]])->to('foo#bar'); + $r->get('/:name' => [name => ['bender', 'leela']])->to('foo#bar'); You can also adjust the regular expressions behind placeholders directly, just make sure not to use C<^> and C<$> or capturing groups C<(...)>, because @@ -595,7 +604,7 @@ # /foo.txt -> undef # /foo.rss -> {controller => 'foo', action => 'bar', format => 'rss'} # /foo.xml -> {controller => 'foo', action => 'bar', format => 'xml'} - $r->get('/foo' => [format => [qw(rss xml)]])->to('foo#bar'); + $r->get('/foo' => [format => ['rss', 'xml']])->to('foo#bar'); A C<format> value can also be passed to L<Mojolicious::Controller/"url_for">. @@ -621,7 +630,7 @@ # /baz.xml -> undef my $inactive = $r->under([format => 0]); $inactive->get('/foo')->to('foo#bar'); - $inactive->get('/baz' => [format => [qw(txt html)]])->to('baz#yada'); + $inactive->get('/baz' => [format => ['txt', 'html']])->to('baz#yada'); =head2 WebSockets diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/lib/Mojolicious/Guides/Tutorial.pod new/Mojolicious-6.42/lib/Mojolicious/Guides/Tutorial.pod --- old/Mojolicious-6.40/lib/Mojolicious/Guides/Tutorial.pod 2016-01-13 19:05:44.000000000 +0100 +++ new/Mojolicious-6.42/lib/Mojolicious/Guides/Tutorial.pod 2016-01-19 19:20:21.000000000 +0100 @@ -7,7 +7,7 @@ =head1 TUTORIAL -A quick example driven introduction to the wonders of L<Mojolicious::Lite>. +A quick example-driven introduction to the wonders of L<Mojolicious::Lite>. Almost everything you'll learn here also applies to full L<Mojolicious> applications. @@ -383,7 +383,7 @@ }; # GET|POST|PATCH /bye - any [qw(GET POST PATCH)] => '/bye' => sub { + any ['GET', 'POST', 'PATCH'] => '/bye' => sub { my $c = shift; $c->render(text => 'Bye World!'); }; @@ -429,7 +429,7 @@ # /test # /123 - any '/:foo' => [foo => [qw(test 123)]] => sub { + any '/:foo' => [foo => ['test', '123']] => sub { my $c = shift; my $foo = $c->param('foo'); $c->render(text => "Our :foo placeholder matched $foo"); @@ -581,7 +581,7 @@ # /hello.json # /hello.txt - get '/hello' => [format => [qw(json txt)]] => sub { + get '/hello' => [format => ['json', 'txt']] => sub { my $c = shift; return $c->render(json => {hello => 'world'}) if $c->stash('format') eq 'json'; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/lib/Mojolicious/Guides.pod new/Mojolicious-6.42/lib/Mojolicious/Guides.pod --- old/Mojolicious-6.40/lib/Mojolicious/Guides.pod 2016-01-10 21:28:01.000000000 +0100 +++ new/Mojolicious-6.42/lib/Mojolicious/Guides.pod 2016-01-24 04:19:02.000000000 +0100 @@ -84,9 +84,9 @@ =head1 HIGHLIGHTS -L<Mojolicious> and L<Mojolicious::Lite> are the sum of many parts, small -building blocks that can be used independently, these are the most prominent -ones. +L<Mojolicious> and L<Mojolicious::Lite> are the sum of many parts, built on top +of the L<Mojo> web development toolkit. Small building blocks that can be used +independently for all kinds of applications, these are the most prominent ones. =over 2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/lib/Mojolicious/Lite.pm new/Mojolicious-6.42/lib/Mojolicious/Lite.pm --- old/Mojolicious-6.40/lib/Mojolicious/Lite.pm 2016-01-09 05:25:41.000000000 +0100 +++ new/Mojolicious-6.42/lib/Mojolicious/Lite.pm 2016-01-19 19:26:47.000000000 +0100 @@ -96,8 +96,8 @@ my $route = any '/:foo' => sub {...}; my $route = any '/:foo' => {foo => 'bar'} => sub {...}; my $route = any '/:foo' => [foo => qr/\w+/] => sub {...}; - my $route = any [qw(GET POST)] => '/:foo' => sub {...}; - my $route = any [qw(GET POST)] => '/:foo' => [foo => qr/\w+/] => sub {...}; + my $route = any ['GET', 'POST'] => '/:foo' => sub {...}; + my $route = any ['GET', 'POST'] => '/:foo' => [foo => qr/\w+/] => sub {...}; Generate route with L<Mojolicious::Routes::Route/"any">, matching any of the listed HTTP request methods or all. See also L<Mojolicious::Guides::Tutorial> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/lib/Mojolicious/Plugin/DefaultHelpers.pm new/Mojolicious-6.42/lib/Mojolicious/Plugin/DefaultHelpers.pm --- old/Mojolicious-6.40/lib/Mojolicious/Plugin/DefaultHelpers.pm 2016-01-09 05:25:41.000000000 +0100 +++ new/Mojolicious-6.42/lib/Mojolicious/Plugin/DefaultHelpers.pm 2016-01-19 19:26:20.000000000 +0100 @@ -219,7 +219,7 @@ =head2 c - %= c(qw(a b c))->shuffle->join + %= c('a', 'b', 'c')->shuffle->join Turn list into a L<Mojo::Collection> object. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/lib/Mojolicious/Plugin/TagHelpers.pm new/Mojolicious-6.42/lib/Mojolicious/Plugin/TagHelpers.pm --- old/Mojolicious-6.40/lib/Mojolicious/Plugin/TagHelpers.pm 2016-01-13 18:54:26.000000000 +0100 +++ new/Mojolicious-6.42/lib/Mojolicious/Plugin/TagHelpers.pm 2016-01-19 19:25:49.000000000 +0100 @@ -553,11 +553,11 @@ =head2 select_field - %= select_field country => [qw(de en)] + %= select_field country => ['de', 'en'] %= select_field country => [[Germany => 'de'], 'en'], id => 'eu' %= select_field country => [[Germany => 'de', selected => 'selected'], 'en'] %= select_field country => [c(EU => [[Germany => 'de'], 'en'], id => 'eu')] - %= select_field country => [c(EU => [qw(de en)]), c(Asia => [qw(cn jp)])] + %= select_field country => [c(EU => ['de', 'en']), c(Asia => ['cn', 'jp'])] Generate C<select> and C<option> tags from array references and C<optgroup> tags from L<Mojo::Collection> objects. Previous input values will automatically diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/lib/Mojolicious/Renderer.pm new/Mojolicious-6.42/lib/Mojolicious/Renderer.pm --- old/Mojolicious-6.40/lib/Mojolicious/Renderer.pm 2016-01-13 19:13:26.000000000 +0100 +++ new/Mojolicious-6.42/lib/Mojolicious/Renderer.pm 2016-01-15 18:01:51.000000000 +0100 @@ -372,12 +372,23 @@ Register a handler. + $renderer->add_handler(foo => sub { + my ($renderer, $c, $output, $options) = @_; + ... + $$output = 'Hello World!'; + }); + =head2 add_helper $renderer = $renderer->add_helper(url_for => sub {...}); Register a helper. + $renderer->add_helper(foo => sub { + my ($c, @args) = @_; + ... + }); + =head2 get_data_template my $template = $renderer->get_data_template({ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/lib/Mojolicious/Routes/Route.pm new/Mojolicious-6.42/lib/Mojolicious/Routes/Route.pm --- old/Mojolicious-6.40/lib/Mojolicious/Routes/Route.pm 2016-01-09 05:25:41.000000000 +0100 +++ new/Mojolicious-6.42/lib/Mojolicious/Routes/Route.pm 2016-01-19 19:21:37.000000000 +0100 @@ -302,8 +302,8 @@ my $route = $r->any('/:foo' => sub {...}); my $route = $r->any('/:foo' => {foo => 'bar'} => sub {...}); my $route = $r->any('/:foo' => [foo => qr/\w+/] => sub {...}); - my $route = $r->any([qw(GET POST)] => '/:foo' => sub {...}); - my $route = $r->any([qw(GET POST)] => '/:foo' => [foo => qr/\w+/]); + my $route = $r->any(['GET', 'POST'] => '/:foo' => sub {...}); + my $route = $r->any(['GET', 'POST'] => '/:foo' => [foo => qr/\w+/]); Generate L<Mojolicious::Routes::Route> object matching any of the listed HTTP request methods or all. See also L<Mojolicious::Guides::Tutorial> for many more @@ -564,14 +564,14 @@ my $methods = $r->via; $r = $r->via('GET'); - $r = $r->via(qw(GET POST)); - $r = $r->via([qw(GET POST)]); + $r = $r->via('GET', 'POST'); + $r = $r->via(['GET', 'POST']); Restrict HTTP methods this route is allowed to handle, defaults to no restrictions. # Route with two methods and destination - $r->route('/foo')->via(qw(GET POST))->to('foo#bar'); + $r->route('/foo')->via('GET', 'POST')->to('foo#bar'); =head2 websocket diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/lib/Mojolicious/Routes.pm new/Mojolicious-6.42/lib/Mojolicious/Routes.pm --- old/Mojolicious-6.40/lib/Mojolicious/Routes.pm 2016-01-09 05:25:41.000000000 +0100 +++ new/Mojolicious-6.42/lib/Mojolicious/Routes.pm 2016-01-19 19:22:21.000000000 +0100 @@ -257,7 +257,7 @@ =head2 hidden my $hidden = $r->hidden; - $r = $r->hidden([qw(attr has new)]); + $r = $r->hidden(['attr', 'has', 'new']); Controller attributes and methods that are hidden from router, defaults to C<attr>, C<has>, C<new> and C<tap>. @@ -290,12 +290,23 @@ Register a condition. + $r->add_condition(foo => sub { + my ($route, $c, $captures, $arg) = @_; + ... + return 1; + }); + =head2 add_shortcut $r = $r->add_shortcut(foo => sub {...}); Register a shortcut. + $r->add_shortcut(foo => sub { + my ($route, @args) = @_; + ... + }); + =head2 continue $r->continue(Mojolicious::Controller->new); @@ -311,7 +322,7 @@ =head2 hide - $r = $r->hide(qw(foo bar)); + $r = $r->hide('foo', 'bar'); Hide controller attributes and methods from router. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/lib/Mojolicious/Types.pm new/Mojolicious-6.42/lib/Mojolicious/Types.pm --- old/Mojolicious-6.40/lib/Mojolicious/Types.pm 2016-01-09 05:25:41.000000000 +0100 +++ new/Mojolicious-6.42/lib/Mojolicious/Types.pm 2016-01-19 19:25:06.000000000 +0100 @@ -140,7 +140,7 @@ my $type = $types->type('png'); $types = $types->type(png => 'image/png'); - $types = $types->type(json => [qw(application/json text/x-json)]); + $types = $types->type(json => ['application/json', 'text/x-json']); Get or set MIME types for file extension, alternatives are only used for detection. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/lib/Mojolicious/Validator/Validation.pm new/Mojolicious-6.42/lib/Mojolicious/Validator/Validation.pm --- old/Mojolicious-6.40/lib/Mojolicious/Validator/Validation.pm 2016-01-09 05:25:41.000000000 +0100 +++ new/Mojolicious-6.42/lib/Mojolicious/Validator/Validation.pm 2016-01-24 00:43:47.000000000 +0100 @@ -64,12 +64,16 @@ sub is_valid { exists $_[0]->output->{$_[1] // $_[0]->topic} } sub optional { - my ($self, $name) = @_; + my ($self, $name, @filters) = @_; - my $input = $self->input->{$name}; - my @input = ref $input eq 'ARRAY' ? @$input : $input; - $self->output->{$name} = $input - unless grep { !defined($_) || $_ eq '' } @input; + return $self->topic($name) unless defined(my $input = $self->input->{$name}); + + my @input = ref $input eq 'ARRAY' ? @$input : ($input); + for my $cb (map { $self->validator->filters->{$_} } @filters) { + @input = map { $self->$cb($name, $_) } @input; + } + $self->output->{$name} = @input > 1 ? \@input : $input[0] + unless grep { $_ eq '' } @input; return $self->topic($name); } @@ -79,8 +83,8 @@ sub passed { [sort keys %{shift->output}] } sub required { - my ($self, $name) = @_; - return $self if $self->optional($name)->is_valid; + my ($self, $name) = (shift, shift); + return $self if $self->optional($name, @_)->is_valid; return $self->error($name => ['required']); } @@ -101,7 +105,7 @@ my $validation = Mojolicious::Validator::Validation->new(validator => $validator); $validation->input({foo => 'bar'}); - $validation->required('foo')->in(qw(bar baz)); + $validation->required('foo')->in('bar', 'baz'); say $validation->param('foo'); =head1 DESCRIPTION @@ -191,7 +195,7 @@ my $names = $validation->failed; -Return a list of all names for values that failed validation. +Return an array reference with all names for values that failed validation. # Names of all values that failed say for @{$validation->failed}; @@ -220,8 +224,12 @@ =head2 optional $validation = $validation->optional('foo'); + $validation = $validation->optional('foo', 'filter1', 'filter2'); + +Change validation L</"topic"> and apply filters. -Change validation L</"topic">. + # Trim value and check size + $validation->optional('user', 'trim')->size(1, 15); =head2 param @@ -234,7 +242,7 @@ my $names = $validation->passed; -Return a list of all names for values that passed validation. +Return an array reference with all names for values that passed validation. # Names of all values that passed say for @{$validation->passed}; @@ -242,9 +250,13 @@ =head2 required $validation = $validation->required('foo'); + $validation = $validation->required('foo', 'filter1', 'filter2'); + +Change validation L</"topic">, apply filters, and make sure a value is present +and not an empty string. -Change validation L</"topic"> and make sure a value is present and not an empty -string. + # Trim value and check size + $validation->required('user', 'trim')->size(1, 15); =head1 AUTOLOAD @@ -255,10 +267,10 @@ # Call validation checks $validation->required('foo')->size(2, 5)->like(qr/^[A-Z]/); $validation->optional('bar')->equal_to('foo'); - $validation->optional('baz')->in(qw(test 123)); + $validation->optional('baz')->in('test', '123'); # Longer version - $validation->required('foo')->check('size', 2,5)->check('like', qr/^[A-Z]/); + $validation->required('foo')->check('size', 2, 5)->check('like', qr/^[A-Z]/); =head1 SEE ALSO diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/lib/Mojolicious/Validator.pm new/Mojolicious-6.42/lib/Mojolicious/Validator.pm --- old/Mojolicious-6.40/lib/Mojolicious/Validator.pm 2016-01-09 05:25:41.000000000 +0100 +++ new/Mojolicious-6.42/lib/Mojolicious/Validator.pm 2016-01-20 06:04:56.000000000 +0100 @@ -1,6 +1,7 @@ package Mojolicious::Validator; use Mojo::Base -base; +use Mojo::Util 'trim'; use Mojolicious::Validator::Validation; has checks => sub { @@ -12,8 +13,10 @@ upload => sub { !ref $_[2] || !$_[2]->isa('Mojo::Upload') } }; }; +has filters => sub { {trim => \&_trim} }; -sub add_check { $_[0]->checks->{$_[1]} = $_[2] and return $_[0] } +sub add_check { $_[0]->checks->{$_[1]} = $_[2] and return $_[0] } +sub add_filter { $_[0]->filters->{$_[1]} = $_[2] and return $_[0] } sub validation { Mojolicious::Validator::Validation->new(validator => shift); @@ -37,6 +40,8 @@ return $len < $min || $len > $max; } +sub _trim { trim $_[2] } + 1; =encoding utf8 @@ -71,7 +76,7 @@ =head2 in - $validation = $validation->in(qw(foo bar baz)); + $validation = $validation->in('foo', 'bar', 'baz'); String value needs to match one of the values in the list. @@ -94,6 +99,17 @@ Value needs to be a L<Mojo::Upload> object, representing a file upload. +=head1 FILTERS + +These filters are available by default. + +=head2 trim + + $validation = $validation->optional('foo', 'trim'); + +Trim whitespace characters from both ends of string value with +L<Mojo::Util/"trim">. + =head1 ATTRIBUTES L<Mojolicious::Validator> implements the following attributes. @@ -117,6 +133,24 @@ Register a validation check. + $validator->add_check(foo => sub { + my ($validation, $name, $value, @args) = @_; + ... + return undef; + }); + +=head2 add_filter + + $validator = $validator->add_filter(trim => sub {...}); + +Register a new filter. + + $validator->add_filter(foo => sub { + my ($validation, $name, $value) = @_; + ... + return $value; + }); + =head2 validation my $validation = $validator->validation; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/lib/Mojolicious.pm new/Mojolicious-6.42/lib/Mojolicious.pm --- old/Mojolicious-6.40/lib/Mojolicious.pm 2016-01-11 19:14:50.000000000 +0100 +++ new/Mojolicious-6.42/lib/Mojolicious.pm 2016-01-20 21:02:19.000000000 +0100 @@ -43,7 +43,7 @@ has validator => sub { Mojolicious::Validator->new }; our $CODENAME = 'Clinking Beer Mugs'; -our $VERSION = '6.40'; +our $VERSION = '6.42'; sub AUTOLOAD { my $self = shift; @@ -523,6 +523,12 @@ return $value ne 'foo'; }); + # Add validation filter + $app->validator->add_filter(quotemeta => sub { + my ($validation, $name, $value) = @_; + return quotemeta $value; + }); + =head1 METHODS L<Mojolicious> inherits all methods from L<Mojo> and implements the following @@ -549,8 +555,8 @@ my $hash = $app->defaults; my $foo = $app->defaults('foo'); - $app = $app->defaults({foo => 'bar'}); - $app = $app->defaults(foo => 'bar'); + $app = $app->defaults({foo => 'bar', baz => 23}); + $app = $app->defaults(foo => 'bar', baz => 23); Default values for L<Mojolicious::Controller/"stash">, assigned for every new request. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/t/mojolicious/validation_lite_app.t new/Mojolicious-6.42/t/mojolicious/validation_lite_app.t --- old/Mojolicious-6.40/t/mojolicious/validation_lite_app.t 2016-01-12 23:31:46.000000000 +0100 +++ new/Mojolicious-6.42/t/mojolicious/validation_lite_app.t 2016-01-24 00:44:26.000000000 +0100 @@ -9,7 +9,7 @@ use Test::Mojo; # Custom check -app->validator->add_check(two => sub { length $_[2] == 2 ? undef : 'ohoh' }); +app->validator->add_check(two => sub { length $_[2] == 2 ? undef : "e:$_[1]" }); any '/' => sub { my $c = shift; @@ -161,6 +161,27 @@ is_deeply $validation->error('bar'), [qw(size 1 1 6)], 'right error'; is_deeply $validation->failed, ['bar'], 'right names'; +# Trim +$validation = $t->app->validation->input({foo => ' bar', baz => [' 0 ', 1]}); +ok $validation->required('foo', 'trim')->in('bar')->is_valid, 'valid'; +is_deeply $validation->output, {foo => 'bar'}, 'right result'; +ok !$validation->optional('missing', 'trim')->is_valid, 'not valid'; +ok $validation->optional('baz', 'trim')->like(qr/^\d$/)->is_valid, 'valid'; +is_deeply $validation->output, {foo => 'bar', baz => [0, 1]}, 'right result'; +$validation = $t->app->validation->input({nothing => ' '}); +ok !$validation->required('nothing', 'trim')->is_valid, 'not valid'; +is_deeply $validation->output, {}, 'right result'; +ok $validation->required('nothing')->is_valid, 'valid'; +is_deeply $validation->output, {nothing => ' '}, 'right result'; + +# Custom filter +$t->app->validator->add_filter(quote => sub {qq{$_[1]="$_[2]"}}); +$validation = $t->app->validation->input({foo => [' bar', 'baz']}); +ok $validation->required('foo', 'trim', 'quote')->like(qr/"/)->is_valid, + 'valid'; +is_deeply $validation->output, {foo => ['foo="bar"', 'foo="baz"']}, + 'right result'; + # Multiple empty values $validation = $t->app->validation; ok !$validation->has_data, 'no data'; @@ -306,7 +327,7 @@ } ); $t->get_ok('/?foo=too_long&bar=too_long_too&baz=way_too_long&yada=whatever') - ->status_is(200)->text_is('div:root' => 'two ohoh') + ->status_is(200)->text_is('div:root' => 'two e:foo') ->text_is('label.custom.my-field-with-error[for="foo"]' => '<Foo>') ->element_exists('input.custom.my-field-with-error[type="text"]') ->element_exists('textarea.my-field-with-error') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.40/t/mojolicious/websocket_lite_app.t new/Mojolicious-6.42/t/mojolicious/websocket_lite_app.t --- old/Mojolicious-6.40/t/mojolicious/websocket_lite_app.t 2016-01-11 06:57:53.000000000 +0100 +++ new/Mojolicious-6.42/t/mojolicious/websocket_lite_app.t 2016-01-19 20:32:25.000000000 +0100 @@ -29,7 +29,7 @@ websocket '/protocols' => sub { my $c = shift; - $c->send($c->tx->with_protocols('foo', 'bar', 'baz') // 'none'); + $c->send($c->tx->with_protocols('foo', 'bar', 'baz', '0') // 'none'); $c->send($c->tx->protocol // 'none'); }; @@ -225,12 +225,20 @@ is $t->tx->protocol, 'foo', 'right protocol'; is $t->tx->res->headers->sec_websocket_protocol, 'foo', 'right "Sec-WebSocket-Protocol" value'; +$t->websocket_ok('/protocols' => ['0'])->message_ok->message_is('0') + ->message_ok->message_is('0')->finish_ok; +is $t->tx->protocol, '0', 'right protocol'; +is $t->tx->res->headers->sec_websocket_protocol, '0', + 'right "Sec-WebSocket-Protocol" value'; $t->websocket_ok('/protocols' => [''])->message_ok->message_is('none') ->message_ok->message_is('none')->finish_ok; is $t->tx->protocol, undef, 'no protocol'; $t->websocket_ok('/protocols' => ['', '', ''])->message_ok->message_is('none') ->message_ok->message_is('none')->finish_ok; is $t->tx->protocol, undef, 'no protocol'; +$t->websocket_ok('/protocols')->message_ok->message_is('none') + ->message_ok->message_is('none')->finish_ok; +is $t->tx->protocol, undef, 'no protocol'; # JSON roundtrips (with a lot of different tests) $t->websocket_ok('/json')->send_ok({json => {test => 23, snowman => '☃'}})
