Strelka is a framework for creating and deploying Mongrel2 web applications in Ruby.
It's named after a lesser known Russian cosmonaut who was one of the first canine space travelers to orbit the Earth and return alive. Her name means “little arrow”.
Mongrel2 1.8.0 or better
Ruby 2.2 or better
$ gem install strelka
We're going to assume you've already built and installed the Mongrel2 daemon. If not, please refer to the Mongrel2 documentation and get that ready.
Mongrel2 loads its configuration from a SQLite database. You can create the this database in any fashion you like, but the Mongrel2 ruby module includes a command-line tool called m2sh.rb that'll let you quickstart a server if you just want to experiment. If you've already installed the strelka gem, then it will already have been installed as a dependency.
To bootstrap a basic server, configure it, and run it:
$ mkdir strelka-tryout $ cd !$ $ m2sh.rb quickstart
This will generate a Ruby DSL config, then invoke an editor on it.
Make sure the config has a line like:
route '/hello', handler( 'tcp://127.0.0.1:9999', 'helloworld' )
in the 'host' section; that's the part of the Mongrel2 server we'll be talking to.
The quickstart will generate a SQLite configuration database for use with Mongrel2 in your current working directory, with the default required directory structure. Mongrel2 will listen on port 8113 (unless you changed it), and send all requests starting at the URI /hello to a handler called helloworld.
If you stop the server (Ctrl-C will do so), you can restart it like so:
$ m2sh.rb start
Now that the Mongrel2 daemon is up and running, we can move forward and create our first application!
A Minimal Application
Strelka applications are subclasses of the Strelka::App class. Strelka::App is pretty minimal by itself; it inherits most of its behavior from the basic Mongrel2::Handler class, only adding a few convenience methods for common HTTP tasks.
A minimal application would look something like:
#!/usr/bin/env ruby require 'strelka' class HelloWorldApp < Strelka::App def handle_request( request ) response = request.response response.content_type = 'text/plain' response.puts( "Hello, World!" ) return response end end # class HelloWorldApp # Run the app HelloWorldApp.run if __FILE__ == $0
While functional, this application is pretty dumb, and making it do anything more intelligent on your own would require a bunch of additional code and accompanying tests. Fortunately, Strelka already has done the heavy lifting. It knows how to read the Mongrel2 configuration and hook your app up with the right sockets to talk to the Mongrel2 front end (providing you follow one of several simple conventions), provides hooks into the lifecycle of an HTTP request, and includes a plugin system that uses these hooks to handle common application tasks. This allows you to mix in the specific framework parts you need, so you get exactly what you want and nothing more.
Talking to Mongrel2
Mongrel2 associates handlers with itself via an identifier, which is described in the Mongrel2 manual as a UUID, but can actually be any string consisting of dashes and alphanumeric characters. Strelka reads the Mongrel2 config database, and can automatically configure its apps to talk to the right socket with the right send_ident if it can find them. It gives you a couple of different ways of doing this. It will default to a string derived from the name of the class, or you can set it yourself by declaring an ID constant in your application class. If you need more control, you can also override the ::run class method and super with the right appid:
class HelloWorldApp # Run as a tester if not running in the production environment def self::run appid = if Socket.gethostname.include?( 'test' ) 'helloworld-test' else 'helloworld' end super( appid ) end end
Because our config.sqlite configuration directs requests to / to be sent to the helloworldapp handler, Strelka will automatically find and pair this route to Mongrel2 when run.
Run this handler, then point a browser to http://localhost:8080/. If you see the text “Hello, World!”, congrats! We'll build off of this in the next section, the Strelka Tutorial.
If you want your app to be launchable via the strelka command, you can do so by registering it with the Strelka::Discovery module. For instance, if your app is defined in a file called lib/acme/store.rb and you want to start it with the command
strelka start acme-store
then you'd do something like:
require 'strelka/discovery' Strelka::Discovery.register_app( 'acme-store', 'acme/store.rb' )
If you want the app to be launchable directory from the gem, you can put the above discovery code in a file named lib/strelka/apps.rb to your gem. The `strelka` command will load all of those files from any installed gems before running start. You can test to see which apps are discoverable this way using the strelka discover command.
See Strelka::Discovery for more info.
You'll likely want to start with the Tutorial.
Going forward, we're going to be extracting useful stuff out of our own applications as plugins, and finishing up the packaging and deployment stories once we've ironed out the details in own environment.
Here's a tentative list of what kinds of stuff we have planned:
CORS – manage Cross-Origin Resource Sharing headers, especially for service applications
caching – utilities for easy HTTP caching
New Application Styles
Create some new handler classes for different application styles, similar to those in the Tir framework.
Support for sending partial responses via the Chunked encoding.
After checking out the source, run:
$ rake newb
This task will install any missing dependencies, run the tests/specs, and generate the API documentation.
Copyright © 2011-2016, Michael Granger and Mahlon E. Smith All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of the author/s, nor the names of the project's contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.