Name
SPVM::Mojo::UserAgent - Context-aware HTTP and WebSocket user agent
Description
Mojo::UserAgent class in SPVM is a full featured HTTP and WebSocket user agent. Every I/O operation is context-aware and can be canceled via Go::Context.
Since this class is designed to be goroutine-safe, you can perform multiple HTTP requests in parallel by creating goroutines. This is efficient for fetching data from multiple APIs simultaneously.
Usage
use Mojo::UserAgent;
use Go::Context;
use Go;
# Note: This version is not compatible with previous versions.
# The first argument of I/O methods (get, post, put, patch, delete, head, options, start)
# now requires a Go::Context object.
my $ua = Mojo::UserAgent->new;
my $ctx = Go::Context->background;
# --- Single request example ---
my $res = $ua->get($ctx, "docs.mojolicious.org")->result;
say $res->body if $res->is_success;
# --- Parallel access example ---
# Fetch multiple URLs in parallel using goroutines.
# Note: SPVM does not support closures, so variables must be passed as arguments.
my $urls = ["https://google.com", "https://github.com", "https://metacpan.org"];
for my $url (@$urls) {
Go->go([$ctx : Go::Context, $ua : Mojo::UserAgent, $url : string], method : void () {
my $tx = $ua->get($ctx, $url);
if (my $res = $tx->result) {
say "URL: $url, Code: " . $res->code;
}
});
}
# Wait for all goroutines to finish
Go->gosched;
# --- Request with timeout example ---
{
my $timeout_ctx_derived = Go::Context->with_timeout($ctx, 0.5);
my $timeout_ctx = $timeout_ctx_derived->ctx;
my $tx = $ua->get($timeout_ctx, "https://example.com");
}
Class Methods
new
static method new : Mojo::UserAgent ();
Create a new Mojo::UserAgent object, and return it.
Instance Methods
build_tx
method build_tx : Mojo::Transaction::HTTP ($method : string, $url : string|Mojo::URL, $args : object...);
Generate Mojo::Transaction::HTTP object with Mojo::UserAgent::Transactor#tx.
Examples:
my $tx = $ua->build_tx(GET => "example.com");
my $tx = $ua->build_tx(PUT => "http://example.com" => {Accept => "*/*"} => "Content!");
my $tx = $ua->build_tx(PUT => "http://example.com" => {Accept => "*/*"} => [(object)form => {a => "b"}]);
my $tx = $ua->build_tx(PUT => "http://example.com" => {Accept => "*/*"} => [(object)json => {a => "b"}]);
# Request with custom cookie
my $tx = $ua->build_tx(GET => "https://example.com/account");
$tx->req->cookies({name => "user", value => "sri"});
$tx = $ua->start($ctx, $tx);
# Deactivate gzip compression
my $tx = $ua->build_tx(GET => "example.com");
$tx->req->headers->remove("Accept-Encoding");
$tx = $ua->start($ctx, $tx);
# Interrupt response by raising an error
my $tx = $ua->build_tx(GET => "http://example.com");
$tx->res->on(progress => method ($res : Mojo::Message::Response) {
unless (my $server = $res->headers->server) {
return;
}
if (Re->m($server, "IIS")) {
die "Oh noes, it is IIS!";
}
});
$tx = $ua->start($ctx, $tx);
build_websocket_tx
Not yet implemented.
delete
method delete : Mojo::Transaction::HTTP ($ctx : Go::Context, $url : string|Mojo::URL, $args : object...);
Perform blocking DELETE request and return resulting Mojo::Transaction::HTTP object, takes the same arguments as "tx" in Mojo::UserAgent::Transactor (except for the DELETE method, which is implied).
Examples:
my $tx = $ua->delete($ctx, "example.com");
my $tx = $ua->delete($ctx, "http://example.com" => {Accept => "*/*"} => "Content!");
my $tx = $ua->delete($ctx, "http://example.com" => {Accept => "*/*"} => [(object)form => {a => "b"}]);
my $tx = $ua->delete($ctx, "http://example.com" => {Accept => "*/*"} => [(object)json => {a => "b"}]);
get
method get : Mojo::Transaction::HTTP ($ctx : Go::Context, $url : string|Mojo::URL, $args : object...);
Perform blocking GET request and return resulting Mojo::Transaction::HTTP object, takes the same arguments as "tx" in Mojo::UserAgent::Transactor (except for the GET method, which is implied).
Examples:
my $tx = $ua->get($ctx, "example.com");
my $tx = $ua->get($ctx, "http://example.com" => {Accept => "*/*"} => "Content!");
my $tx = $ua->get($ctx, "http://example.com" => {Accept => "*/*"} => [(object)form => {a => "b"}]);
my $tx = $ua->get($ctx, "http://example.com" => {Accept => "*/*"} => [(object)json => {a => "b"}]);
head
method head : Mojo::Transaction::HTTP ($ctx : Go::Context, $url : string|Mojo::URL, $args : object...);
Perform blocking HEAD request and return resulting Mojo::Transaction::HTTP object, takes the same arguments as "tx" in Mojo::UserAgent::Transactor (except for the HEAD method, which is implied).
Examples:
my $tx = $ua->head($ctx, "example.com");
my $tx = $ua->head($ctx, "http://example.com" => {Accept => "*/*"} => "Content!");
my $tx = $ua->head($ctx, "http://example.com" => {Accept => "*/*"} => [(object)form => {a => "b"}]);
my $tx = $ua->head($ctx, "http://example.com" => {Accept => "*/*"} => [(object)json => {a => "b"}]);
options
method options : Mojo::Transaction::HTTP ($ctx : Go::Context, $url : string|Mojo::URL, $args : object...);
Perform blocking OPTIONS request and return resulting Mojo::Transaction::HTTP object, takes the same arguments as "tx" in Mojo::UserAgent::Transactor (except for the OPTIONS method, which is implied).
Examples:
my $tx = $ua->options($ctx, "example.com");
my $tx = $ua->options($ctx, "http://example.com" => {Accept => "*/*"} => "Content!");
my $tx = $ua->options($ctx, "http://example.com" => {Accept => "*/*"} => [(object)form => {a => "b"}]);
my $tx = $ua->options($ctx, "http://example.com" => {Accept => "*/*"} => [(object)json => {a => "b"}]);
patch
method patch : Mojo::Transaction::HTTP ($ctx : Go::Context, $url : string|, $args : object...);
Perform blocking PATCH request and return resulting Mojo::Transaction::HTTP object, takes the same arguments as "tx" in Mojo::UserAgent::Transactor (except for the PATCH method, which is implied).
Examples:
my $tx = $ua->patch($ctx, "example.com");
my $tx = $ua->patch($ctx, "http://example.com" => {Accept => "*/*"} => "Content!");
my $tx = $ua->patch($ctx, "http://example.com" => {Accept => "*/*"} => [(object)form => {a => "b"}]);
my $tx = $ua->patch($ctx, "http://example.com" => {Accept => "*/*"} => [(object)json => {a => "b"}]);
post
method post : Mojo::Transaction::HTTP ($ctx : Go::Context, $url : string|Mojo::URL, $args : object...);
Perform blocking POST request and return resulting Mojo::Transaction::HTTP object, takes the same arguments as "tx" in Mojo::UserAgent::Transactor (except for the POST method, which is implied).
Examples:
my $tx = $ua->post($ctx, "example.com");
my $tx = $ua->post($ctx, "http://example.com" => {Accept => "*/*"} => "Content!");
my $tx = $ua->post($ctx, "http://example.com" => {Accept => "*/*"} => [(object)form => {a => "b"}]);
my $tx = $ua->post($ctx, "http://example.com" => {Accept => "*/*"} => [(object)json => {a => "b"}]);
put
method put : Mojo::Transaction::HTTP ($ctx : Go::Context, $url : string|Mojo::URL, $args : object...);
Perform blocking PUT request and return resulting Mojo::Transaction::HTTP object, takes the same arguments as "tx" in Mojo::UserAgent::Transactor (except for the PUT method, which is implied).
Examples:
my $tx = $ua->put($ctx, "example.com");
my $tx = $ua->put($ctx, "http://example.com" => {Accept => "*/*"} => "Content!");
my $tx = $ua->put($ctx, "http://example.com" => {Accept => "*/*"} => [(object)form => {a => "b"}]);
my $tx = $ua->put($ctx, "http://example.com" => {Accept => "*/*"} => [(object)json => {a => "b"}]);
start
method start : Mojo::Transaction::HTTP ($ctx : Go::Context, $tx : Mojo::Transaction::HTTP);
Perform blocking request for a custom Mojo::Transaction::HTTP object, which can be prepared manually or with "build_tx".
Examples:
my $tx = $ua->start($ctx, Mojo::Transaction::HTTP->new);
websocket
Not yet implemented.
See Also
Copyright & License
Copyright (c) 2025 Yuki Kimoto
MIT License
1 POD Error
The following errors were encountered while parsing the POD:
- Around line 166:
Nested L<> are illegal. Pretending inner one is X<...> so can continue looking for other errors.