.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.42) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "LWP::Protocol::PSGI 3pm" .TH LWP::Protocol::PSGI 3pm "2022-06-30" "perl v5.34.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" LWP::Protocol::PSGI \- Override LWP's HTTP/HTTPS backend with your own PSGI application .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& use LWP::UserAgent; \& use LWP::Protocol::PSGI; \& \& # $app can be any PSGI application: Mojolicious, Catalyst or your own \& my $app = do { \& use Dancer; \& set apphandler => \*(AqPSGI\*(Aq; \& get \*(Aq/search\*(Aq => sub { \& return \*(Aqsearching for \*(Aq . params\->{q}; \& }; \& dance; \& }; \& \& # Register the $app to handle all LWP requests \& LWP::Protocol::PSGI\->register($app); \& \& # can hijack any code or module that uses LWP::UserAgent underneath, with no changes \& my $ua = LWP::UserAgent\->new; \& my $res = $ua\->get("http://www.google.com/search?q=bar"); \& print $res\->content; # "searching for bar" \& \& # Only hijacks specific host (and port) \& LWP::Protocol::PSGI\->register($psgi_app, host => \*(Aqlocalhost:3000\*(Aq); \& \& my $ua = LWP::UserAgent\->new; \& $ua\->get("http://localhost:3000/app"); # this routes $app \& $ua\->get("http://google.com/api"); # this doesn\*(Aqt \- handled with actual HTTP requests .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" LWP::Protocol::PSGI is a module to hijack \fBany\fR code that uses LWP::UserAgent underneath such that any \s-1HTTP\s0 or \s-1HTTPS\s0 requests can be routed to your own \s-1PSGI\s0 application. .PP Because it works with any code that uses \s-1LWP,\s0 you can override various WWW::*, Net::* or WebService::* modules such as WWW::Mechanize, without modifying the calling code or its internals. .PP .Vb 2 \& use WWW::Mechanize; \& use LWP::Protocol::PSGI; \& \& LWP::Protocol::PSGI\->register($my_psgi_app); \& \& my $mech = WWW::Mechanize\->new; \& $mech\->get("http://amazon.com/"); # $my_psgi_app runs .Ve .SH "TESTING" .IX Header "TESTING" This module is extremely handy if you have tests that run \s-1HTTP\s0 requests against your application and want them to work with both internal and external instances. .PP .Vb 3 \& # in your .t file \& use Test::More; \& use LWP::UserAgent; \& \& unless ($ENV{TEST_LIVE}) { \& require LWP::Protocol::PSGI; \& my $app = Plack::Util::load_psgi("app.psgi"); \& LWP::Protocol::PSGI\->register($app); \& } \& \& my $ua = LWP::UserAgent\->new; \& my $res = $ua\->get("http://myapp.example.com/"); \& is $res\->code, 200; \& like $res\->content, qr/Hello/; .Ve .PP This test script will by default route all \s-1HTTP\s0 requests to your own \&\s-1PSGI\s0 app defined in \f(CW$app\fR, but with the environment variable \&\f(CW\*(C`TEST_LIVE\*(C'\fR set, runs the requests against the live server. .PP You can also combine Plack::App::Proxy with LWP::Protocol::PSGI to route all requests made in your test against a specific server. .PP .Vb 2 \& use LWP::Protocol::PSGI; \& use Plack::App::Proxy; \& \& my $app = Plack::App::Proxy\->new(remote => "http://testapp.local:3000")\->to_app; \& LWP::Protocol::PSGI\->register($app); \& \& my $ua = LWP::UserAgent\->new; \& my $res = $ua\->request("http://testapp.com"); # this hits testapp.local:3000 .Ve .SH "METHODS" .IX Header "METHODS" .IP "register" 4 .IX Item "register" .Vb 2 \& LWP::Protocol::PSGI\->register($app, %options); \& my $guard = LWP::Protocol::PSGI\->register($app, %options); .Ve .Sp Registers an override hook to hijack \s-1HTTP\s0 requests. If called in a non-void context, returns a guard object that automatically resets the override when it goes out of context. .Sp .Vb 4 \& { \& my $guard = LWP::Protocol::PSGI\->register($app); \& # hijack the code using LWP with $app \& } \& \& # now LWP uses the original HTTP implementations .Ve .Sp When \f(CW%options\fR is specified, the option limits which \s-1URL\s0 and hosts this handler overrides. You can either pass \f(CW\*(C`host\*(C'\fR or \f(CW\*(C`uri\*(C'\fR to match requests, and if it doesn't match, the handler falls back to the original \s-1LWP HTTP\s0 protocol implementor. .Sp .Vb 3 \& LWP::Protocol::PSGI\->register($app, host => \*(Aqwww.google.com\*(Aq); \& LWP::Protocol::PSGI\->register($app, host => qr/\e.google\e.com$/); \& LWP::Protocol::PSGI\->register($app, uri => sub { my $uri = shift; ... }); .Ve .Sp The options can take either a string, where it does a complete match, a regular expression or a subroutine reference that returns boolean given the value of \f(CW\*(C`host\*(C'\fR (only the hostname) or \f(CW\*(C`uri\*(C'\fR (the whole \&\s-1URI,\s0 including query parameters). .IP "unregister" 4 .IX Item "unregister" .Vb 1 \& LWP::Protocol::PSGI\->unregister; .Ve .Sp Resets all the overrides for \s-1LWP.\s0 If you use the guard interface described above, it will be automatically called for you. .SH "DIFFERENCES WITH OTHER MODULES" .IX Header "DIFFERENCES WITH OTHER MODULES" .SS "Mock vs Protocol handlers" .IX Subsection "Mock vs Protocol handlers" There are similar modules on \s-1CPAN\s0 that allows you to emulate \s-1LWP\s0 requests and responses. Most of them are implemented as a mock library, which means it doesn't go through the \s-1LWP\s0 guts and just gives you a wrapper for receiving HTTP::Request and returning HTTP::Response back. .PP LWP::Protocol::PSGI is implemented as an \s-1LWP\s0 protocol handler and it allows you to use most of the \s-1LWP\s0 extensions to add capabilities such as manipulating headers and parsing cookies. .SS "Test::LWP::UserAgent" .IX Subsection "Test::LWP::UserAgent" Test::LWP::UserAgent has the similar concept of overriding \s-1LWP\s0 request method with particular \s-1PSGI\s0 applications. It has more features and options such as passing through the requests to the native \s-1LWP\s0 handler, while LWP::Protocol::PSGI only allows one to map certain hosts and ports. .PP Test::LWP::UserAgent requires you to change the instantiation of UserAgent from \f(CW\*(C`LWP::UserAgent\->new\*(C'\fR to \f(CW\*(C`Test::LWP::UserAgent\->new\*(C'\fR somehow and it's your responsibility to do so. This mechanism gives you more control which requests should go through the \s-1PSGI\s0 app, and it might not be difficult if the creation is done in one place in your code base. However it might be hard or even impossible when you are dealing with third party modules that calls LWP::UserAgent inside. .PP LWP::Protocol::PSGI affects the \s-1LWP\s0 calling code more globally, while having an option to enable it only in a specific block, thus there's no need to change the UserAgent object manually, whether it is in your code or \s-1CPAN\s0 modules. .SH "AUTHOR" .IX Header "AUTHOR" Tatsuhiko Miyagawa .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright 2011\- Tatsuhiko Miyagawa .SH "LICENSE" .IX Header "LICENSE" This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. .SH "SEE ALSO" .IX Header "SEE ALSO" Plack::Client LWP::UserAgent