Hello community, here is the log from the commit of package perl-Mojolicious for openSUSE:Factory checked in at 2015-12-16 17:43:22 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 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 2015-12-09 22:28:13.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.perl-Mojolicious.new/perl-Mojolicious.changes 2015-12-16 17:45:04.000000000 +0100 @@ -1,0 +2,11 @@ +Tue Dec 15 10:08:39 UTC 2015 - co...@suse.com + +- updated to 6.37 + see /usr/share/doc/packages/perl-Mojolicious/Changes + + 6.37 2015-12-14 + - Added protocol and with_protocols methods to Mojo::Transaction::WebSocket. + - Fixed a few reference encoding bugs in Mojo::JSON. + - Fixed a few form generation bugs in Mojo::UserAgent::Transactor. + +------------------------------------------------------------------- Old: ---- Mojolicious-6.36.tar.gz New: ---- Mojolicious-6.37.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ perl-Mojolicious.spec ++++++ --- /var/tmp/diff_new_pack.lNadue/_old 2015-12-16 17:45:05.000000000 +0100 +++ /var/tmp/diff_new_pack.lNadue/_new 2015-12-16 17:45:05.000000000 +0100 @@ -17,7 +17,7 @@ Name: perl-Mojolicious -Version: 6.36 +Version: 6.37 Release: 0 %define cpan_name Mojolicious Summary: Real-time web framework ++++++ Mojolicious-6.36.tar.gz -> Mojolicious-6.37.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.36/Changes new/Mojolicious-6.37/Changes --- old/Mojolicious-6.36/Changes 2015-12-08 15:54:16.000000000 +0100 +++ new/Mojolicious-6.37/Changes 2015-12-14 23:39:03.000000000 +0100 @@ -1,4 +1,9 @@ +6.37 2015-12-14 + - Added protocol and with_protocols methods to Mojo::Transaction::WebSocket. + - Fixed a few reference encoding bugs in Mojo::JSON. + - Fixed a few form generation bugs in Mojo::UserAgent::Transactor. + 6.36 2015-12-08 - Improved Mojo::JSON performance slightly. (haarg) - Improved inactivity_timeout helper to return the current controller object. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.36/MANIFEST new/Mojolicious-6.37/MANIFEST --- old/Mojolicious-6.36/MANIFEST 2015-12-09 02:09:49.000000000 +0100 +++ new/Mojolicious-6.37/MANIFEST 2015-12-15 01:34:59.000000000 +0100 @@ -166,6 +166,7 @@ t/mojo/cookie.t t/mojo/cookiejar.t t/mojo/daemon.t +t/mojo/daemon_ipv6_tls.t t/mojo/date.t t/mojo/delay.t t/mojo/dom.t diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.36/META.json new/Mojolicious-6.37/META.json --- old/Mojolicious-6.36/META.json 2015-12-09 02:09:49.000000000 +0100 +++ new/Mojolicious-6.37/META.json 2015-12-15 01:34:58.000000000 +0100 @@ -58,5 +58,5 @@ }, "x_IRC" : "irc://irc.perl.org/#mojo" }, - "version" : "6.36" + "version" : "6.37" } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.36/META.yml new/Mojolicious-6.37/META.yml --- old/Mojolicious-6.36/META.yml 2015-12-09 02:09:49.000000000 +0100 +++ new/Mojolicious-6.37/META.yml 2015-12-15 01:34:58.000000000 +0100 @@ -31,4 +31,4 @@ homepage: http://mojolicio.us license: http://www.opensource.org/licenses/artistic-license-2.0 repository: https://github.com/kraih/mojo.git -version: '6.36' +version: '6.37' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.36/lib/Mojo/JSON.pm new/Mojolicious-6.37/lib/Mojo/JSON.pm --- old/Mojolicious-6.36/lib/Mojo/JSON.pm 2015-12-06 14:19:31.000000000 +0100 +++ new/Mojolicious-6.37/lib/Mojo/JSON.pm 2015-12-14 23:39:03.000000000 +0100 @@ -239,10 +239,10 @@ return $$value ? 'true' : 'false' if $ref eq 'SCALAR'; return $value ? 'true' : 'false' if $ref eq 'JSON::PP::Boolean'; - # Blessed reference with TO_JSON method - if (blessed $value && (my $sub = $value->can('TO_JSON'))) { - return _encode_value($value->$sub); - } + # Everything else + return _encode_string($value) + unless blessed $value && (my $sub = $value->can('TO_JSON')); + return _encode_value($value->$sub); } # Null diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.36/lib/Mojo/Server/Daemon.pm new/Mojolicious-6.37/lib/Mojo/Server/Daemon.pm --- old/Mojolicious-6.36/lib/Mojo/Server/Daemon.pm 2015-11-30 17:53:49.000000000 +0100 +++ new/Mojolicious-6.37/lib/Mojo/Server/Daemon.pm 2015-12-14 23:39:03.000000000 +0100 @@ -135,11 +135,10 @@ } # Close connection if necessary - my $req = $tx->req; - return $self->_remove($id) if $req->error || !$tx->keep_alive; + return $self->_remove($id) if $tx->error || !$tx->keep_alive; # Build new transaction for leftovers - return if (my $leftovers = $req->content->leftovers) eq ''; + return if (my $leftovers = $tx->req->content->leftovers) eq ''; $tx = $c->{tx} = $self->_build_tx($id, $c); $tx->server_read($leftovers); } @@ -193,7 +192,7 @@ my ($self, $id, $chunk) = @_; # Make sure we have a transaction and parse chunk - return unless my $c = $self->{connections}{$id}; + my $c = $self->{connections}{$id}; my $tx = $c->{tx} ||= $self->_build_tx($id, $c); warn term_escape "-- Server <<< Client (@{[_url($tx)]})\n$chunk\n" if DEBUG; $tx->server_read($chunk); @@ -219,7 +218,7 @@ my ($self, $id) = @_; # Get chunk and write - return unless my $c = $self->{connections}{$id}; + my $c = $self->{connections}{$id}; return unless my $tx = $c->{tx}; return if !$tx->is_writing || $c->{writing}++; my $chunk = $tx->server_write; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.36/lib/Mojo/Transaction/WebSocket.pm new/Mojolicious-6.37/lib/Mojo/Transaction/WebSocket.pm --- old/Mojolicious-6.36/lib/Mojo/Transaction/WebSocket.pm 2015-12-08 15:53:47.000000000 +0100 +++ new/Mojolicious-6.37/lib/Mojo/Transaction/WebSocket.pm 2015-12-14 23:39:03.000000000 +0100 @@ -3,9 +3,10 @@ use Compress::Raw::Zlib 'Z_SYNC_FLUSH'; use Config; +use List::Util 'first'; use Mojo::JSON qw(encode_json j); use Mojo::Transaction::HTTP; -use Mojo::Util qw(b64_encode decode dumper encode sha1_bytes xor_encode); +use Mojo::Util qw(b64_encode decode dumper encode sha1_bytes trim xor_encode); use constant DEBUG => $ENV{MOJO_WEBSOCKET_DEBUG} || 0; @@ -209,6 +210,8 @@ return [$fin, $rsv1, $rsv2, $rsv3, $op, $payload]; } +sub protocol { shift->res->headers->sec_websocket_protocol } + sub remote_address { shift->handshake->remote_address } sub remote_port { shift->handshake->remote_port } sub req { shift->handshake->req } @@ -276,6 +279,17 @@ =~ /permessage-deflate/; } +sub with_protocols { + my $self = shift; + + my %protos = map { trim($_) => 1 } split ',', + $self->req->headers->sec_websocket_protocol; + return undef unless my $proto = first { $protos{$_} } @_; + + $self->res->headers->sec_websocket_protocol($proto); + return $proto; +} + sub _challenge { b64_encode(sha1_bytes(($_[0] || '') . GUID), '') } sub _message { @@ -631,6 +645,12 @@ say "Opcode: $frame->[4]"; say "Payload: $frame->[5]"; +=head2 protocol + + my $proto = $ws->protocol; + +Return negotiated subprotocol or C<undef>. + =head2 remote_address my $address = $ws->remote_address; @@ -717,6 +737,12 @@ Negotiate C<permessage-deflate> extension for this WebSocket connection. +=head2 with_protocols + + my $proto = $ws->with_protocols('v2.proto', 'v1.proto'); + +Negotiate subprotocol for this WebSocket connection. + =head1 DEBUGGING You can set the C<MOJO_WEBSOCKET_DEBUG> environment variable to get some diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.36/lib/Mojo/UserAgent/Transactor.pm new/Mojolicious-6.37/lib/Mojo/UserAgent/Transactor.pm --- old/Mojolicious-6.36/lib/Mojo/UserAgent/Transactor.pm 2015-11-20 00:08:51.000000000 +0100 +++ new/Mojolicious-6.37/lib/Mojo/UserAgent/Transactor.pm 2015-12-14 23:39:03.000000000 +0100 @@ -170,12 +170,12 @@ } # Query parameters or urlencoded - my $p = Mojo::Parameters->new(map { $_ => $form->{$_} } sort keys %$form); - $p->charset($options{charset}) if defined $options{charset}; my $method = uc $req->method; - if ($method eq 'GET' || $method eq 'HEAD') { $req->url->query($p) } + my @form = map { $_ => $form->{$_} } sort keys %$form; + if ($method eq 'GET' || $method eq 'HEAD') { $req->url->query->merge(@form) } else { - $req->body($p->to_string); + $req->body( + Mojo::Parameters->new(@form)->charset($options{charset})->to_string); _type($headers, 'application/x-www-form-urlencoded'); } return $tx; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.36/lib/Mojo/UserAgent.pm new/Mojolicious-6.37/lib/Mojo/UserAgent.pm --- old/Mojolicious-6.36/lib/Mojo/UserAgent.pm 2015-12-03 14:48:26.000000000 +0100 +++ new/Mojolicious-6.37/lib/Mojo/UserAgent.pm 2015-12-14 23:39:03.000000000 +0100 @@ -51,12 +51,12 @@ # Non-blocking if ($cb) { warn "-- Non-blocking request (@{[_url($tx)]})\n" if DEBUG; - return $self->_start(1, $tx, $cb); + return $self->_start(Mojo::IOLoop->singleton, $tx, $cb); } # Blocking warn "-- Blocking request (@{[_url($tx)]})\n" if DEBUG; - $self->_start(0, $tx => sub { shift->ioloop->stop; $tx = shift }); + $self->_start($self->ioloop, $tx => sub { shift->ioloop->stop; $tx = shift }); $self->ioloop->start; return $tx; @@ -70,22 +70,13 @@ sub _cleanup { my $self = shift; - - # Clean up active connections (by closing them) delete $self->{pid}; $self->_finish($_, 1) for keys %{$self->{connections} || {}}; - - # Clean up keep-alive connections - my $loop = $self->_loop(0); - $loop->remove($_->[1]) for @{delete $self->{queue} || []}; - $loop = $self->_loop(1); - $loop->remove($_->[1]) for @{delete $self->{nb_queue} || []}; - return $self; } sub _connect { - my ($self, $nb, $peer, $tx, $handle, $cb) = @_; + my ($self, $loop, $peer, $tx, $handle, $cb) = @_; my $t = $self->transactor; my ($proto, $host, $port) = $peer ? $t->peer($tx) : $t->endpoint($tx); @@ -108,7 +99,7 @@ weaken $self; my $id; - return $id = $self->_loop($nb)->client( + return $id = $loop->client( %options => sub { my ($loop, $err, $stream) = @_; @@ -127,12 +118,12 @@ } sub _connect_proxy { - my ($self, $nb, $old, $cb) = @_; + my ($self, $loop, $old, $cb) = @_; # Start CONNECT request return undef unless my $new = $self->transactor->proxy_connect($old); return $self->_start( - ($nb, $new) => sub { + ($loop, $new) => sub { my ($self, $tx) = @_; # CONNECT failed (connection needs to be kept alive) @@ -143,16 +134,15 @@ # Start real transaction $old->req->via_proxy(0); my $id = $tx->connection; - return $self->_start($nb, $old->connection($id), $cb) + return $self->_start($loop, $old->connection($id), $cb) unless $tx->req->url->protocol eq 'https'; # TLS upgrade - my $loop = $self->_loop($nb); my $handle = $loop->stream($id)->steal_handle; - $loop->remove($id); - $id = $self->_connect($nb, 0, $old, $handle, - sub { shift->_start($nb, $old->connection($id), $cb) }); - $self->{connections}{$id} = {cb => $cb, nb => $nb, tx => $old}; + $self->_remove($id); + $id = $self->_connect($loop, 0, $old, $handle, + sub { shift->_start($loop, $old->connection($id), $cb) }); + $self->{connections}{$id} = {cb => $cb, ioloop => $loop, tx => $old}; } ); } @@ -161,9 +151,8 @@ my ($self, $id) = @_; # Inactivity timeout - my $c = $self->{connections}{$id}; - my $stream - = $self->_loop($c->{nb})->stream($id)->timeout($self->inactivity_timeout); + my $c = $self->{connections}{$id}; + my $stream = $c->{ioloop}->stream($id)->timeout($self->inactivity_timeout); # Store connection information in transaction my $tx = $c->{tx}->connection($id); @@ -178,35 +167,34 @@ } sub _connection { - my ($self, $nb, $tx, $cb) = @_; + my ($self, $loop, $tx, $cb) = @_; # Reuse connection my ($proto, $host, $port) = $self->transactor->endpoint($tx); - my $id = $tx->connection || $self->_dequeue($nb, "$proto:$host:$port", 1); + my $id = $tx->connection || $self->_dequeue($loop, "$proto:$host:$port", 1); if ($id) { warn "-- Reusing connection $id ($proto://$host:$port)\n" if DEBUG; - $self->{connections}{$id} = {cb => $cb, nb => $nb, tx => $tx}; + @{$self->{connections}{$id}}{qw(cb tx)} = ($cb, $tx); $tx->kept_alive(1) unless $tx->connection; $self->_connected($id); return $id; } # CONNECT request to proxy required - if (my $id = $self->_connect_proxy($nb, $tx, $cb)) { return $id } + if (my $id = $self->_connect_proxy($loop, $tx, $cb)) { return $id } # Connect - $id = $self->_connect($nb, 1, $tx, undef, \&_connected); + $id = $self->_connect($loop, 1, $tx, undef, \&_connected); warn "-- Connect $id ($proto://$host:$port)\n" if DEBUG; - $self->{connections}{$id} = {cb => $cb, nb => $nb, tx => $tx}; + $self->{connections}{$id} = {cb => $cb, ioloop => $loop, tx => $tx}; return $id; } sub _dequeue { - my ($self, $nb, $name, $test) = @_; + my ($self, $loop, $name, $test) = @_; - my $loop = $self->_loop($nb); - my $old = $self->{$nb ? 'nb_queue' : 'queue'} ||= []; + my $old = $self->{queue}{$loop} ||= []; my ($found, @new); for my $queued (@$old) { push @new, $queued and next if $found || !grep { $_ eq $name } @$queued; @@ -220,16 +208,6 @@ return $found; } -sub _enqueue { - my ($self, $nb, $name, $id) = @_; - - # Enforce connection limit - my $queue = $self->{$nb ? 'nb_queue' : 'queue'} ||= []; - my $max = $self->max_connections; - $self->_remove(shift(@$queue)->[1]) while @$queue && @$queue >= $max; - $max ? push @$queue, [$name, $id] : $self->_loop($nb)->stream($id)->close; -} - sub _error { my ($self, $id, $err) = @_; my $tx = $self->{connections}{$id}{tx}; @@ -242,14 +220,13 @@ # Remove request timeout return unless my $c = $self->{connections}{$id}; - my $loop = $self->_loop($c->{nb}); - $loop->remove($c->{timeout}) if $c->{timeout}; + $c->{ioloop}->remove($c->{timeout}) if $c->{timeout}; - return $self->_remove($id, $close) unless my $old = $c->{tx}; + return $self->_reuse($id, $close) unless my $old = $c->{tx}; $old->client_close($close); # Finish WebSocket - return $self->_remove($id, 1) if $old->is_websocket; + return $self->_remove($id) if $old->is_websocket; $self->cookie_jar->collect($old); @@ -262,18 +239,15 @@ } # Finish normal connection and handle redirects - $self->_remove($id, $close); + $self->_reuse($id, $close); $c->{cb}($self, $old) unless $self->_redirect($c, $old); } -sub _loop { $_[1] ? Mojo::IOLoop->singleton : $_[0]->ioloop } - sub _read { my ($self, $id, $chunk) = @_; # Corrupted connection - return unless my $c = $self->{connections}{$id}; - return $self->_remove($id) unless my $tx = $c->{tx}; + return $self->_remove($id) unless my $tx = $self->{connections}{$id}{tx}; # Process incoming data warn term_escape "-- Client <<< Server (@{[_url($tx)]})\n$chunk\n" if DEBUG; @@ -286,41 +260,51 @@ my ($self, $c, $old) = @_; return undef unless my $new = $self->transactor->redirect($old); return undef unless @{$old->redirects} < $self->max_redirects; - return $self->_start($c->{nb}, $new, delete $c->{cb}); + return $self->_start($c->{ioloop}, $new, delete $c->{cb}); } sub _remove { + my ($self, $id) = @_; + my $c = delete $self->{connections}{$id}; + $self->_dequeue($c->{ioloop}, $id); + $c->{ioloop}->remove($id); +} + +sub _reuse { my ($self, $id, $close) = @_; - # Close connection - my $c = delete $self->{connections}{$id} || {}; - my $tx = $c->{tx}; - return map { $self->_dequeue($_, $id); $self->_loop($_)->remove($id) } 1, 0 - if $close || !$tx || !$tx->keep_alive || $tx->error; - - # Keep connection alive (CONNECT requests get upgraded) - $self->_enqueue($c->{nb}, join(':', $self->transactor->endpoint($tx)), $id) - unless uc $tx->req->method eq 'CONNECT'; + # Connection close + my $c = $self->{connections}{$id}; + my $tx = delete $c->{tx}; + my $max = $self->max_connections; + return $self->_remove($id) + if $close || !$tx || !$max || !$tx->keep_alive || $tx->error; + + # Keep connection alive + my $queue = $self->{queue}{$c->{ioloop}} ||= []; + $self->_remove(shift(@$queue)->[1]) while @$queue && @$queue >= $max; + push @$queue, [join(':', $self->transactor->endpoint($tx)), $id]; } sub _start { - my ($self, $nb, $tx, $cb) = @_; + my ($self, $loop, $tx, $cb) = @_; # Application server my $url = $tx->req->url; unless ($url->is_abs) { - my $base = $nb ? $self->server->nb_url : $self->server->url; + my $base + = $loop == $self->ioloop ? $self->server->url : $self->server->nb_url; $url->scheme($base->scheme)->authority($base->authority); } $_->prepare($tx) for $self->proxy, $self->cookie_jar; # Connect and add request timeout if necessary - my $id = $self->emit(start => $tx)->_connection($nb, $tx, $cb); + my $id = $self->emit(start => $tx)->_connection($loop, $tx, $cb); if (my $timeout = $self->request_timeout) { weaken $self; - $self->{connections}{$id}{timeout} = $self->_loop($nb) - ->timer($timeout => sub { $self->_error($id, 'Request timeout') }); + $self->{connections}{$id}{timeout} + = $loop->timer($timeout => sub { $self->_error($id, 'Request timeout') }); } return $id; @@ -332,13 +316,13 @@ my ($self, $id) = @_; # Get and write chunk - return unless my $c = $self->{connections}{$id}; + my $c = $self->{connections}{$id}; return unless my $tx = $c->{tx}; return if !$tx->is_writing || $c->{writing}++; my $chunk = $tx->client_write; delete $c->{writing}; warn term_escape "-- Client >>> Server (@{[_url($tx)]})\n$chunk\n" if DEBUG; - my $stream = $self->_loop($c->{nb})->stream($id)->write($chunk); + my $stream = $c->{ioloop}->stream($id)->write($chunk); $self->_finish($id) if $tx->is_finished; # Continue writing diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.36/lib/Mojolicious/Static.pm new/Mojolicious-6.37/lib/Mojolicious/Static.pm --- old/Mojolicious-6.36/lib/Mojolicious/Static.pm 2015-11-17 05:42:32.000000000 +0100 +++ new/Mojolicious-6.37/lib/Mojolicious/Static.pm 2015-12-14 23:39:03.000000000 +0100 @@ -57,7 +57,7 @@ my $res_headers = $c->res->headers; my ($last, $etag) = @$options{qw(last_modified etag)}; - $res_headers->last_modified(Mojo::Date->new($last)) if $last; + $res_headers->last_modified(Mojo::Date->new($last)->to_string) if $last; $res_headers->etag($etag = qq{"$etag"}) if $etag; # Unconditional diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.36/lib/Mojolicious.pm new/Mojolicious-6.37/lib/Mojolicious.pm --- old/Mojolicious-6.36/lib/Mojolicious.pm 2015-12-04 18:47:14.000000000 +0100 +++ new/Mojolicious-6.37/lib/Mojolicious.pm 2015-12-14 23:39:03.000000000 +0100 @@ -43,7 +43,7 @@ has validator => sub { Mojolicious::Validator->new }; our $CODENAME = 'Clinking Beer Mugs'; -our $VERSION = '6.36'; +our $VERSION = '6.37'; sub AUTOLOAD { my $self = shift; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.36/t/mojo/daemon_ipv6_tls.t new/Mojolicious-6.37/t/mojo/daemon_ipv6_tls.t --- old/Mojolicious-6.36/t/mojo/daemon_ipv6_tls.t 1970-01-01 01:00:00.000000000 +0100 +++ new/Mojolicious-6.37/t/mojo/daemon_ipv6_tls.t 2015-12-14 23:39:03.000000000 +0100 @@ -0,0 +1,38 @@ +use Mojo::Base -strict; + +BEGIN { $ENV{MOJO_REACTOR} = 'Mojo::Reactor::Poll' } + +use Test::More; +use Mojo::IOLoop::Server; + +plan skip_all => 'set TEST_IPV6 to enable this test (developer only!)' + unless $ENV{TEST_IPV6}; +plan skip_all => 'set TEST_TLS to enable this test (developer only!)' + unless $ENV{TEST_TLS}; +plan skip_all => 'IO::Socket::SSL 1.94+ required for this test!' + unless Mojo::IOLoop::Server::TLS; + +use Mojo::IOLoop; +use Mojo::Server::Daemon; +use Mojo::UserAgent; +use Mojolicious::Lite; + +# Silence +app->log->level('fatal'); + +get '/' => {text => 'works!'}; + +# IPv6 and TLS +my $daemon = Mojo::Server::Daemon->new( + app => app, + listen => ['https://[::1]'], + silent => 1 +); +$daemon->start; +my $port = Mojo::IOLoop->acceptor($daemon->acceptors->[0])->port; +my $ua = Mojo::UserAgent->new(ioloop => Mojo::IOLoop->singleton); +my $tx = $ua->get("https://[::1]:$port/"); +is $tx->res->code, 200, 'right status'; +is $tx->res->body, 'works!', 'right content'; + +done_testing(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.36/t/mojo/json.t new/Mojolicious-6.37/t/mojo/json.t --- old/Mojolicious-6.36/t/mojo/json.t 2015-11-17 05:38:54.000000000 +0100 +++ new/Mojolicious-6.37/t/mojo/json.t 2015-12-14 23:39:03.000000000 +0100 @@ -5,6 +5,10 @@ sub TO_JSON { shift->something } +package JSONTest2; +use Mojo::Base -base; +use overload '&' => sub {die}, '""' => sub {'works!'}; + package main; use Mojo::Base -strict; @@ -311,6 +315,11 @@ my $dual = dualvar 23, 'twenty three'; is encode_json([$dual]), '["twenty three"]', 'dualvar stringified'; +# Other reference types +my $sub = sub { }; +is encode_json([$sub]), "[\"$sub\"]", 'code reference stringified'; +is encode_json([JSONTest2->new]), "[\"works!\"]", 'object stringified'; + # Ensure numbers and strings are not upgraded my $mixed = [3, 'three', '3', 0, "0"]; is encode_json($mixed), '[3,"three","3",0,"0"]', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.36/t/mojo/transactor.t new/Mojolicious-6.37/t/mojo/transactor.t --- old/Mojolicious-6.36/t/mojo/transactor.t 2015-11-17 05:39:04.000000000 +0100 +++ new/Mojolicious-6.37/t/mojo/transactor.t 2015-12-14 23:39:03.000000000 +0100 @@ -130,33 +130,45 @@ # Existing query string (lowercase HEAD) $tx = $t->tx(head => 'http://example.com?foo=bar' => form => {baz => [1, 2]}); -is $tx->req->url->to_abs, 'http://example.com?baz=1&baz=2', 'right URL'; +is $tx->req->url->to_abs, 'http://example.com?foo=bar&baz=1&baz=2', 'right URL'; is $tx->req->method, 'head', 'right method'; is $tx->req->headers->content_type, undef, 'no "Content-Type" value'; ok $tx->is_empty, 'transaction is empty'; is $tx->req->body, '', 'no content'; -# UTF-8 form +# UTF-8 query $tx - = $t->tx(POST => 'http://example.com/foo' => form => {test => 12345678912} => + = $t->tx( + GET => 'http://example.com/foo' => form => {a => '☃', b => '♥'} => charset => 'UTF-8'); +is $tx->req->url->to_abs, 'http://example.com/foo?a=%E2%98%83&b=%E2%99%A5', + 'right URL'; +is $tx->req->method, 'GET', 'right method'; +is $tx->req->headers->content_type, undef, 'no "Content-Type" value'; +is $tx->req->body, '', 'no content'; + +# UTF-8 form +$tx + = $t->tx( + POST => 'http://example.com/foo' => form => {'♥' => '☃'} => charset => + 'UTF-8'); is $tx->req->url->to_abs, 'http://example.com/foo', 'right URL'; is $tx->req->method, 'POST', 'right method'; is $tx->req->headers->content_type, 'application/x-www-form-urlencoded', 'right "Content-Type" value'; -is $tx->req->body, 'test=12345678912', 'right content'; +is $tx->req->body, '%E2%99%A5=%E2%98%83', 'right content'; # UTF-8 form with header and custom content type $tx = $t->tx(POST => 'http://example.com/foo' => {Accept => '*/*', 'Content-Type' => 'application/mojo-form'} => form => - {test => 123, nothing => undef} => charset => 'UTF-8'); + {'♥' => '☃', nothing => undef} => charset => 'UTF-8'); is $tx->req->url->to_abs, 'http://example.com/foo', 'right URL'; is $tx->req->method, 'POST', 'right method'; is $tx->req->headers->content_type, 'application/mojo-form', 'right "Content-Type" value'; is $tx->req->headers->accept, '*/*', 'right "Accept" value'; -is $tx->req->body, 'test=123', 'right content'; +is $tx->req->body, '%E2%99%A5=%E2%98%83', 'right content'; # Multipart form $tx diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.36/t/mojo/user_agent.t new/Mojolicious-6.37/t/mojo/user_agent.t --- old/Mojolicious-6.36/t/mojo/user_agent.t 2015-12-07 16:24:09.000000000 +0100 +++ new/Mojolicious-6.37/t/mojo/user_agent.t 2015-12-14 23:39:03.000000000 +0100 @@ -131,14 +131,14 @@ is $body, 'works!', 'right content'; # SOCKS proxy request without SOCKS support -$ua = Mojo::UserAgent->new(ioloop => Mojo::IOLoop->singleton); +$ua = Mojo::UserAgent->new; my $tx = $ua->build_tx(GET => '/'); $tx->req->proxy($ua->server->url->scheme('socks')); $tx = $ua->start($tx); like $tx->error->{message}, qr/IO::Socket::Socks/, 'right error'; # HTTPS request without TLS support -$ua = Mojo::UserAgent->new(ioloop => Mojo::IOLoop->singleton); +$ua = Mojo::UserAgent->new; $tx = $ua->get($ua->server->url->scheme('https')); like $tx->error->{message}, qr/IO::Socket::SSL/, 'right error'; @@ -308,6 +308,7 @@ is $body, '{"hello":"world"}', 'right content'; # Built-in web server times out +$ua = Mojo::UserAgent->new(ioloop => Mojo::IOLoop->singleton); my $log = ''; my $msg = app->log->on(message => sub { $log .= pop }); $tx = $ua->get('/timeout?timeout=0.25'); @@ -383,6 +384,7 @@ # Fork-safety $tx = $ua->get('/'); +ok $tx->keep_alive, 'keep connection alive'; is $tx->res->body, 'works!', 'right content'; my $last = $tx->connection; my $port = $ua->server->url->port; @@ -393,12 +395,16 @@ { local $$ = -23; $tx = $ua->get('/'); + ok !$tx->kept_alive, 'kept connection not alive'; + ok $tx->keep_alive, 'keep connection alive'; is $tx->res->body, 'works!', 'right content'; isnt $tx->connection, $last, 'new connection'; isnt $ua->server->url->port, $port, 'new port'; $port = $ua->server->url->port; $last = $tx->connection; $tx = $ua->get('/'); + ok $tx->kept_alive, 'kept connection alive'; + ok $tx->keep_alive, 'keep connection alive'; is $tx->res->body, 'works!', 'right content'; is $tx->connection, $last, 'same connection'; is $ua->server->url->port, $port, 'same port'; @@ -476,7 +482,14 @@ is $tx->res->body, '0123456789', 'right content'; is $stream, 1, 'no leaking subscribers'; -# Nested non-blocking requests after blocking one, with custom URL +# Mixed blocking and non-blocking requests, with custom URL +$ua = Mojo::UserAgent->new(ioloop => Mojo::IOLoop->singleton); +$tx = $ua->get($ua->server->url); +ok $tx->success, 'successful'; +ok !$tx->kept_alive, 'kept connection not alive'; +ok $tx->keep_alive, 'keep connection alive'; +is $tx->res->code, 200, 'right status'; +is $tx->res->body, 'works!', 'right content'; my @kept_alive; $ua->get( $ua->server->nb_url => sub { @@ -499,6 +512,12 @@ ); Mojo::IOLoop->start; is_deeply \@kept_alive, [undef, 1, 1], 'connections kept alive'; +$tx = $ua->get($ua->server->url); +ok $tx->success, 'successful'; +ok $tx->kept_alive, 'kept connection alive'; +ok $tx->keep_alive, 'keep connection alive'; +is $tx->res->code, 200, 'right status'; +is $tx->res->body, 'works!', 'right content'; # Simple nested non-blocking requests with timers @kept_alive = (); @@ -520,13 +539,6 @@ Mojo::IOLoop->start; is_deeply \@kept_alive, [1, 1], 'connections kept alive'; -# Blocking request after non-blocking one, with custom URL -$tx = $ua->get($ua->server->url); -ok $tx->success, 'successful'; -ok $tx->kept_alive, 'kept connection alive'; -is $tx->res->code, 200, 'right status'; -is $tx->res->body, 'works!', 'right content'; - # Unexpected 1xx responses $req = Mojo::Message::Request->new; $id = Mojo::IOLoop->server( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.36/t/mojo/user_agent_online.t new/Mojolicious-6.37/t/mojo/user_agent_online.t --- old/Mojolicious-6.36/t/mojo/user_agent_online.t 2015-11-17 05:39:06.000000000 +0100 +++ new/Mojolicious-6.37/t/mojo/user_agent_online.t 2015-12-14 23:39:03.000000000 +0100 @@ -183,24 +183,12 @@ ok $tx->keep_alive, 'connection will be kept alive'; ok $tx->kept_alive, 'connection was kept alive'; -# Request that requires IPv6 -$tx = $ua->get('http://ipv6.google.com'); -is $tx->req->method, 'GET', 'right method'; -is $tx->req->url, 'http://ipv6.google.com', 'right url'; -is $tx->res->code, 200, 'right status'; - # Simple HTTPS request $tx = $ua->get('https://metacpan.org'); is $tx->req->method, 'GET', 'right method'; is $tx->req->url, 'https://metacpan.org', 'right url'; is $tx->res->code, 200, 'right status'; -# HTTPS request that requires IPv6 -$tx = $ua->get('https://ipv6.google.com'); -is $tx->req->method, 'GET', 'right method'; -is $tx->req->url, 'https://ipv6.google.com', 'right url'; -is $tx->res->code, 200, 'right status'; - # HTTPS request that requires SNI SKIP: { skip 'SNI support required!', 1 unless IO::Socket::SSL->can_client_sni; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Mojolicious-6.36/t/mojolicious/websocket_lite_app.t new/Mojolicious-6.37/t/mojolicious/websocket_lite_app.t --- old/Mojolicious-6.36/t/mojolicious/websocket_lite_app.t 2015-11-17 05:39:25.000000000 +0100 +++ new/Mojolicious-6.37/t/mojolicious/websocket_lite_app.t 2015-12-14 23:39:03.000000000 +0100 @@ -27,6 +27,12 @@ $c->on(binary => sub { shift->send({binary => shift}) }); }; +websocket '/protocols' => sub { + my $c = shift; + $c->send($c->tx->with_protocols('foo', 'bar', 'baz') // 'none'); + $c->send($c->tx->protocol // 'none'); +}; + websocket '/json' => sub { my $c = shift; $c->on( @@ -208,6 +214,24 @@ ->send_ok({binary => $huge})->message_ok->message_is({binary => $huge}) ->finish_ok; +# Protocol negotiation +$t->websocket_ok('/protocols' => ['bar'])->message_ok->message_is('bar') + ->message_ok->message_is('bar')->finish_ok; +is $t->tx->protocol, 'bar', 'right protocol'; +is $t->tx->res->headers->sec_websocket_protocol, 'bar', + 'right "Sec-WebSocket-Protocol" value'; +$t->websocket_ok('/protocols' => ['baz', 'bar', 'foo']) + ->message_ok->message_is('foo')->message_ok->message_is('foo')->finish_ok; +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' => [''])->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 => '☃'}}) ->message_ok->json_message_is('' => {test => 24, snowman => '☃'})