Results tagged “psgi”

leaves falling off the tree

For me, one of the promises of PSGI and Plack is to get away from programming with global variables in Perl, particularly being able to modify the request object after it’s been created. Long ago, CGI.pm replaced using a global

%FORM
hash with a “query object”, but it essentially has been used as always-accessible read/write data structure.

It would appear at first look that improving this might a fundamental part of the new system: A lexical environment hashref is explicitly passed around, as seen here:

Plack::Request->new($psgi_env);

vs the old implicit grab from the environment:

CGI->new;

You might hope to be escaping some of th action-at-a-distance badness of global variables, like having a change to environment alter your object after the object is created. You might like avoid having changes made to your object avoid changing the global environment as well.

Not only does Plack::Request require an explicit environment hash to be passed in, both nearly all methods are read-only, including a param() method inspired by a read/write method from CGI.pm of the same name. That’s all good.

This would all seem to speak to safety and simplicity for using Plack::Request, but the reality turns out to be far muddier than you might hope. I encourage you to down and run this short, safe interactive perl script which illustrates some differences. It shows that:

  • Plack::Request objects can be altered after they are created by changing the external environment.
  • Modifying a Plack::Request object can potentially alter the external environment hash (Something which CGI.pm explicitly does not allow).

In effect, the situation with global variables is in some regards worse. Plack::Request provides the impression that there is a move away from action-at-distance programming, but the fundamental properties of being affected by global changes and locally creating them are still present.

On the topic of surprising read/write behavior in Plack::Request, you may also interested to note the behavior of query_parameters(), body_parameters() and parameters() is not consistent in this regard. I submitted tests and suggestion to clarify this, although that contribution has not yet been accepted.

Here’s the deal: The hashref returned by query_parameters() and body_parameters() and parameters() are all read/write — subsequent calls to the same method return the modified hashref.

However, modifying the hashes returned by body_parameters() or query_paremeters() does not modify the hashref returned by parameters(), which claims to be a merger of the two.

It seems that either all the return values should be read-only, ( always returning the same values ), or if modifying them is supported then the parameters() hash should be updated when either of the body_parameters() or query_parameters() hashes are updated.

Reflections

An incoming HTTP request to your server is by it’s nature read-only. It’s analogous to a paper letter being delivered to you be postal mail.

It’s a perfect application for an immutable object object design that Yuval Kogman eloquently advocates for. Plack::Request comes close to implementing the idea with mostly read-only accessors, but falls short. The gap it leave unfortunately carries forward some possibilities for action-at-distance cases that have been been sources of bugs in the past. I’d like to see Plack::Request, or some alternative to it, with the holes plugged: It should copy the input, not modify it by reference, and parameter related methods should also return copies rather than reference to internal data structures.

baby sleeps again I’ve spent a lot time recently triaging bugs for CGI.pm. I’ve enjoyed the process, and respect CGI.pm as a widely used Perl module. I’m not in love all aspects of module. I don’t use or recommend the HTML generation features— I recommend using HTML template files and HTML::FillInForm for filling them.

Whenever I think about how I’d like to change CGI.pm,what I have mind is often the same choice that CGI::Simple made. There was a time years ago that I focused my attention on CGI::Simple and tried it in production, only to be bit by a compatibility issue, so I reverted back to CGI.pm. I don’t remember what the specific issue, and it’s likely been fixed by now. But the pragmatic point remained with me: CGI::Simple may have clean code and a good test suite, but it’s not necessarily free of defects and in particularly it lacks the vastly larger user base that CGI.pm has to provide real world beta testing.

1
Close