Security Advisories (2)
CVE-2024-58134 (2025-05-03)

Mojolicious versions from 0.999922 for Perl uses a hard coded string, or the application's class name, as a HMAC session secret by default. These predictable default secrets can be exploited to forge session cookies. An attacker who knows or guesses the secret could compute valid HMAC signatures for the session cookie, allowing them to tamper with or hijack another user's session.

CVE-2024-58135 (2025-05-03)

Mojolicious versions from 7.28 for Perl may generate weak HMAC session secrets. When creating a default app with the "mojo generate app" tool, a weak secret is written to the application's configuration file using the insecure rand() function, and used for authenticating and protecting the integrity of the application's sessions. This may allow an attacker to brute force the application's session keys.

NAME

Mojo::UserAgent::Transactor - User agent transactor

SYNOPSIS

use Mojo::UserAgent::Transactor;

# GET request with Accept header
my $t = Mojo::UserAgent::Transactor->new;
say $t->tx(GET => 'http://example.com' => {Accept => '*/*'})->req->to_string;

# POST request with form-data
say $t->tx(POST => 'example.com' => form => {a => 'b'})->req->to_string;

# PUT request with JSON data
say $t->tx(PUT => 'example.com' => json => {a => 'b'})->req->to_string;

DESCRIPTION

Mojo::UserAgent::Transactor is the transaction building and manipulation framework used by Mojo::UserAgent.

GENERATORS

These content generators are available by default.

form

$t->tx(POST => 'http://example.com' => form => {a => 'b'});

Generate query string, application/x-www-form-urlencoded or multipart/form-data content. See "tx" for more.

json

$t->tx(PATCH => 'http://example.com' => json => {a => 'b'});

Generate JSON content with Mojo::JSON. See "tx" for more.

multipart

$t->tx(PUT => 'http://example.com' => multipart => ['Hello', 'World!']);

Generate multipart content. See "tx" for more.

ATTRIBUTES

Mojo::UserAgent::Transactor implements the following attributes.

compressed

my $bool = $t->compressed;
$t       = $t->compressed($bool);

Try to negotiate compression for the response content and decompress it automatically, defaults to the value of the MOJO_GZIP environment variable or true.

generators

my $generators = $t->generators;
$t             = $t->generators({foo => sub {...}});

Registered content generators, by default only form, json and multipart are already defined.

name

my $name = $t->name;
$t       = $t->name('Mojolicious');

Value for User-Agent request header of generated transactions, defaults to Mojolicious (Perl).

METHODS

Mojo::UserAgent::Transactor inherits all methods from Mojo::Base and implements the following new ones.

add_generator

$t = $t->add_generator(foo => sub {...});

Register a content generator.

$t->add_generator(foo => sub ($t, $tx, @args) {...});

download

my $tx = $t->download(Mojo::Transaction::HTTP->new, '/home/sri/test.tar.gz');

Build Mojo::Transaction::HTTP resumable file download request as follow-up to a HEAD request. Note that this method is EXPERIMENTAL and might change without warning!

endpoint

my ($proto, $host, $port) = $t->endpoint(Mojo::Transaction::HTTP->new);

Actual endpoint for transaction.

peer

my ($proto, $host, $port) = $t->peer(Mojo::Transaction::HTTP->new);

Actual peer for transaction.

promisify

$t->promisify(Mojo::Promise->new, Mojo::Transaction::HTTP->new);

Resolve or reject Mojo::Promise object with Mojo::Transaction::HTTP object.

proxy_connect

my $tx = $t->proxy_connect(Mojo::Transaction::HTTP->new);

Build Mojo::Transaction::HTTP proxy CONNECT request for transaction if possible.

redirect

my $tx = $t->redirect(Mojo::Transaction::HTTP->new);

Build Mojo::Transaction::HTTP follow-up request for 301, 302, 303, 307 or 308 redirect response if possible.

tx

my $tx = $t->tx(GET  => 'example.com');
my $tx = $t->tx(POST => 'http://example.com');
my $tx = $t->tx(GET  => 'http://example.com' => {Accept => '*/*'});
my $tx = $t->tx(PUT  => 'http://example.com' => 'Content!');
my $tx = $t->tx(PUT  => 'http://example.com' => form => {a => 'b'});
my $tx = $t->tx(PUT  => 'http://example.com' => json => {a => 'b'});
my $tx = $t->tx(PUT  => 'https://example.com' => multipart => ['a', 'b']);
my $tx = $t->tx(POST => 'example.com' => {Accept => '*/*'} => 'Content!');
my $tx = $t->tx(PUT => 'example.com' => {Accept => '*/*'} => form => {a => 'b'});
my $tx = $t->tx(PUT => 'example.com' => {Accept => '*/*'} => json => {a => 'b'});
my $tx = $t->tx(PUT => 'example.com' => {Accept => '*/*'} => multipart => ['a', 'b']);

Versatile general purpose Mojo::Transaction::HTTP transaction builder for requests, with support for "GENERATORS".

# Generate and inspect custom GET request with DNT header and content
say $t->tx(GET => 'example.com' => {DNT => 1} => 'Bye!')->req->to_string;

# Stream response content to STDOUT
my $tx = $t->tx(GET => 'http://example.com');
$tx->res->content->unsubscribe('read')->on(read => sub { say $_[1] });

# PUT request with content streamed from file
my $tx = $t->tx(PUT => 'http://example.com');
$tx->req->content->asset(Mojo::Asset::File->new(path => '/foo.txt'));

The json content generator uses Mojo::JSON for encoding and sets the content type to application/json.

# POST request with "application/json" content
my $tx = $t->tx(POST => 'http://example.com' => json => {a => 'b', c => [1, 2, 3]});

The form content generator will automatically use query parameters for GET and HEAD requests.

# GET request with query parameters
my $tx = $t->tx(GET => 'http://example.com' => form => {a => 'b'});

For all other request methods the application/x-www-form-urlencoded content type is used.

# POST request with "application/x-www-form-urlencoded" content
my $tx = $t->tx(POST => 'http://example.com' => form => {a => 'b', c => 'd'});

Parameters may be encoded with the charset option.

# PUT request with Shift_JIS encoded form values
my $tx = $t->tx(PUT => 'example.com' => form => {a => 'b'} => charset => 'Shift_JIS');

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 => ['b', 'c', 'd']});

A hash reference with a content or file value can be used to switch to the multipart/form-data content type for file uploads.

# POST request with "multipart/form-data" content
my $tx = $t->tx(POST => 'http://example.com' => form => {mytext => {content => 'lala'}});

# POST request with multiple files sharing the same name
my $tx = $t->tx(POST => 'http://example.com' => form => {mytext => [{content => 'first'}, {content => 'second'}]});

The file value should contain the path to the file you want to upload or an asset object, like Mojo::Asset::File or Mojo::Asset::Memory.

# POST request with upload streamed from file
my $tx = $t->tx(POST => 'http://example.com' => form => {mytext => {file => '/foo.txt'}});

# POST request with upload streamed from asset
my $asset = Mojo::Asset::Memory->new->add_chunk('lalala');
my $tx    = $t->tx(POST => 'http://example.com' => form => {mytext => {file => $asset}});

A filename value will be generated automatically, but can also be set manually if necessary. All remaining values in the hash reference get merged into the multipart/form-data content as headers.

# POST request with form values and customized upload (filename and header)
my $tx = $t->tx(POST => 'http://example.com' => form => {
  a      => 'b',
  c      => 'd',
  mytext => {
    content        => 'lalala',
    filename       => 'foo.txt',
    'Content-Type' => 'text/plain'
  }
});

The multipart/form-data content type can also be enforced by setting the Content-Type header manually.

# Force "multipart/form-data"
my $headers = {'Content-Type' => 'multipart/form-data'};
my $tx = $t->tx(POST => 'example.com' => $headers => form => {a => 'b'});

The multipart content generator can be used to build custom multipart requests and does not set a content type.

# POST request with multipart content ("foo" and "bar")
my $tx = $t->tx(POST => 'http://example.com' => multipart => ['foo', 'bar']);

Similar to the form content generator you can also pass hash references with content or file values, as well as headers.

# POST request with multipart content streamed from file
my $tx = $t->tx(POST => 'http://example.com' => multipart => [{file => '/foo.txt'}]);

# PUT request with multipart content streamed from asset
my $headers = {'Content-Type' => 'multipart/custom'};
my $asset   = Mojo::Asset::Memory->new->add_chunk('lalala');
my $tx      = $t->tx(PUT => 'http://example.com' => $headers => multipart => [{file => $asset}]);

# POST request with multipart content and custom headers
my $tx = $t->tx(POST => 'http://example.com' => multipart => [
  {
    content            => 'Hello',
    'Content-Type'     => 'text/plain',
    'Content-Language' => 'en-US'
  },
  {
    content            => 'World!',
    'Content-Type'     => 'text/plain',
    'Content-Language' => 'en-US'
  }
]);

upgrade

my $tx = $t->upgrade(Mojo::Transaction::HTTP->new);

Build Mojo::Transaction::WebSocket follow-up transaction for WebSocket handshake if possible.

websocket

my $tx = $t->websocket('ws://example.com');
my $tx = $t->websocket('ws://example.com' => {DNT => 1} => ['v1.proto']);

Versatile Mojo::Transaction::HTTP transaction builder for WebSocket handshake requests.

SEE ALSO

Mojolicious, Mojolicious::Guides, https://mojolicious.org.