Results tagged “Plack”

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, replaced using a global
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 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](/blog/2011/02/ 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 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.
A midwinter box bike ride
Recently I've been reviewing how various Perl frameworks and modules generate HTTP headers. After reviewing several approaches, it's clear that there are two major camps: those which put the response headers in a specific order and those which don't. Surely one approach or the other would seem like it would be more spec-compliant, but RFC 2616 provides [conflicting guidance on this point]( The bottom line is that spec says that *"the order in which header fields with differing field names are received is not significant"*. But then it goes on to say that it is a "good practice" (and it puts "good practice" in quotes) to order the headers a particular way. So, without strict guidance from the spec about the importance of header ordering, it would be interesting to know if header order caused a problem in practice. The [Plack::Middleware::RearrangeHeaders]( documentation suggests there is some benefit to strict header ordering: *"to work around buggy clients like very old MSIE or broken HTTP proxy servers"* You might wonder what the big deal is-- why not just stick to the "good practice" recommendation all the time? The difference can be seen in the benchmarks provided by [HTTP::Headers::Fast]( By ignoring the good-practice header order, an alternate implementation was able to speed-up header generation to be about twice as fast. Considering that a web-app needs to generate a header on every single request, making header generation smaller and faster is potentially a tangible win, while also still being spec-compliant.