strelka 0.0.1.pre.295 → 0.0.1.pre.301

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data.tar.gz.sig CHANGED
Binary file
data/ChangeLog CHANGED
@@ -1,8 +1,37 @@
1
+ 2012-08-24 Mahlon E. Smith <mahlon@martini.nu>
2
+
3
+ * examples/strelka.conf.example:
4
+ Add a documented example configuration file.
5
+ [9d8ce0e99016] [tip]
6
+
7
+ 2012-08-23 Mahlon E. Smith <mahlon@martini.nu>
8
+
9
+ * spec/strelka/paramvalidator_spec.rb:
10
+ Oop, fix test copy/paste.
11
+ [59ad6d4842e2]
12
+
13
+ * lib/strelka/paramvalidator.rb, spec/strelka/paramvalidator_spec.rb:
14
+ Finish the uuid built-in for ParamValidator.
15
+ [f854a54dda0b]
16
+
17
+ 2012-08-16 Michael Granger <ged@FaerieMUD.org>
18
+
19
+ * lib/strelka/app/restresources.rb:
20
+ Don't try to auto-create restresource routes for no-param datasets,
21
+ either.
22
+ [10af8924212c] [github/master]
23
+
24
+ 2012-08-13 Michael Granger <ged@FaerieMUD.org>
25
+
26
+ * lib/strelka/multipartparser.rb:
27
+ Fix a debugging statement on Strelka::MultipartParser (Mike Hix)
28
+ [329ce8f7c57c]
29
+
1
30
  2012-08-10 Michael Granger <ged@FaerieMUD.org>
2
31
 
3
32
  * lib/strelka/app/errors.rb:
4
33
  Make the error-handler info log less spammy
5
- [39a1afa23a17] [tip]
34
+ [39a1afa23a17]
6
35
 
7
36
  * lib/strelka/httprequest.rb:
8
37
  Make the debugging log for non-form entity bodies a bit less scary
@@ -974,7 +1003,7 @@
974
1003
 
975
1004
  * lib/strelka/app/errors.rb, spec/strelka/app/errors_spec.rb:
976
1005
  Add documentation for the Errors plugin, improve test coverage.
977
- [ff3ef6e5a7a1]
1006
+ [ff3ef6e5a7a1] [github/master@default]
978
1007
 
979
1008
  * Manifest.txt:
980
1009
  Add session files to the manifest
data/Deploying.rdoc ADDED
@@ -0,0 +1,83 @@
1
+ ---
2
+ title: Deploying a Strelka App
3
+ layout: default
4
+ index: 4
5
+ filters:
6
+ - erb
7
+ - links
8
+ - examples
9
+ - textile
10
+ ---
11
+
12
+ h2. <%= page.config['title'] %>
13
+
14
+ <div id="auto-toc"></div>
15
+
16
+ Strelka uses the Rubygems plugin system to find and load applications. You don't need to necessarily package them up this way if you've already got a deployment strategy in mind, but the rest of this manual assumes you will be.
17
+
18
+ ** Include their static content and the apps themselves in their data dir
19
+ ** Include any library code in lib/
20
+ * These instructions use Hoe, but you don't need to necessarily use that
21
+
22
+ h3. Setting up the Project
23
+
24
+ First you'll need to create the project layout. It should look something like this:
25
+
26
+ !images/project-layout.png(Example project layout screenshot)!
27
+
28
+ The data directory should contain your apps, templates, and any static content your app requires in a directory with the same name as your gem. Strelka's runtime environment will look for them there, though most of them can be configured to look elsewhere. The presence of an @apps@ subdirectory is what Strelka looks for when searching for installed application gems.
29
+
30
+ The rest of the gem is "pretty standard":http://chneukirchen.github.com/rps/: Your applications' reusable code should be under @lib/@ and @ext/@ directories, and tests or specs under @test/@ and @spec/@, respectively.
31
+
32
+ h4. Easy Setup with Hoe
33
+
34
+ Hoe is a Rake helper that provides tasks for setting up and maintaining a project. It comes with a tool called 'sow' that generates a project based on a template directory. Strelka includes a Hoe project template in its @contrib/hoetemplate@ directory. If you copy that directory into @~/.hoe_template@:
35
+
36
+ bc. $ sow #(run once to set up the template directory if you don't have one)
37
+ $ cp -r contrib/hoetemplate ~/.hoe_template/strelka
38
+
39
+ you can generate a new project like so:
40
+
41
+ bc.. $ sow -s strelka GoodDoggie
42
+ erb: .autotest.erb
43
+ erb: History.rdoc.erb
44
+ erb: Manifest.txt.erb
45
+ erb: README.rdoc.erb
46
+ erb: Rakefile.erb
47
+ erb: data/good_doggie/apps/file_name_app
48
+ erb: data/good_doggie/templates/layout.tmpl.erb
49
+ erb: data/good_doggie/templates/top.tmpl.erb
50
+ erb: lib/file_name.rb.erb
51
+ erb: spec/file_name_spec.rb.erb
52
+
53
+ ... done, now go fix all occurrences of 'FIX':
54
+
55
+ GoodDoggie/data/good_doggie/apps/good_doggie_app:10: ID = 'FIX' # (set the app id of the main application)
56
+ GoodDoggie/data/good_doggie/templates/layout.tmpl:5: FIX (application title)
57
+ GoodDoggie/data/good_doggie/templates/layout.tmpl:9: <!-- FIX (set up the main layout template) -->
58
+ GoodDoggie/data/good_doggie/templates/top.tmpl:1:<!-- FIX (set up the main content template) -->
59
+ GoodDoggie/lib/good_doggie.rb:3:# FIX (top-level documentation)
60
+ GoodDoggie/Rakefile:17: self.developer 'FIX', 'FIX' # (name, email)
61
+ GoodDoggie/README.rdoc:3:* FIX (url)
62
+ GoodDoggie/README.rdoc:7:FIX (describe your package)
63
+ GoodDoggie/README.rdoc:15:Copyright (c) 2011, FIX
64
+
65
+ p. Now just fix all the "FIX" items.
66
+
67
+ Strelka looks for handler apps in the 'apps' subdirectory of your gem's datadir, so in our example, the app is @GoodDoggie/data/good_doggie/apps/good_doggie_app@:
68
+
69
+ bc.. # The main GoodDoggie application
70
+ class GoodDoggie::Application < Strelka::App
71
+
72
+ # Uncomment this if you need an appid other than
73
+ # 'gooddoggie-application'.
74
+ #ID = 'FIX' # (set the app id of the main application)
75
+
76
+
77
+ p. The End
78
+
79
+
80
+
81
+
82
+
83
+
data/Manifest.txt CHANGED
@@ -1,11 +1,14 @@
1
1
  .gemtest
2
2
  ChangeLog
3
+ Deploying.rdoc
3
4
  History.rdoc
4
5
  IDEAS.rdoc
5
6
  MILESTONES.rdoc
6
7
  Manifest.txt
8
+ Plugins.rdoc
7
9
  README.rdoc
8
10
  Rakefile
11
+ Tutorial.rdoc
9
12
  bin/strelka
10
13
  contrib/hoetemplate/History.rdoc.erb
11
14
  contrib/hoetemplate/Manifest.txt.erb
@@ -26,6 +29,7 @@ examples/config.yml
26
29
  examples/gen-config.rb
27
30
  examples/static/examples.css
28
31
  examples/static/examples.html
32
+ examples/strelka.conf.example
29
33
  examples/templates/auth-form.tmpl
30
34
  examples/templates/auth-success.tmpl
31
35
  examples/templates/layout.tmpl
data/Plugins.rdoc ADDED
@@ -0,0 +1,201 @@
1
+ ---
2
+ title: Write Your Own Strelka Plugin
3
+ layout: default
4
+ index: 5
5
+ filters:
6
+ - erb
7
+ - api
8
+ - links
9
+ - examples
10
+ - textile
11
+ ---
12
+
13
+ h2. <%= page.config['title'] %>
14
+
15
+ <div id="auto-toc"></div>
16
+
17
+ h3. Overview
18
+
19
+ Because Mongrel2 makes it easy to have discrete handler processes
20
+ managing different URI routes, you'll quickly find benefit from
21
+ refactoring common code into reusable components.
22
+
23
+ As mentioned in the <?link "tutorial":Strelka Tutorial ?> section,
24
+ Strelka breaks out functionality into a set of core plugins that allow
25
+ you to cherry pick the capabilities you need. It's easy to create your
26
+ own plugins for optional loading of shared behavior into any number of
27
+ handlers.
28
+
29
+ This page is a walkthrough for creating an example Strelka plugin that
30
+ logs all HTTP accesses to a "SQLite":http://www.sqlite.org/ database.
31
+
32
+ h3. The Basics
33
+
34
+ A Strelka plugin is just a module under the <?api Strelka::App ?>
35
+ namespace that is extended by the <?api Strelka::Plugin ?> class.
36
+ Once extended, the plugin participates in the @request@ -> @response@
37
+ lifecycle, and is able to alter it via hooks. The plugin only
38
+ participates for handlers that load it via the @plugin@ declarative.
39
+
40
+ Lets start by creating and naming an empty plugin. We'll call it
41
+ @dblogger@.
42
+
43
+ <?example { lang: Ruby, caption: "A no-op plugin" } ?>
44
+ require 'strelka'
45
+ require 'strelka/app'
46
+
47
+ module Strelka::App::DBLogger
48
+ extend Strelka::Plugin
49
+ end
50
+ <?end example ?>
51
+
52
+ It's important to save the plugin under a path that Strelka can
53
+ locate it. It can go anywhere in your @$LOAD_PATH@, but should be under a
54
+ @lib/strelka/app@ subdirectory, and the filename should match the class.
55
+
56
+ We'll save this to @lib/strelka/app/dblogger.rb@, and Strelka
57
+ applications can use it like so:
58
+
59
+ <?example { lang: Ruby, caption: "Using the dblogger plugin" } ?>
60
+ require 'strelka'
61
+
62
+ class ExampleApplication < Strelka::App
63
+ plugins :routing, :dblogger
64
+
65
+ get do |req|
66
+ res = req.response
67
+ res.content_type = 'text/plain'
68
+ return res.body << "Hi! I'll be logged!"
69
+ end
70
+ end
71
+
72
+ ExampleApplication.run
73
+ <?end example ?>
74
+
75
+
76
+ h3. Load Order
77
+
78
+ The request is passed through plugins sequentually. You can control
79
+ where in the chain your plugin belongs, by using the @run_before@ and
80
+ @run_after@ methods. Both methods accept a comma separated list of
81
+ other plugin names.
82
+
83
+ In this example case, we want the logger to log the request before the
84
+ other core plugins run, so any errors still make it out to the log.
85
+
86
+ <?example { lang: Ruby, caption: "Adding load order" } ?>
87
+ require 'strelka'
88
+ require 'strelka/app'
89
+
90
+ module Strelka::App::DBLogger
91
+ extend Strelka::Plugin
92
+
93
+ run_before \
94
+ :auth,
95
+ :filters,
96
+ :negotiation,
97
+ :parameters,
98
+ :routing,
99
+ :sessions,
100
+ :templating
101
+
102
+ end
103
+ <?end example ?>
104
+
105
+ h3. Hooks
106
+
107
+ There are three primary extension points you can override in your
108
+ plugin. All hooks absolutely require you to @super@ at some point, so
109
+ the request/response chain passes through your plugin.
110
+
111
+ <dl>
112
+ <dt>fixup_request</dt>
113
+ <dd>
114
+ Make any changes to the @request@ that are necessary before handling it and
115
+ return it. This is an alternate extension-point for plugins that
116
+ wish to modify or replace the request before the request cycle is
117
+ started.
118
+ </dd>
119
+ <dt>handle_request</dt>
120
+ <dd>
121
+ Handle the request and return a @response@. This is the main extension-point
122
+ for the plugin system. Without being overridden or extended by plugins, this
123
+ method just returns the default Mongrel2 response.
124
+ </dd>
125
+ <dt>fixup_response</dt>
126
+ <dd>
127
+ Make any changes to the @response@ that are necessary before handing it to
128
+ Mongrel and return it. This is an alternate extension-point for plugins that
129
+ wish to modify or replace the response after the whole request cycle is
130
+ completed.
131
+ </dd>
132
+ </dl>
133
+
134
+ For our logging purposes, we want to hook the @fixup_response@ method.
135
+ We won't be altering the response itself, but just reading attributes
136
+ from it and squirreling them away. (Most notably, the @response@ has
137
+ access to the @request@ object, and visa versa.) You can find more detail
138
+ for these hooks in the API documentation for <?api Strelka::App ?>.
139
+
140
+ Here's the complete plugin.
141
+
142
+ <?example { lang: Ruby, caption: "A basic DBLogger plugin" } ?>
143
+ require 'strelka'
144
+ require 'strelka/app'
145
+ require 'sequel'
146
+
147
+ module Strelka::App::DBLogger
148
+ extend Strelka::Plugin
149
+
150
+ run_before \
151
+ :auth,
152
+ :filters,
153
+ :negotiation,
154
+ :parameters,
155
+ :routing,
156
+ :sessions,
157
+ :templating
158
+
159
+ def initialize( * )
160
+ super
161
+
162
+ @db = Sequel.sqlite( '////tmp/strelka_access.db' )
163
+ @db.create_table( :log ) do
164
+ timestamptz :date, :null => false
165
+ varchar :agent, :size => 255
166
+ varchar :remote_ip, :null => false
167
+ smallint :status
168
+ varchar :method, :size => 8, :null => false
169
+ varchar :path, :size => 255
170
+ varchar :query, :size => 255
171
+ varchar :referer, :size => 255
172
+ end unless @db.table_exists?( :log )
173
+ end
174
+
175
+ attr_reader :db
176
+
177
+ def fixup_response( response )
178
+ request = response.request
179
+
180
+ self.log.debug self.db[ :log ].insert(
181
+ :date => Time.now.to_s,
182
+ :agent => request.headers.user_agent,
183
+ :remote_ip => request.remote_ip.to_s,
184
+ :status => response.status,
185
+ :method => request.verb.to_s,
186
+ :path => request.uri.path,
187
+ :query => request.uri.query,
188
+ :referer => request.headers.referer
189
+ )
190
+
191
+ super
192
+ end
193
+ end
194
+ <?end example ?>
195
+
196
+ Handler startup creates the database and the logging schema, and
197
+ every request performs an @insert@ with the data we're after. There's
198
+ plenty of room for improvement here (configurable db location, prepared
199
+ statements), but hopefully that gives you a first-round idea of how easy
200
+ it is to add pluggable functionality to Strelka.
201
+
data/README.rdoc CHANGED
@@ -8,16 +8,18 @@ docs :: http://deveiate.org/code/strelka
8
8
 
9
9
  == Description
10
10
 
11
- Strelka is a framework for creating and deploying Mongrel2 web applications
12
- in Ruby, and for managing a Mongrel2 cluster.
11
+ Strelka is a framework for creating and deploying
12
+ "Mongrel2":http://mongrel2.org/ web applications in Ruby.
13
13
 
14
- It's named after the Russian dog who was one of the first space travelers
15
- to orbit the Earth and return alive.
14
+ It's named after a lesser known "Russian
15
+ cosmonaut":http://en.wikipedia.org/wiki/Strelka_(dog)#Belka_and_Strelka who was
16
+ one of the first canine space travelers to orbit the Earth and return alive.
17
+ Her name means "little arrow".
16
18
 
17
19
 
18
20
  == Prerequisites
19
21
 
20
- * Mongrel2[http://mongrel2.org/]
22
+ * Mongrel2[http://mongrel2.org/] 1.8.0 or better
21
23
  * Ruby 1.9.3 or better
22
24
 
23
25
 
@@ -26,95 +28,123 @@ to orbit the Earth and return alive.
26
28
  $ gem install strelka
27
29
 
28
30
 
29
- == Usage
31
+ == Getting Started
30
32
 
31
- Strelka is an application framework built on top of the Ruby-Mongrel2
32
- connector. It also includes a command-line tool for discovering Strelka
33
- application gems that are installed, setting up an application's
34
- runtime directory, and starting a Strelka application.
33
+ We're going to assume you've already built and installed the Mongrel2 daemon.
34
+ If not, please refer to the {Mongrel2
35
+ documentation}[http://mongrel2.org/wiki/quick_start.html] and get that ready.
35
36
 
37
+ Mongrel2 loads its configuration from a SQLite database. You can create the
38
+ this database in any fashion you like, but the Mongrel2 ruby module includes a
39
+ command-line tool called <tt>m2sh.rb</tt> that'll let you quickstart a server
40
+ if you just want to experiment. If you've already installed the *strelka* gem,
41
+ then it will already have been installed as a dependency.
36
42
 
37
- === The Application Framework
43
+ To bootstrap a basic server, configure it, and run it:
38
44
 
39
- The application framework is primarily geared towards developing web (HTTP)
40
- applications at the moment, but the intention is to make Strelka useful for
41
- developing applications that use the other protocols supported by Mongrel2
42
- at some point as well.
45
+ $ mkdir strelka-tryout
46
+ $ cd !$
47
+ $ m2sh.rb quickstart
43
48
 
44
- The framework is centered around the Strelka::App class, which is what you'll
45
- subclass when creating your own applications. It's pretty minimal by itself;
46
- Strelka applications are composed out of plugins that mix in the specific
47
- framework parts you specify, so you get exactly what you need and nothing
48
- more.
49
+ This will generate a Ruby DSL config, then invoke an editor on it.
49
50
 
50
- The plugins system itself is contained in the Strelka::Plugins mixin,
51
- which is included in Strelka::App already. This adds the +plugins+
52
- declarative, which you use from your app to load the plugins you want to use.
51
+ Make sure the config has a line like:
53
52
 
54
- A very basic application might look like this:
53
+ route '/hello', handler( 'tcp://127.0.0.1:9999', 'helloworld' )
54
+
55
+ in the 'host' section; that's the part of the Mongrel2 server we'll be talking
56
+ to.
57
+
58
+ The quickstart will generate a SQLite configuration database for use with
59
+ Mongrel2 in your current working directory, with the default required directory
60
+ structure. Mongrel2 will listen on port 8113 (unless you changed it), and send
61
+ all requests starting at the URI <tt>/hello</tt> to a handler called
62
+ <tt>helloworld</tt>.
63
+
64
+ If you stop the server (Ctrl-C will do so), you can restart it like so:
65
+
66
+ $ m2sh.rb start
67
+
68
+ Now that the Mongrel2 daemon is up and running, we can move forward and create
69
+ our first application!
70
+
71
+
72
+
73
+ === A Minimal Application
74
+
75
+ Strelka applications are subclasses of the Strelka::App class. Strelka::App is
76
+ pretty minimal by itself; it inherits most of its behavior from the basic
77
+ Mongrel2::Handler[http://deveiate.org/code/mongrel2/Mongrel2/Handler.html]
78
+ class, only adding a few convenience methods for common HTTP tasks.
79
+
80
+ A minimal application would look something like:
55
81
 
56
82
  #!/usr/bin/env ruby
57
83
 
58
84
  require 'strelka'
59
85
 
60
- # The Strelka admin web console.
61
86
  class HelloWorldApp < Strelka::App
62
87
 
63
- # The route appid that will configure this app's
64
- # connection to Mongrel2 if no appid is given
65
- # to App.run
66
- ID = 'hello-world'
88
+ def handle_request( request )
89
+ response = request.response
90
+ response.content_type = 'text/plain'
91
+ response.puts( "Hello, World!" )
92
+ return response
93
+ end
67
94
 
68
- # Use Sinatra-like routing
69
- plugins :routing
95
+ end # class HelloWorldApp
70
96
 
71
- # Set responses to plaintext if they don't specify differently
72
- default_type 'text/plain'
97
+ # Run the app
98
+ HelloWorldApp.run if __FILE__ == $0
73
99
 
74
- # Handle all GET requests the same way
75
- get do |req|
76
- res = req.response
77
- res.status = HTTP::OK
78
- res << 'Hello, world!'
79
- return res
100
+ While functional, this application is pretty dumb, and making it do anything
101
+ more intelligent on your own would require a bunch of additional code and
102
+ accompanying tests. Fortunately, Strelka already has done the heavy lifting.
103
+ It knows how to read the Mongrel2 configuration and hook your app up with the
104
+ right sockets to talk to the Mongrel2 front end (providing you follow one of
105
+ several simple conventions), provides hooks into the lifecycle of an HTTP
106
+ request, and includes a plugin system that uses these hooks to handle common
107
+ application tasks. This allows you to mix in the specific framework parts you
108
+ need, so you get exactly what you want and nothing more.
109
+
110
+
111
+ === Talking to Mongrel2
112
+
113
+ Mongrel2 associates handlers with itself via an identifier, which is described
114
+ in the Mongrel2 manual as a UUID, but can actually be any string consisting of
115
+ dashes and alphanumeric characters. Strelka reads the Mongrel2 config database,
116
+ and can automatically configure its apps to talk to the right socket with the
117
+ right <tt>send_ident</tt> if it can find them. It gives you a couple of
118
+ different ways of doing this. It will default to a string derived from the name
119
+ of the class, or you can set it yourself by declaring an <tt>ID</tt> constant
120
+ in your application class. If you need more control, you can also override the
121
+ <tt>::run</tt> class method and <tt>super</tt> with the right <tt>appid</tt>:
122
+
123
+ class HelloWorldApp
124
+ # Run as a tester if not running in the production environment
125
+ def self::run
126
+ appid = if Socket.gethostname.include?( 'test' )
127
+ 'helloworld-test'
128
+ else
129
+ 'helloworld'
130
+ end
131
+
132
+ super( appid )
80
133
  end
134
+ end
81
135
 
82
- end # class HelloWorldApp
136
+ Because our <tt>config.sqlite</tt> configuration directs requests to <tt>/</tt>
137
+ to be sent to the <tt>helloworldapp</tt> handler, Strelka will automatically
138
+ find and pair this route to Mongrel2 when run.
83
139
 
140
+ Run this handler, then point a browser to <tt>http://localhost:8080/</tt>. If
141
+ you see the text "Hello, World!", congrats! We'll build off of this in the
142
+ next section, the {Strelka Tutorial}[rdoc-ref:Tutorial.rdoc].
84
143
 
85
- # Run the app
86
- HelloWorldApp.run if __FILE__ == $0
87
144
 
88
- This app uses the 'routing' plugin, which adds Sinatra-like hooks for matching
89
- callbacks to requests. The example app above responds only to 'GET' requests,
90
- and ignores the path of the request altogether.
91
-
92
- Strelka comes with a few default plugins, but you can define your own fairly
93
- easily.
94
-
95
-
96
- === Default Plugins
97
-
98
- [auth[rdoc-ref:Strelka::App::Auth]]
99
- Pluggable authentication and authorization for Strelka applications.
100
- [errors[rdoc-ref:Strelka::App::Errors]]
101
- Custom error-handling.
102
- [filters[rdoc-ref:Strelka::App::Filters]]
103
- Request/response filters, for doing things like compression, content-type
104
- negotiation, or other things that somehow modify every request or response.
105
- [negotiation[rdoc-ref:Strelka::App::Negotiation]]
106
- HTTP Content negotiation for Strelka applications.
107
- [parameters[rdoc-ref:Strelka::App::Parameters]]
108
- Query and URI path-parameter validation and untainting.
109
- [restresources[rdoc-ref:Strelka::App::RestResources]]
110
- Automatically set up RESTful service resources for Sequel::Model-derived
111
- classes.
112
- [routing[rdoc-ref:Strelka::App::Routing]]
113
- Sinatra-ish request routing.
114
- [sessions[rdoc-ref:Strelka::App::Sessions]]
115
- Sessions for Strelka apps.
116
- [templating[rdoc-ref:Strelka::App::Templating]]
117
- Templating via the Inversion template engine.
145
+ == Further Reading
146
+
147
+ You'll likely want to start with {the Tutorial}[rdoc-ref:Tutorial.rdoc].
118
148
 
119
149
 
120
150
  == Roadmap
@@ -141,8 +171,12 @@ migrations, etc.
141
171
 
142
172
  === New Application Styles
143
173
 
144
- Create some new handler classes for different application styles, similar to those
145
- in the Tir[http://tir.mongrel2.org/] framework.
174
+ Create some new handler classes for different application styles, similar to
175
+ those in the Tir[http://tir.mongrel2.org/] framework.
176
+
177
+ === Chunked Encoding
178
+
179
+ Support for sending partial responses via the Chunked encoding.
146
180
 
147
181
 
148
182
  == Contributing