1

Background:

I've written an LWP::Protocol "implementor" for HTTP(S) based on AnyEvent::HTTP. (i.e: it implements both HTTP and HTTPS).

It's different than LWP::Protocol::AnyEvent::http or Coro::LWP in that it doesn't BLOCK on $protocol->request. I've implemented most of the same hacks for select(), name-resolution etc that Coro::LWP does, but making better use of AnyEvent.

The HTTP response returned by $protocol->request() is 230 - Pending Completion of Request for now but I'm open to better ways to convey that it isn't a completed request.

I've also written a subclass of HTTP::Response which forces BLOCKING on the standard "consumer" methods if they attempt to use parts of the response before it's complete; it also adds methods for working nicely with internal/provided AnyEvent::CondVar so that you can fire lots of requests off at once, as well as do other stuff with AnyEvent. (I've also overridden all of LWP::UserAgent's post-send_request() logic to defer it until the real request completion).

Problem:

I'm currently doing a hack were I have my LWP::UserAgent subclass "upgrade" the URL scheme by appending '_async' for async requests, and I've got the LWP::Protocol subclass being an "implementor" for schemes matching /^https?_async$/

Question:

How can I get my LWP::UserAgent subclass to choose my (more asynchronous) HTTP & HTTPS protocol "implementors" instead of others installed on the system? (i.e: when the LWP::UserAgent subclass calls LWP::Protocol::create).

Can I force selection of my "implementors"? Or is there a more natural way to do this?

David-SkyMesh
  • 5,041
  • 1
  • 31
  • 38

1 Answers1

2

You need to call implementor in close proximity to your send_request call:

LWP::Protocol::implementor('http', 'your::module::name');

See source of http://search.cpan.org/~gaas/LWP-Protocol-http10-6.03/lib/LWP/Protocol/http10.pm to understand what you need to implement to replace the HTTP protocol handler

Noam Rathaus
  • 5,405
  • 2
  • 28
  • 37
  • As I said in my question it's both HTTP and HTTPS protocols I wish to override. `AnyEvent::HTTP` already deals fine with SSL. I'm trying to get `LWP::UserAgent` to use *my* LWP::Protocol "implementor" over others installed on the system (e.g: LWP::Protocol::http, LWP::Protocol::AnyEvent::http) that implement the same schemes - HTTP and HTTPS. – David-SkyMesh Dec 29 '13 at 07:56
  • If you actually read the question, I've written a subclass of LWP::UserAgent. LWP::UserAgent calls `$protocol->request` from the "appropriate" LWP::Protocol subclass (where $protocol is manufactured by a factory function called `LWP::Protocol::create`). My question is about how to influence that selection. – David-SkyMesh Dec 29 '13 at 07:59
  • Ok, sorry, but your question isn't very clear to me, so now, have you tried to change the LWP::Protocol::implementor ? http://search.cpan.org/~gaas/libwww-perl-6.05/lib/LWP/Protocol.pm – Noam Rathaus Dec 29 '13 at 08:01
  • Specifically LWP::Protocol::implementor('http', 'your::module::name'); – Noam Rathaus Dec 29 '13 at 08:01
  • I've done that. It still chooses another implementor. There are several that implement 'http'. – David-SkyMesh Dec 29 '13 at 08:03
  • So you are not calling it in the right order, or you are not using Your::CustomAgent and inside it call the implementator – Noam Rathaus Dec 29 '13 at 08:04
  • Ok, so do I need to (e.g:) `use LWP::Protocol::http_async` before requiring LWP::UserAgent? Will that cause that particular implementor to be chosen? – David-SkyMesh Dec 29 '13 at 08:05
  • It needs to be called before as far as I remember, as it will override an undefined value, but not a defined one, this is why the order is important – Noam Rathaus Dec 29 '13 at 08:06
  • Or do I need to make sure `implementor` gets called just before `request`? – David-SkyMesh Dec 29 '13 at 08:07
  • Try to dump the data structure of your LWP and see which implementor is defined – Noam Rathaus Dec 29 '13 at 08:07
  • Ah, OK, so the catch is that LWP::Protocol::AnyEvent::http (an "http" implementor) is also loaded so that I can use it's `lwp_request2anyevent_request` method. If all it takes is to avoid doing that, and to manually `use use LWP::Protocol::http_async` then that'll be easy enough. – David-SkyMesh Dec 29 '13 at 08:08
  • The one from `LWP::Protocol::AnyEvent::http` is defined. (As I mentioned just now, I use one of its methods). – David-SkyMesh Dec 29 '13 at 08:09
  • That works. :-) If you edit your answer to remove all the SSL stuff, and mention that `implementor` needs to be called in close proximity to `LWP::UserAgent::send_request()`, then I'll accept your answer. – David-SkyMesh Dec 29 '13 at 08:12