http intermediate

How to use HTTP::Request to build complex requests in Perl?

Question

How to use HTTP::Request to build complex requests in Perl?

Using HTTP::Request to Build Complex HTTP Requests in Perl

The HTTP::Request module is part of Perl's LWP library and is designed to create detailed HTTP requests manually. It provides control over HTTP methods, headers, and content, which is useful for crafting complex REST API calls or custom interactions where you need more than a simple GET or POST. However, HTTP::Request objects only represent the request and do not execute it—sending requires modules like LWP::UserAgent.

Key Perl Concepts

  • Sigils: $ for scalars, @ for arrays, and % for hashes. Remember strings interpolated in double quotes may treat @ as array interpolation, which can cause errors if not careful.
  • Context: Methods like content() expect scalar strings, not arrays or references.
  • TMTOWTDI (There’s More Than One Way To Do It): You can build request headers incrementally or supply them all at once as a hashref.

Common Pitfall Highlighted

In the original code, the email address inside double quotes with @example.com caused Perl to try to interpolate @example as an array variable, which does not exist, resulting in an error. This is a common Perl gotcha when using @ symbols inside double-quoted strings. The fix is to either escape the @ (e.g. alice\@example.com) or use single quotes where interpolation is disabled.

Corrected Example: Building and Sending a Complex HTTP POST Request

use strict;
use warnings;
use HTTP::Request;
use LWP::UserAgent;
use JSON;

# Construct Perl data structure with single quotes for strings containing "@"
my $data = {
    name    => 'Alice',
    email   => 'alice@example.com',
    roles   => ['admin', 'editor'],
    active  => \1,  # Boolean true reference
};

# Encode the data to a JSON string
my $json_content = encode_json($data);

# Create HTTP::Request object with method and URL
my $req = HTTP::Request->new(
    'POST' => 'https://httpbin.org/post'  # A public test service that echoes requests
);

# Add headers
$req->header('Content-Type'  => 'application/json');
$req->header('User-Agent'    => 'Perl HTTP::Request Example/1.0');
$req->header('Authorization' => 'Bearer xxxxxxxx');

# Set the request content (body)
$req->content($json_content);

# Create a user agent to send the request
my $ua = LWP::UserAgent->new;

# Send the request and capture the response
my $res = $ua->request($req);

# Print the response status line and content
print "Status: ", $res->status_line, "\n";
print "Response body:\n", $res->decoded_content, "\n";

Explanation

  • HTTP::Request->new() creates a request object with method and URL.
  • Headers are added incrementally via header(), avoiding large hashrefs for clarity.
  • Content is serialized JSON, requiring the JSON core module (Perl 5.14+).
  • LWP::UserAgent sends the request and returns a response object.
  • Using single quotes around strings containing @ prevents accidental array interpolation errors.

Tips & Gotchas

  • Double quotes and @ sign: Always escape @ with \\@ or use single quotes in email addresses or strings containing @.
  • Request execution: Remember HTTP::Request only builds requests. Use LWP::UserAgent or similar to send them.
  • Headers overwrite: Setting the same header multiple times replaces earlier values unless you use arrays.

Version Notes

  • The JSON module is included in core Perl 5.14+. For older versions, CPAN installation is required.
  • HTTP::Request and LWP::UserAgent have stable APIs across Perl 5.x.

This approach gives you granular control over building HTTP requests, making it great for working with APIs that require specific headers, HTTP verbs, and payload formats.

Verified Code

Executed in a sandbox to capture real output. • v5.34.1 • 98ms

Tip: edit code and use “Run (Browser)”. Server runs always execute the published, verified snippet.
STDOUT
Status: 500 Can't verify SSL peers without knowing which Certificate Authorities to trust
Response body:
Can't verify SSL peers without knowing which Certificate Authorities to trust

This problem can be fixed by either setting the PERL_LWP_SSL_CA_FILE
environment variable or by installing the Mozilla::CA module.

To disable verification of SSL peers set the PERL_LWP_SSL_VERIFY_HOSTNAME
environment variable to 0.  If you do this you can't be sure that you
communicate with the expected peer.

STDERR
(empty)

Was this helpful?

Related Questions