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

Sign up to get free protection for your applications and to get access to all the features.
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