-
Notifications
You must be signed in to change notification settings - Fork 580
Upgrading
NOTE: This community-maintained page may be out-of-date and should not be solely relied upon for completeness. If you find missing information or discrepancies you are welcome to edit this document or discuss it with us.
Formats would previously be detected and removed from any request path with a file extension, unless disabled for a set of routes with [format => 0]
, or unless formats are explicitly listed. Since Mojolicious now considers failure to find a template for a requested format a server error, this can allow clients to cause excess error logging in a production application.
This default is now changed so automatic format detection is disabled by default, and can be enabled for a set of routes with [format => 1]
. Like [format => 0]
, this will be inherited by nested routes, but this feature is overly magical and may be removed completely in the future.
my $active = $r->any([format => 1]); # automatic format detection enabled in this and nested routes
$active->get('/foo')->to('Test#first');
$active->put('/bar')->to('Test#second');
You are encouraged to explicitly declare allowed formats in each route if you want to use format detection without the magic (these are also inherited in Mojolicious 9.16+). Use the normal mechanism for optional placeholders to make the format optional.
$r->get('/foo' => [format => ['html', 'json']])->to('bar#yada'); # /foo.html, /foo.json
$r->get('/foo' => [format => ['html', 'json']])->to('bar#yada', format => undef); # /foo, /foo.html, /foo.json
Reserved stash values previously could be set from route parameters directly. This either was used to set controller
and action
as a discouraged form of semi-dynamic routing (/foo/:controller/:action
), or was done accidentally and led to strange behavior and errors (/foo/:text
). Attempting to use reserved stash value names as parameters now results in an error.
This also means that methods no longer need to be hidden from the router to prevent it from using them as actions, so the hidden
attribute of Mojolicious::Routes
has been removed.
Instead of routing to controllers and actions dynamically through route parameters, consider iterating through your controllers and actions explicitly to add such routes, or using a routing schema such as with Mojolicious::Plugin::OpenAPI.
The 'plugins' key in a configuration file read by Mojolicious::Plugin::Config, or the other core config plugins, will now be used to load deployment specific plugins. This means this top-level key is now reserved in configuration and should not be used for other purposes.
Mojolicious::Plugin::Config and the other core config plugins used to set the reserved stash value 'config' to the application config, for use in templates as $config
. This is no longer done and the application config can be accessed via the config default helper regardless of the use of config plugins. This also means 'config' is no longer a reserved stash value.
# in templates, instead of $config->{foo}
%= config->{foo}
The deprecated Mojo::IOLoop::Delay module has been spun off to its own CPAN distribution. This control flow mechanism was a predecessor to promises support in Mojolicious and is no longer necessary.
The deprecated success
method of Mojo::Transaction
has been removed. The error
and result
methods should be used to determine whether a request was successful and retrieve its result respectively.
# throw exception on connection and HTTP errors
my $tx = $ua->get('https://example.com');
if (my $err = $tx->error) {
die $err->{code} ? "HTTP error: $err->{code} $err->{message}"
: "Connection error: $err->{message}";
} else {
my $len = $tx->res->headers->content_length;
say "Content-Length: $len";
}
# throw exception on connection errors, custom handling for HTTP errors
my $res = $ua->get('https://example.com')->result;
if ($res->is_error) { # 4xx or 5xx
my $code = $res->code;
my $message = $res->message;
say "HTTP error: $code $message";
} elsif ($res->code == 304) {
say "Not modified";
} else {
my $len = $res->headers->content_length;
say "Content-Length: $len";
}
Various cleanups have been made to the routing methods provided by Mojolicious::Routes::Route
.
- The
detour
method has been removed. Use->partial(1)->to(...)
instead, passing the same arguments toto
. - The
route
method has been removed. Useany
instead. - The
over
method has been renamed torequires
. - The
via
method has been renamed tomethods
.
Note that if you were using argument passing in the route
method of the non-reference form for restrictive placeholders like $r->route('/foo/:id/', id => qr/\d+/);
you will need to update this to the form passing an arrayref when using ->any
: $r->any('/foo/:id/', [id => qr/\d+/]);
Rather than individually handling different socket and TLS options, these have been consolidated into single options which are passed directly to the underlying IO::Socket::IP
or IO::Socket::SSL
object.
- The
local_address
attribute forMojo::UserAgent
and option forMojo::IOLoop->client
has been replaced by asocket_options
hashref attribute and option which takes arbitrary IO::Socket::IP arguments, includingLocalAddr
as previously set bylocal_address
.
# instead of $ua->local_address('127.0.0.1');
$ua->socket_options({LocalAddr => '127.0.0.1'});
# instead of Mojo::IOLoop->client(local_address => '127.0.0.1', ...);
Mojo::IOLoop->client(socket_options => {LocalAddr => '127.0.0.1'}, ...);
- The
tls_ciphers
,tls_protocols
,tls_verify
, andtls_version
options have been replaced by atls_options
hashref of arbitrary IO::Socket::SSL options inMojo::IOLoop->client
andMojo::IOLoop->server
, as well as in the underlyingMojo::IOLoop::TLS->negotiate
method.
# instead of Mojo::IOLoop->client(tls_protocols => $protocols, tls_verify => 0, ...);
Mojo::IOLoop->client(tls_options => {SSL_alpn_protocols => $protocols, SSL_verify_mode => 0x00}, ...);
# instead of Mojo::IOLoop->server(tls_ciphers => $ciphers, tls_verify => 0, tls_version => $version, ...);
Mojo::IOLoop->server(tls_options => {SSL_cipher_list => $ciphers, SSL_verify_mode => 0x00, SSL_version => $version}, ...);
Rather than invisibly logging to files in the application home if a log
directory happens to exist there, the application log now defaults only to logging to STDERR. A log path can be set explicitly during startup if desired. Mojo::Log::Role::Clearable may be applied first to ensure the new path is used even if a filehandle has already been cached for logging.
# log to application home as before
my $mode = $app->mode;
$app->log->path($app->home->child('log', "$mode.log"));
# log to /var/log
$app->log->path('/var/log/myapp/myapp.log');
# with Mojo::Log::Role::Clearable installed
$app->log->with_roles('+Clearable')->path($log_path);
Mojo::Log
will now join multiple messages passed to a single logging method with a space character instead of a newline, so that contextual logging can pass context as a separate argument.
The HTML tags <script>
and <style>
contain data which is not intended as text to display. The contents of these tags will no longer be included in all_text
in HTML mode (the default).
The application's controller classes, found within the default controller namespace of ${AppName}::Controller
, are now loaded just after startup of the application by default. This allows their memory to be shared among forked child processes, particularly prefork server workers. The namespaces to preload can be adjusted or cleared during startup via the preload_namespaces attribute.
sub startup ($self) {
$self->preload_namespaces(['Some::Namespace']);
}
Mojolicious now requires Perl 5.16 or newer, in order to make use of important features like unicode_strings and current_sub. The 5.16 feature bundle -- which includes both of these features as well as fc
, unicode_eval
, and evalbytes
-- is now enabled for any code using Mojo::Base
, Mojolicious::Lite
, or ojo
. It is expected that this requirement will be increased to Perl 5.20 in the future to facilitate usage of subroutine signatures across Mojolicious.
Mojo::Promise->new
now only takes an optional coderef similarly to the JavaScript Promise object constructor. The previous behavior of accepting attribute values has been removed, and attributes can instead be set after construction with chained setters.
my $p = Mojo::Promise->new(sub ($resolve, $reject) { ... })->ioloop($loop);
Rejected promises disappearing usually indicates a failure to capture or handle error states. Mojo::Promise now warns if this occurs; you can resolve the warning by attaching a ->catch
rejection handler to your promise chain.
Since browsers can only submit HTML forms as GET or POST, the _method
query parameter was previously recognized for GET requests to allow the request to match other route methods. This can be abused and is now only allowed for POST requests.
Mojolicious::Validator
previously treated empty string form values as if they were not submitted. Now it validates it like any other value. The not_empty
filter (available from Mojolicious 8.35) can be applied to a validation check for the previous behavior.
If a content type is not specified or implied for a response, such as when using $c->render(data => $data)
, the default is now application/octet-stream
instead of text. This avoids issues where a browser would attempt to render an unspecified binary file response as text. By manually setting the content type in such cases you can avoid relying on the default:
$c->res->headers->content_type('text/plain;charset=UTF-8');
$c->render(data => $bytes);
The slice
method was removed from Mojo::Collection, for most cases the new head
and tail
methods are more useful, and in other cases you can use standard array slicing on the collection object.
use Mojo::Collection 'c';
my $c = c(1..10);
my $first_five = $c->head(5);
my $odds = c(@$c[1,3,5,7,9]);
Previously, examples showed that you could control the Mojo::IOLoop using the EV functions such as EV::run
when the Mojo::Reactor::EV backend is in use. This is no longer supported, as the Mojo::Reactor must control the running state of the loop in order to properly reset after forking, such as in Mojo::IOLoop->subprocess
. The loop should always be started and stopped through Mojo::IOLoop, Mojo::Promise, Future::Mojo, or similar.
The finally
method appends a callback to be called when the promise is fulfilled or rejected, and used to receive the fulfillment result or rejection reason. It no longer receives these results as the corresponding function in the JavaScript Promises API does not, and the then
or catch
methods should be used to chain result-aware callbacks.
This plugin was removed so that it could be maintained separately from Mojolicious for the Mojolicious website. A stripped down fork is available from CPAN as Mojolicious::Plugin::PODViewer.
The mojo_lib_dir method finds the directory which Mojolicious has been installed to, which all Mojolicious modules can find directly using Mojo::File, so it was unnecessary. If you need to find the directory where Mojolicious was installed for some reason, you can check %INC
as follows:
use Mojo::File 'path';
my $lib_dir = path($INC{'Mojo/File.pm'})->dirname->dirname;
The query
method of Mojo::URL can take a hash or array reference to modify how it will update the URL's query component. Now, a hash reference will merge into the existing query, and an array reference will append to the end of the query, preserving order. The behavior was previously the reverse, so appending did not preserve order.
The built-in test
command has been removed. Use the standard prove tool directly to test your application, the -l
option will allow modules from the lib
directory to be loaded and the -r
option will run all .t
files recursively: prove -lr t/
The expect_close attribute was removed from Mojo::Content in order to support requesting from certain exotic websites. See this GitHub issue stemming from this mailing list thread.
In order to better integrate Delay objects as a Mojo::Promise subclass, these events were removed. It's recommended to convert Delay-using code to use Mojo::Promise directly, which can attach success and error handlers using then
and catch
.
The built-in commands cpanify
, generate
, inflate
, and the generate
sub-commands were moved to the new Mojolicious::Command::Author::
namespace from Mojolicious::Command::
. This reflects their nature as commands useful for authors using Mojolicious, and not generally for applications developed in Mojolicious.
The delay helper has been removed from Mojolicious::Plugin::DefaultHelpers. This was a wrapper for Mojo::IOLoop::Delay to automatically set it up for use within a Mojolicious action. It is recommended to migrate to using Mojo::Promise for asynchronous sequencing logic, though you still may need to set render_later, hold a reference to the transaction, and add exception handling code, as the delay helper did.
As an example, this code using the delay helper:
$c->delay(sub {
my $delay = shift;
nonblocking_call($delay->begin);
nonblocking_call($delay->begin);
}, sub {
my ($delay, $err1, $result1, $err2, $result2) = @_;
return $c->reply->exception($err1) if $err1;
return $c->reply->exception($err2) if $err2;
$c->render(json => [$result1, $result2]);
});
might be translated to this code using promises:
use Mojo::Promise;
my $tx = $c->render_later->tx;
my $p1 = Mojo::Promise->new;
my $p2 = Mojo::Promise->new;
do {
my $p = $_;
nonblocking_call(sub {
my ($invocant, $err, $result) = @_;
return $p->reject($err) if $err;
$p->resolve($result);
});
} for $p1, $p2;
Mojo::Promise->all($p1, $p2)->then(sub {
my ($result1, $result2) = @_;
$c->render(json => [$result1->[0], $result2->[0]]);
})->catch(sub { $c->reply->exception(shift); undef $tx });
It's even simpler when using APIs that already return promises:
use Mojo::Promise;
my $tx = $c->render_later->tx;
my $p1 = returns_promise;
my $p2 = returns_promise;
Mojo::Promise->all($p1, $p2)->then(sub {
my ($result1, $result2) = @_;
$c->render(json => [$result1->[0], $result2->[0]]);
})->catch(sub { $c->reply->exception(shift); undef $tx });
Route placeholders can be quoted to disambiguate them from surrounding text, make the colon prefix optional, and support placeholder types. The quote characters used to be parentheses and have been changed to chevrons.
get '/foo(bar)baz';
# should now be
get '/foo<bar>baz';
Mojo::JSON will now automatically use Cpanel::JSON::XS for better performance when available. It also changed some of its behavior to avoid differences in behavior when Cpanel::JSON::XS is used. The unicode characters U+2028 and U+2029 are no longer escaped, and unblessed references other than scalar/array/hash references will be encoded to null rather than stringified.
Subprocesses via Mojo::IOLoop->subprocess will now wait until the next tick of the event loop to fork, rather than forking the subprocess immediately when called. Among other things, this means that using it in a Mojolicious action may expose a scoping bug when you don't hold on to a reference to the transaction. See https://mojolicious.org/perldoc/Mojolicious/Guides/FAQ#What-does-Transaction-already-destroyed-mean and Mojolicious::Plugin::Subprocess, which can handle this automatically if your needs are simple.
The build_tx
, config
, handler
, and log
methods have been removed from Mojo, leaving it as an empty class. This functionality is now wholly provided by using Mojolicious as a base class for your application.
The MOJO_USERAGENT_DEBUG and MOJO_DAEMON_DEBUG environment variables, used for temporary debugging of the user-agent and daemon communication, have been replaced by MOJO_CLIENT_DEBUG and MOJO_SERVER_DEBUG.
Previously, Mojo::IOLoop::TLS (used by TCP clients such as Mojo::IOLoop->client and Mojo::UserAgent to initiate a SSL connection) would disable server certificate verification in IO::Socket::SSL. This has been changed to defer to IO::Socket::SSL's defaults, which results in enforcing verification by default. If you are connecting to servers with invalid certificates, and are aware of the risk of MITM attacks, you must now pass tls_verify => 0x00
to Mojo::IOLoop->client, or set the insecure
attribute to true on the Mojo::UserAgent object, to allow insecure connections to such servers.
The all
and race
convergent promise constructors can now only be called as class methods. Instead of my $all = $p1->all($p2, $p3)
, do my $all = Mojo::Promise->all($p1, $p2, $p3)
.
The data
and remaining
methods have been removed. Data can be passed between delay steps by closing over variables in the callback subroutines. Delay objects are now promises, so flow can be controlled using standard promise chaining with Mojo::Promise.
Response cookies without a valid domain set, when received by Mojo::UserAgent, used to set the origin
attribute to indicate the original request host. To better comply with the spec, it now sets the host_only
attribute of the cookie to true, and sets the domain
attribute to the original request host. This prevents multiple identical cookies from being stored and submitted per domain.
- The
$delay->catch
method is now the Mojo::Promise method that returns a fresh promise object rather than the Mojo::EventEmitter method that returns the original$delay
object, so chained calls like$delay->catch($handler)->on(some_event => ...)
will most likely no longer do what you want. - The catch handler now receives the error message as its first argument and the
$delay
itself is no longer available unless you closed over it, i.e.,$delay->catch(sub { my ($delay, $error) = @_; ... })
changes to$delay->catch(sub { my ($error) = @_; ... })
. - Since Delay's
error
andfinish
events are being deprecated, you'll want to change to usingcatch
andfinally
to establish those handlers instead. (Even if this doesn't actually break until 8.0, you'll want to do this now while you're thinking about it.)
The watch
attribute of Mojo::Server::Morbo was moved to the new Morbo backend classes. Instead of $morbo->watch
, use $morbo->backend->watch
.
Several functions have had their functionality moved to the new Mojo::File class, a generic file/directory helper object.
- Mojo::Util
files
function removed. Use Mojo::Filelist_tree
method instead. - Mojo::Util and Mojo::ByteStream
slurp
andspurt
functions/methods removed in favor of Mojo::File. Instead ofuse Mojo::Util 'slurp'; my $contents = slurp $filename;
, douse Mojo::File 'path'; my $contents = path($filename)->slurp;
- Mojolicious::Command
rel_dir
method removed. Userel_file
method instead.
Mojo::Home now inherits all methods from Mojo::File, so some of its specific functionality is no longer needed.
-
lib_dir
method removed. Use->child('lib')
to get a Mojo::File object representing the lib dir. -
list_files
method removed. Use inheritedlist_tree
method instead. -
parse
method removed. As a Mojo::File subclass, a new Mojo::Home object can be constructed for any path. -
parts
method removed. As a Mojo::File subclass, Mojo::Home objects can be dereferenced as an array (or withto_array
) to read the path components, or a new Mojo::Home object can be created to change the path components. -
rel_dir
method removed. Userel_file
method instead.
Mojo::Message::Response is_status_class
method has been removed. Use is_error
, is_client_error
, is_server_error
, is_info
, is_redirect
, or is_success
as appropriate.
The authority
method has been removed from Mojo::URL. When stringifying a URL, the userinfo is no longer included, so instead use host_port
to retrieve the remaining portion of the authority, or the userinfo
attribute directly if needed.
The all_text
and text
methods of Mojo::DOM no longer perform whitespace trimming, as the behavior was inconsistent and it is difficult to determine what a correct implementation would be. As such, the squish
method of Mojo::ByteStream and the squish
function from Mojo::Util have also been removed.
The Charset plugin has been removed as its functionality is simple to implement. See the charset lite app test for an example.
The multi_accept
attribute was removed from Mojo::IOLoop, Mojo::IOLoop::Server, and Mojo::Server::Daemon, along with the multi_accept
setting for Hypnotoad and the -M
option for the daemon and prefork commands. Instead there is a new single_accept
option for the listen
methods in Mojo::IOLoop::Server and Mojo::Server::Daemon. If single_accept
is not enabled, servers will accept as many connections as are available.
The build
and compile
methods were removed from Mojo::Template, and the interpret
method was removed in favor of the new process
method which compiles the template if needed.
The check
method was removed from Mojo::Server::Morbo in favor of a new modified_files
method which returns all files that have been modified instead of just one at a time.
The methods is_debug
, is_error
, is_info
, and is_warn
methods of Mojo::Log were removed, use is_level
instead.
The xss_escape
function was removed from Mojo::Util, since it is now equivalent to xml_escape
.
The methods build_frame
and parse_frame
were removed from Mojo::Transaction::WebSocket in favor of the equivalent methods in Mojo::WebSocket.
The methods client_close
and server_close
were removed from Mojo::Transaction and replaced by the method closed
.
The following methods were removed in a refactor of WebSocket transactions, replaced by the new module Mojo::WebSocket to handle the WebSocket protocol.
- Mojo::Transaction::WebSocket:
client_challenge
,client_handshake
,server_handshake
,server_open
- Mojo::Transaction:
is_writing
Also, the upgrade
event of Mojo::Transaction::HTTP was removed.
The method collecting
has been removed from Mojo::UserAgent::CookieJar. Use the ignore
attribute instead.
The methods build_body
and build_headers
have been removed from Mojo::Content. Instead, use get_header_chunk
, get_body_chunk
, headers_contain
, or body_contains
.
Support for switching user and group in Mojo::Server has been removed as it was untested and not correctly implemented. This also means the related user
and group
options have been removed:
- Mojo::Server:
user
andgroup
attributes, andsetuidgid
method - Mojo::Server::Hypnotoad:
user
andgroup
configuration settings - daemon and prefork commands:
user
andgroup
switches
There are several possible alternatives to this functionality such as the SetUserGroup plugin, see here for more information.
Name listing support was removed from the Mojolicious::Controller and Mojo::Parameters param
methods, in favor of the more appropriate Mojolicious::Parameters names
method. For example, my @names = $c->param
should now be written as my @names = @{$c->req->params->names}
, if you wish to retrieve all GET/POST parameter names. The previous behavior of including names of placeholders and uploads has been removed. Similarly, the names of validated parameters in Mojolicious::Validator::Validation have been moved from param
to passed
and failed
, which also now return arrayrefs instead of lists.
Multi-name support was removed from various methods that retrieved parameters by name; these methods can only be used to retrieve one parameter at a time now. The affected methods include: Mojolicious::Controller cookie
, param
, and signed_cookie
; Mojolicious::Validator::Validation param
; Mojo::Parameters param
; Mojo::Message cookie
and upload
.
The log
method was removed from Mojo::Log; use the individual logging methods instead (e.g. debug
, info
). The is_level
method was also removed, use is_debug
and similar methods to test the log level. The is_fatal
method was removed because fatal logging is always enabled.
The all
and find
methods now return arrayrefs instead of lists.
Mojo::Transaction no longer supports receiving a prepared socket in $tx->connection
, which means the UserAgent cannot be coerced into using a special socket. This is only relevant to you if you rely on UA over Unix domain sockets or similar. Sri has indicated that a patch to factor out some UA internals into Mojo::UserAgent::ConnectionPool might be a reasonable way to restore this, if you're interested.
The Mojo::Loader OO API has been removed, use the exported-on-demand functions data_section
, find_modules
, and load_class
directly instead.
The deprecated Mojolicious::Controller methods render_exception
and render_not_found
have been removed, use the helpers $c->reply->exception
and $c->reply->not_found
instead.
The accept mutex behavior was removed from Mojo::IOLoop and Mojo::Server::Prefork for better performance, along with the related attributes and options:
- Mojo::IOLoop:
accept_interval
,lock
, andunlock
- Mojo::Server::Prefork:
accept_interval
,lock_file
, andlock_timeout
- prefork command
-a/--accept-interval
,--lock-file
and-L/--lock-timeout
options - Hypnotoad settings
accept_interval
,lock_file
, andlock_timeout
- Mojo::Reactor
is_readable
method - Mojolicious::Routes::Route
bridge
method - useunder
instead - Mojolicious::Routes
auto_render
method
Mojo::DOM methods have been reorganized to better match the DOM spec.
-
all_contents
=>descendant_nodes
-
contents
=>child_nodes
-
match
=>matches
(also renamed in Mojo::DOM::CSS) -
following_siblings
=>following_nodes
-
preceding_siblings
=>preceding_nodes
-
next_sibling
=>next_node
-
previous_sibling
=>previous_node
-
siblings
=> Replaced byfollowing
andpreceding
methods -
node
=>type
-
type
=>tag
- Mojo::UserAgent::CookieJar:
-
extracting
=>collecting
-
extract
=>collect
-
inject
=>prepare
- Mojo::Template:
template
=>unparsed
- Mojolicious::Types:
types
=>mapping
- Mojolicious::Routes::Match:
-
current
=>position
-
match
=>find
- Mojolicious::Routes::Pattern:
pattern
=>unparsed
- Mojo::UserAgent::Proxy:
inject
=>prepare
- Mojo::Parameters:
params
=>pairs
- prefork command switch:
-A
=>-a
- Hypnotoad option:
keep_alive_requests
=>requests
The Mojo::JSON object-oriented API has been removed, encode_json
and decode_json
functions should be used instead.
Mojo::Collection stringification support has been removed, use the join
method instead. Mojo::Collection also no longer uses AUTOLOAD; the map
method should be used for this functionality (as well as to replace the removed pluck
method).
Mojo::DOM no longer uses AUTOLOAD, the children
method should be used instead. The val
method has also been removed.
Mojo::JSON::Pointer methods no longer take a $data
argument to specify the data structure to traverse, and only uses its data
attribute.
The render_static
method of Mojolicious::Controller has been removed, use the $c->reply->static
helper instead.
- Mojo::EventEmitter:
emit_safe
- Mojolicious::Routes::Route:
has_conditions
Methods that previously worked differently in scalar than in list context now always assume scalar context, and new methods (every_*
) have been added to cover the list context functionality, returning an arrayref. For example, my @things = $c->param('thing')
should now be written my @things = @{$c->every_param('thing')}
.
- Mojo::Message:
-
cookie
/every_cookie
-
upload
/every_upload
- Mojo::Message::Request:
param
/every_param
- Mojo::Parameters:
param
/every_param
- Mojolicious::Controller:
-
cookie
/every_cookie
-
param
/every_param
-
signed_cookie
/every_signed_cookie
- Mojolicious::Validator::Validation:
param
/every_param
This change addresses a security vulnerability when working with context-sensitive functions in perl; see here for more information.