I need to handle some HTTP URLs in a Perl program, but I have doubts how should the URI class help me.
Particularly, I'd like the to use the URI class for resolving relative URLs and getting their components. However, the problems are:
I need a function to work with both URI objects and URI strings as arguments (or ensure only one gets passed)
sub foo_string_or_url {
my $uri = URI->new(shift);
is that the right approach? I don't quite like it, because it stringifies the URI and creates new object unnecessarily.
Extract the components
my $host = $uri->host;
This is also problematic, because not all URIs have host, particularly, if someone passes garbage to the function, this will die().
Resolve a relative URL
my $new_url = URI::URL->new($uri, $base)->abs;
IIUC, without the ->abs, the result will still stringify to the relative URL (and will not work for HTTP::Requests), am I right? Also, is this guaranteed to return a URI?
How should I handle these problems? The possibilities are
Use ->isa('URI') and ->can("host") all the time
Seems error prone and ugly to me
Don't use URI class at all and parse URLs using regexes
I'd still rather use a library solution than debug my own
Wrap URI operations in try { ... } catch { ... }
see the first point
Is there a sane, fool-proof way of using the URI classes? Something simple I haven't thought of (in the list above)?
I think your question can be summarised: parameter validation is tedious, what do I do about it?
I don't like it, either. This is a matter of differing opinion among developers, other say coercions are better than sliced bread, especially when automatically done by Moose. I argue that allowing only one type of simplifies the program. Also, YAGNI applies in the vast majority of cases. Reject wrong types, employ a helper module such as Params::Validate/MooseX::Method::Signatures/MooseX::Declare in order to avoid the manual checks as shown in your code samples.
This is the desired behaviour. Exception handling mechanisms let you write custom code appropriate for each situation. If you think it's not aesthetically pleasing, remove it and mind the consequences of letting exceptions go unchecked.
use Try::Tiny;
my $host;
try {
$host = $uri->host;
} catch {
warn "Could not determine host for $uri. Message was: $_. Retry/abort/ignore?\n";
…
};
Yes and yes.
Related
I have a large Catalyst app and want to get a list of all endpoints it supports (bonus points if it can tell me if the request method). Is there some easy way to ask Catalyst to list them?
Catalyst does not know the full set of paths. The true dispatch paths are resolved dynamically, iterating through DispatchType classes until one responds favourably to a call of match.
The debug option does a one-time enumeration of all possibilities that your controllers allow. If you want to interfere with this, you have to look at Catalyst::Dispatcher::_display_action_tables
It's a tree-walking algorithm that iterates through each route it finds at '/' and follows each subsequent route that $controller->actions returns. It's not easy to read, but you could conceivably implement a version of _display_action_tables that doesn't just print to a table, but does something else instead. Then call it in the live application with $c as argument and see what happens!
Can someone give me some direction on the best way to do when sharing a $dbh variable between "objects" in different .pm files.
For instance, my main module say Foo.pm has a new constructor, etc and I could give it a dbh or create a dbh and then share it by passing it as a parameter to the new constructor for Bar.pm, and then re-assigning inside Bar->new, but that seems like I'm doing a lot of work managing this variable.
Is this a simple, yet elegant way to do this? I've researched Exporter and a few other examples, but none seem to be straight forward.
Thanks!
I suppose that what you actually want is to take the control over $dbh creation out of the code that works with it. Most trivial way is, well,
my $dbh;
sub get_dbh {
if ( $dbh is bad ) {
reconnect or whatever
}
return $dbh || die;
}
And then in your code access it like
get_dbh()->do("your sql");
You could put that get_dbh() function to a separate module and call it from anywhere in your project - as usual with perl, it will be included only once and its local static variable $dbh will exist in only one copy within the perl process.
There are many possible ways to achieve that, writing a function like described above (and maybe passing a reference to that function instead of passing the $dbh) is one. There are plenty of others, depending on your design and personal taste - a singleton class, a variable tied to the function described above, or even a class that imitates DBI... That's up to you, but that should be one piece of code, spreading this logic all over your project is a bad idea.
If you're using Moose to build your object, you could encapsulate your database handle in a role and require it into classes that need the database access.
i've got a problem that i wasn't able to solve yet, and hope you can help :)
i have build a CataPLACK-Application with a web-interface. Now i am supposed to establish a JSON/REST/XML-Api, so i thought i could do something like this:
/ => root
/blog/ => ...
/news/ => ...
/api =>chainedTo(root) PathPart(api) Args(1) { set_view($arg) };
how do i loop back api to root (/), so i can redispatch the whole request with a different view without having to establish a lot of "fake routines" ?
i feel there must be a clean way ...
Have a look at the differences between $c->forward / $c->detach and $c->visit / $c->go in the manual. I think you'll find you can probably build a $c->go() construct from within your api method that achieves what you're after.
It's still a bit messy though, particularly if you have to de-reference the URI back to an action manually.
You can achieve the same effect with a lot less hassle by adding the 'api' path-part at the end rather than the beginning, so it just becomes an argument to the request that you can test for in your auto sub, and set whatever stash variables you need. Then you don't need to do any re-dispatching. Only you can decide whether such a URI scheme will be clean enough and appropriate for your application.
I have seen the examples of Net::OpenID::Consumer::Lite on CPAN but I was hoping to get a single script that uses POST method. If nobody has this than I will post my solution back here once I get it working.
This seems to be the only applicable test in the manifest and it doesn't seem too useful
http://cpansearch.perl.org/src/TOKUHIROM/Net-OpenID-Consumer-Lite-0.02/xt/001_mixi.t Apache2::AuthMixi also uses it a bit
This module simply delegates to LWP::UserAgent. I don't like it, it should subclass LWP::UserAgent instead of delegating. You can find the docs for LWP::UserAgent on cpan, and access the base copy through the hidden method _ua (though, by convention, the preceding underscore tells you it isn't supported and it is supposed to be kept secret)
my $csr = Net::OpenID::Consumer::Lite->new();
$csr->_ua->post(); # same as LWP::UserAgent::post()
It seems as if you're supposed to use only handle_server_response() which calls _check_authentication() which calls _get() which delegates to ->_ua->get().
check_authentication() wants an HashRef jump-table with 5 events for not_openid, setup_required, cancelled, verified, and error. In addition I believe it wants a bunch of key (openid.) prefixed stuff, and values.
Per the code, for a request to be sent $request->{'openid.mode'} must exist in the $request and be set (preferably to) check_authentication, and not set to 'cancel'. The openid.user_setup_url key must logically not be set or it will just call the respective callback. It must also have an op_endpoint.endpoint key set, which is where the request is destined to go.
This code isn't hard to read, I'd suggesting taking a look The author also seems to have a bunch of modules which is a good sign. I don't like jump-tables with data like that, it seems kind of weird from a UI perspective.
A little known built-in Perl feature is attributes. However, the official documentation is doing a rather bad job introducing newbies to the concept. At the same time, frameworks like Catalyst use attributes extensively which seems to make many things easier there. Since using something without knowing the implications sucks a bit, I'd like to know the details. Syntax-wise they look like Python's decorators, but the documentation implies something simpler.
Could you explain (with real-world examples if possible) what attributes are good for and what happens behind the doors?
You are right, the documentation is not very clear in this area, especially since attributes are not so complicated. If you define a subroutine attribute, like this:
sub some_method :Foo { }
Perl will while compiling your program (this is important) look for the magic sub MODIFY_CODE_ATTRIBUTES in the current package or any of its parent classes. This will be called with the name of the current package, a reference to your subroutine, and a list of the attributes defined for this subroutine. If this handler does not exist, compilation will fail.
What you do in this handler is entirely up to you. Yes, that's right. No hidden magic whatsoever. If you want to signal an error, returning the name of the offending attributes will cause the compilation to fail with an "invalid attribute" message.
There is another handler called FETCH_CODE_ATTRIBUTES that will be called whenever someone says
use attributes;
my #attrs = attributes::get(\&some_method);
This handler gets passed the package name and subroutine reference, and is supposed to return a list of the subroutine's attributes (though what you really do is again up to you).
Here is an example to enable simple "tagging" of methods with arbitrary attributes, which you can query later:
package MyClass;
use Scalar::Util qw( refaddr );
my %attrs; # package variable to store attribute lists by coderef address
sub MODIFY_CODE_ATTRIBUTES {
my ($package, $subref, #attrs) = #_;
$attrs{ refaddr $subref } = \#attrs;
return;
}
sub FETCH_CODE_ATTRIBUTES {
my ($package, $subref) = #_;
my $attrs = $attrs{ refaddr $subref };
return #$attrs;
}
1;
Now, in MyClass and all its subclasses, you can use arbitrary attributes, and query them using attributes::get():
package SomeClass;
use base 'MyClass';
use attributes;
# set attributes
sub hello :Foo :Bar { }
# query attributes
print "hello() in SomeClass has attributes: ",
join ', ', attributes::get(SomeClass->can('hello'));
1;
__END__
hello() in SomeClass has attributes: Foo, Bar
In summary, attributes don't do very much which on the other hand makes them very flexible: You can use them as real "attributes" (as shown in this example), implement something like decorators (see Mike Friedman's article), or for your own devious purposes.
Attributes are one of the things that if you don't know how to use them, you shouldn't bother with them. I once made a database_method attribute, to indicate to the system that a record set would be requested before entering this method and that the method knew it's main inputs would come from the stored procedure it corresponded to.
I was using attributes to wrap the actual, specified actions with that data. So one of the really seemingly useful ideas is to wrap methods with indirection, but it was harder to make caller work, without overriding it. In the end it was much too visible as an "expert-only" feature and would have required support to trace through the arcane innards--something you want to avoid, if you write Perl in a perl-also shop.
I take from the article cited by the other answer:
Caveats
Although this is a powerful technique, it isn't perfect. The code will not properly wrap anonymous subroutines, and it won't necessarily propagate calling context to the wrapped functions. Further, using this technique will significantly increase the number of subroutine dispatches that your program must execute during runtime. Depending on your program's complexity, this may significantly increase the size of your call stack. If blinding speed is a major design goal, this strategy may not be for you.
These are significant drawbacks unless you're willing to override caller. I don't care about "blinding speed" quite as much, and I'm half-willing to try my hand at overriding caller to bypass any subroutine that registers itself as "DO_NOT_REPORT" -- but I have some coding foolhardiness that hasn't yet been beaten out of me, too.
Even the article admits how ill-documented this feature is, and contains this caveat. Tell me when else it has been a good idea to use a snazzy, obscure feature? That often enough, people end up putting in the UNIVERSAL namespace to avoid the inheritance issue.