-
Notifications
You must be signed in to change notification settings - Fork 3
Interface based on IO subset
This wiki article describes a hypothetical server-to-application interface based on an IO object that implements a subset of Ruby's IO class interface. For lack of a better name, we'll call this object the IO object.
These are the only methods that need to be implemented on the IO object given to the application.
- read([length [, outbuf]])
- write(string)
- Also aliased as
<<
- Also aliased as
- close
By limiting the interface to only 3 methods, web server and framework developers can easily abstract, defer, or otherwise re-implement calls to these methods if needed. The interface is compatible with any standard Ruby IO object, which of course includes Sockets, which will likely be the most common object passed to Rack Next applications.
It's anticipated frameworks will implement buffering mechanisms and special interfaces for adding headers as needed. It's also quite likely that higher-level code, such as middleware, will inspect the type of IO object provided and leverage additional functionality provided by different types of IO-like objects.
Like Rack, it makes sense to continue using the call
method as the interface for applications. It's quite flexible, and makes the interface compatible with Proc objects.
call
is expected to take a single argument, which is the IO object. The return value is ignored. Any "result" should be written directly to the IO object.
Unlike the current situation where frameworks are built on-top of the Rack framework, it's anticipated that with Rack Next, frameworks won't be built on top of anything. Instead, they'll work with the raw IO object, leveraging components of the Rack Next library wherever relevant at their convenience.
In Rack, the config.ru file defines via a DSL what endpoint to call; this is achieved using the run
method call. In Rack Next, it is up to the server to specify how this is defined, whether it be by command line options or part of a server configuration file. The only two required pieces of information are: what Ruby file to load, and what object to call
, represented as a constant.
A simple yet low-level interface like this lowers the barrier of entry for coding closer to the metal, and gets higher-level web developers thinking in terms of streams. It achieves without sacrificing flexibility. Such an interface makes it relatively trivial to implement a compatibility layer for running legacy Rack applications on servers designed for Rack Next.