Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 17, 2025

Adds support for providing a custom LWP::UserAgent instance to XML::Feed for controlling HTTP behavior when fetching feeds from URIs.

Changes

  • Constructor: Accepts optional { useragent => $ua } hashref as final parameter with validation

    my $ua = LWP::UserAgent->new;
    $ua->timeout(30);
    my $feed = XML::Feed->new('Atom', { useragent => $ua });
  • useragent() method: Getter/setter with lazy initialization

    • Returns existing UserAgent or creates default if none exists
    • Setter validates LWP::UserAgent type
  • get_uri(): Uses instance useragent when available, creates default only when needed

  • parse(): Calls $feed->get_uri() instead of $class->get_uri() to respect instance useragent

  • Validation: Rejects non-LWP::UserAgent objects and unknown hash keys

Maintains backward compatibility - existing code unchanged, RSS version parameter unaffected.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • cpanmin.us
    • Triggering command: curl -L REDACTED (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>Add "useragent" as a real attribute of the class.</issue_title>
<issue_description></issue_description>

Comments on the Issue (you are @copilot in this section)

@davorg * Add an attribute "useragent" to the class * Accept an optional `\%args` hash to the constructor which contains optional extra attritbutes * Validate the keys of the `\%args` hash - currently only "useragent" is allowed and it must be an object of class "LWP::UserAgent" (or a subclass) * In `get_uri()` only create a UserAgent if one already exists * Add a `useragent` method that returns the UserAgent attribute (creating one if it doesn't exist) * Look into other methods that call `bless` (I see it in `parse()`) and see if they can call `new()` instead

💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI changed the title [WIP] Add useragent as a real attribute of the class Add useragent attribute for custom LWP::UserAgent configuration Nov 17, 2025
Copilot AI requested a review from davorg November 17, 2025 08:55
Copilot finished work on behalf of davorg November 17, 2025 08:55
@davorg
Copy link
Collaborator

davorg commented Nov 17, 2025

@copilot Explain in more depth why you can't replace the bless() in parse() with a call to new()

Copy link
Contributor Author

Copilot AI commented Nov 17, 2025

@copilot Explain in more depth why you can't replace the bless() in parse() with a call to new()

The bless() in parse() cannot be replaced with new() because of the fundamental difference in how they work:

The Problem:
parse() needs to identify the feed format before creating the properly-typed object, but new() requires the format to be specified upfront.

Flow in parse() (lines 68-101):

  1. Line 72: bless {}, $class - Creates temporary XML::Feed object
  2. Lines 74-82: Fetch XML content (may call $feed->get_uri(), get_fh(), etc.)
  3. Line 93: $feed->identify_format(\$xml) - Determines format by examining the XML
  4. Line 99: bless $feed, $format_class - Re-blesses to the correct format class (e.g., XML::Feed::Format::Atom)

Flow in new() (lines 23-64):

  1. Line 25: my $format = shift // 'Atom' - Format must be known at construction time
  2. Line 57: bless {}, join('::', __PACKAGE__, "Format", $format) - Blesses directly to format class

Why new() won't work:
If we called new() in parse(), we'd need to know the format beforehand, but the whole point of parse() is to auto-detect the format from the XML content. We need the temporary object (line 72) to call instance methods like identify_format() before we know what the final class should be.

The initial bless on line 72 creates a minimal object just functional enough to run format detection, then line 99 re-blesses it to the correct subclass once we know what format it is.

Copilot finished work on behalf of davorg November 17, 2025 09:18
@davorg
Copy link
Collaborator

davorg commented Nov 17, 2025

@copilot So can the initial bless() on line 72 be replaced by a call to new()?

Copy link
Contributor Author

Copilot AI commented Nov 17, 2025

@copilot So can the initial bless() on line 72 be replaced by a call to new()?

No, the initial bless() on line 72 cannot be replaced with new() because:

  1. Class mismatch: Line 72 blesses to $class (the base XML::Feed class), but new() always blesses to a format-specific class like XML::Feed::Format::Atom (line 57).

  2. new() requires a format: new() expects a format parameter (line 25), but at line 72 we don't know the format yet - that's what we're about to determine.

  3. Different purposes: new() calls init_empty() to initialize a new empty feed, but line 72 just needs a minimal object to call identify_format() and handle errors.

The bare bless {}, $class is the correct, minimal approach. To use new() here, we'd need to significantly refactor it to support blessing to the base class and skip initialization - at which point it would essentially be doing the same thing as the current bless.

Copilot finished work on behalf of davorg November 17, 2025 09:28
@davorg davorg merged commit d77eaeb into master Nov 17, 2025
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add "useragent" as a real attribute of the class.

2 participants