=head1 NAME PSGI::FAQ - Frquently Asked Questions and answers =head1 QUESTIONS =head2 General =head3 How do you pronounce PSGI? We read it simply P-S-G-I, but you may be able to pronounce it "sky" :) =head3 Why do we need this? Perl has L as a core module that somewhat abstracts the difference between CGI, mod_perl and FastCGI. However, most web application framework developers (e.g. Catalyst and Jifty) usually avoid using it to maximize the performance and to access low-level APIs. So they end up writing adapters for all of those different environments, some of which may be well tested while others are not. PSGI allows web application framework developers to only write an adapter for PSGI and the end users can choose whichever backends that supports the PSGI protocol. =head3 My framework already does CGI, FCGI and mod_perl. Why do I want to support PSGI? If your web application framework already does most of server environments and they perform really good and are well tested, there may not be a direct benefit as of today for you to support PSGI immediately. But if a CGI environment is already supported, supporting PSGI in addition should be extremely easy, and the benefit you and your framework users will enjoy is huge. =head3 How is PSGI protocol different from CGI PSGI protocol is designed to be very similar to that of CGI intentionally, so supporting PSGI in addition to CGI would be extremely easy. Here's a highlight of the key differences between CGI and PSGI: =over 4 =item * In CGI, servers are the actual web servers written in any languages but mostly in C, and script is a script that can be written in any language such as C, Perl, Shell scripts, Ruby or Python. In PSGI, servers are still web servers, but they're perl process that are usually embedded in the web server (like mod_perl) or a perl daemon process called by web server (like FastCGI), or an entirely perl based web servers. =item * In CGI, we use STDIN, STDERR and environment variables to read parameters and HTTP request body and send errors from the application. In PSGI, we use the C<$env> hash references and I and I stream to pass those between servers and applications. =item * In CGI, applications are supposed to print HTTP headers and body to STDOUT to pass it back to the web server. In PSGI, applications are supposed to return HTTP status code, headers and body (as an array ref or a filehandle-like object) to the application as an array reference. =back =head3 I'm writing a web application. What's the benefit of PSGI for me? If the framework you're using supports PSGI, that means your application can run on any of existent and feature PSGI implementations. Also, if you use the Plack standard API, the end users of your application should be able to configure and run your application in a bunch of different ways. =head3 What should I do to support PSGI? If you're a web server developer, write a PSGI implemenation that calls a PSGI application. Or join the development on Plack, the reference implementation of PSGI, to add backends for more web servers. If you're a web application framework developer, write an adapter for PSGI. Now you're freed from supporting all different server environments. If you're a web application developer (or a web application framework user), chose the framework that supports PSGI, or ask the author to support it. :) See L how to write PSGI applications, backends and adapters. =head3 Is PSGI faster than (my framework)? Again, PSGI is not an implementation, but there's a potential for a very fast PSGI implementation that preloads everything and runs fully optimized code as a preforked standalone with XS parsers and sendfile(2) kernel call, an event-based tiny web server written in C and embedded perl that supports PSGI, or a plain-old CGI.pm based backend that doesn't load any modules at all and runs pretty quickly without eating so much memory under the CGI environment. The reference implementation Plack already has a very fast backends like Standalone::Prefork and Coro. Users of your framework can chose which backend is the best for their needs. You don't need to think about lots of different user base with different needs. =head2 Plack =head3 What is Plack? What is the difference between PSGI and Plack? PSGI is a specification, so there's no software nor a module called PSGI. End users will need to choose one of PSGI implementations to write PSGI applications. Plack is a reference PSGI implementation that supports environments like prefork standalone server, CGI, FastCGI, mod_perl, AnyEvent and Coro. Plack also has useful APIs and helpers on top of PSGI, such as L to provide a nice object-oriented API on request objects, and L that allows you to run an PSGI application from the command line and configure it using C (a la Rack's Rackup). =head3 What kind of server backends would be available? In Plack, we already support most web servers like Apache2, and also the ones that supports standard CGI or FastCGI, but also want to support special web servers that can embed perl, like ngix. We think it would be really nice if Apache module mod_perlite and Google AppEngine support PSGI too, so you can run on your PSGI/Plack based perl app in the cloud. =head3 Ruby is Rack and JavaScript is Jack. Why is it not called Pack? Well Pack indeed is a cute name, but Perl has a built-in function pack so it's a little confusing, especially in the speech. =head3 What namespaces should I use to implement PSGI support? B. The PSGI namespace is reserved for PSGI specifications and reference unit tests that implementors have to pass. It should not be used by particular implementations. If you write a plugin or an extension to support PSGI for an (imaginary) web application framework called C, name the code such as C. If you write a PSGI backend that runs on an imaginary pure perl web server called C, name it such as C or consider contributing the code to L project as C (by doing so you don't need to worry about how to run/load PSGI applications). =head2 HTTP::Engine =head3 Why PSGI/Plack instead of HTTP::Engine? HTTP::Engine was a great experiment, but it mixed the specification with implementations, and the monolithic class hierarchy and role based interfaces makes it really hard to write a new backend. We kept the existent HTTP::Engine and broke it into three parts: The Spec (PSGI), Reference implementations (Plack::Impl) and Standard APIs and Tools (Plack). =head3 Will HTTP::Engine be dead? It won't be dead but won't be actively developed anymore. Instead, HTTP::Engine will become a I thin API on top of Plack. Your application written in HTTP::Engine should continue to work using L. =head2 API Design Keep in mind that most design choices made in the PSGI spec are to minimize the requirements on backends so they can optimize things. Adding a fancy interface or allowing flexibility on PSGI layers might sound catchy to end users, but it would just add things that backends have to support, which would end up getting in the way of optimizations, or introducing more bugs. What makes a fancy API to attract web application developers is your framework, not PSGI. =head3 Why a big env hash instead of objects with APIs? The simplicity of the protocol is the key that made WSGI and Rack successful. PSGI is a low-level protocol between backends and web application framework developers. If we define an API on what type of objects should be passed and which method they need to implement, there will be so much duplicated code in the backends, some of which may be buggy. For instance, PSGI defines C<< $env->{REMOTE_ADDR} >> as a string. What if the PSGI spec required it to be an instance of Net::IP? Backend code would have to depend on the Net::IP module, or have to write a mock object that implements ALL of Net::IP's methods. Backends depending on specific modules or having to reinvent lots of stuff is considered harmful and that's why the protocol is as minimal as possible. Making a nice API for the end users is a job that web application frameworks (adapter developers) should do, not something PSGI needs to define. =head3 Why is the application a code ref rather than an object with a ->call method? Requiring an object I a code ref would make ALL backend's code a few lines more tedious, while requiring an object I a code ref would make application developers write another class and instantiate an object. Requiring an application ALWAYS be an object instead of a code ref would also work, but then application developers always have to define a class and instanciate the object. The benefit of requiring an object instead of a code ref would be that it gives middleware developers a chance to call some methods on the application instead of the standard C method. However, that can also be done also by setting values or callbacks in the environments hash reference. The problem still remains to fill the gap of how the application should be initialized and by who. This is a solved problem in Ruby's Rack and Python's WSGI and we'll clone that: L takes a C file where users can preloads their framework code, setup anything they need, add middleware, and then return a code reference that is a PSGI application. =head3 Why should the headers returned as an array ref and not a hash ref? Short: In order to support multiple headers (e.g. C). Long: In Python WSGI, the response header is a list of (C, C) I i.e. C so there can be multiple entries for the same header key. In Rack and JSGI, header value is a String consisting of lines separated by "C<\n>". We liked Python's specification here, and since Perl hashes don't allow multiple entries with the same key (unless it's Cd), using an array reference to store C<< [ key => value, key => value ] >> is the simplest solution to keep both framework adapters and backends simple. Other options, like allowing an array ref in addition to a plain scalar, makes either side of the code unnecessarily tedious. Note that I'm talking about multiple header lines with the same key, and NOT about multiple header values (e.g. C). Joining the header values with C<, > is obviously the applications' job. L does exactly that when it's passed an array reference as a header value, for instance. The other option is to always require the application to set value as an array ref, even if there is only one entry: this would make backend's code less tedious, but, for the exact reason of multiple header values vs. multiple header lines with the same name mentioned in the paragraph before, I think it's confusing. =head3 No iterators support in $body? We learned that WSGI and Rack really enjoy the benefit of Python and Ruby's language beauty, which are iterable objects in Python or iterators in Ruby. Rack, for instance, expects the body as an object that responds to the C method and then yields the buffer, so body.each { |buf| request.write(buf) } would just magically work whether body is an Array, FileIO object or an object that implements iterators. Perl doesn't have such a beautiful thing in the language unless L is loaded. And PSGI should not make autobox as a requirement, hence we only support a simple array ref or file handles. Writing an IO::Handle-like object is pretty easy since it's only C and C. You can also use PerlIO to write such an object that behaves like filehandle, even though it might be considered a little unstable. =head3 What if I want to stream content or do a long-poll Comet? A callback-based API is supported with L. =head3 Why CGI-style environment variables instead of HTTP headers as a hash? Most existent web application frameworks already have code or a handler to run under the CGI environment. Using CGI-style hash keys instead of HTTP headers makes it so easy for the framework developers to implement an adapter to support PSGI. For instance, L only differs in a few dozens of lines from L and was written in less than an hour. =head1 SEE ALSO WSGI's FAQ which clearly answers lots of questions about how some API design decisions were made, some of which can directly apply to PSGI. L =head1 MORE QUESTIONS? If you have a question that is not answered here, or things you totally disagree with, come join the IRC channel #http-engine on irc.perl.org or mailing list L. Be sure you clarify which hat you're wearing: application developers, server implementors or middleware developers. And don't criticize the spec just to criticize it: show your exact code that doesn't work or get too messy because of spec restrictions etc. We'll ignore all nitpicks and bikeshed discussion. =head1 AUTHOR Tatsuhiko Miyagawa Emiyagawa@bulknews.netE =head1 COPYRIGHT AND LICENSE =cut