webmachine 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -29,12 +29,17 @@ application for it!
29
29
  require 'webmachine'
30
30
  # Require any of the files that contain your resources here
31
31
  require 'my_resource'
32
-
33
- # Point all URIs at the MyResource class
34
- Webmachine::Dispatcher.add_route(['*'], MyResource)
35
-
32
+
33
+ # Create an application which encompasses routes and configruation
34
+ MyApp = Webmachine::Application.new do |app|
35
+ app.routes do
36
+ # Point all URIs at the MyResource class
37
+ add ['*'], MyResource
38
+ end
39
+ end
40
+
36
41
  # Start the server, binds to port 8080 using WEBrick
37
- Webmachine.run
42
+ MyApp.run
38
43
  ```
39
44
 
40
45
  Your resource will look something like this:
@@ -68,29 +73,31 @@ end
68
73
  There are many other HTTP features exposed to your resource through
69
74
  {Webmachine::Resource::Callbacks}. Give them a try!
70
75
 
71
- ### Configurator
76
+ ### Application/Configurator
72
77
 
73
78
  There's a configurator that allows you to set the ip address and port
74
79
  bindings as well as a different webserver adapter. You can also add
75
- your routes in a block. Both of these call return the `Webmachine`
76
- module, so you could chain them if you like.
80
+ your routes in a block (as shown above). Both of these call return the
81
+ `Webmachine::Application` instance, so you could chain them if you
82
+ like. If you don't want to create your own separate application
83
+ object, `Webmachine.application` will return a global one.
77
84
 
78
85
  ```ruby
79
86
  require 'webmachine'
80
87
  require 'my_resource'
81
88
 
82
- Webmachine.routes do
89
+ Webmachine.application.routes do
83
90
  add ['*'], MyResource
84
91
  end
85
92
 
86
- Webmachine.configure do |config|
93
+ Webmachine.application.configure do |config|
87
94
  config.ip = '127.0.0.1'
88
95
  config.port = 3000
89
96
  config.adapter = :Mongrel
90
97
  end
91
98
 
92
99
  # Start the server.
93
- Webmachine.run
100
+ Webmachine.application.run
94
101
  ```
95
102
 
96
103
  ## Features
@@ -115,6 +122,46 @@ Webmachine.run
115
122
 
116
123
  ## Changelog
117
124
 
125
+ ### 0.4.1 February 8, 2012
126
+
127
+ 0.4.1 is a bugfix release that corrects a few minor issues. Added Sam
128
+ Goldman as a contributor. Thank you for your contributions!
129
+
130
+ * Updated README with `Webmachine::Application` examples.
131
+ * The CGI env vars `CONTENT_LENGTH` and `CONTENT_TYPE` are now being
132
+ correctly converted into their Webmachine equivalents.
133
+ * The request body given via the Rack and Mongrel adapters now
134
+ responds to `#to_s` and `#each` so it can be treated like a `String`
135
+ or `Enumerable` that yields chunks.
136
+
137
+ ### 0.4.0 February 5, 2012
138
+
139
+ 0.4.0 includes some important refactorings, isolating the idea of
140
+ global state into an Application object with its own Dispatcher and
141
+ configuration, and making Adapters into real classes with a consistent
142
+ interface. It also adds some query methods on the Request object for
143
+ the HTTP method and scheme and Route guards (matching predicates).
144
+ Added Michael Maltese, Emmanuel Gomez, and Bernerd Schaefer as
145
+ committers. Thank you for your contributions!
146
+
147
+ * Fixed `Request#query` to handle nil values for the URI query accessor.
148
+ * `Webmachine::Dispatcher` is a real class rather than a module with
149
+ state.
150
+ * `Webmachine::Application` is a class that includes its own
151
+ dispatcher and configuration. The default instance is accessible via
152
+ `Webmachine.application`.
153
+ * `Webmachine::Adapter` is now the superclass of all implemented
154
+ adapters so that they have a uniform interface.
155
+ * The Mongrel spec is skipped on JRuby since version 1.2 (pre-release)
156
+ doesn't work. Direct Mongrel support may be removed in a later
157
+ release.
158
+ * `Webmachine::Dispatcher::Route` now accepts guards, which may be
159
+ expressed as lambdas/procs or any object responding to `call`
160
+ preceding the `Resource` class in the route definition, or as a
161
+ trailing block. All guards will be passed the `Request` object when
162
+ matching the route and should return a truthy or falsey value
163
+ (without side-effects).
164
+
118
165
  ### 0.3.0 November 9, 2011
119
166
 
120
167
  0.3.0 introduces some new features, refactorings, and now has 100%
data/b/autospec ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'autospec' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rspec-core', 'autospec')
data/b/gpgen ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'gpgen' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('gem_plugin', 'gpgen')
data/b/guard ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'guard' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('guard', 'guard')
data/b/htmldiff ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'htmldiff' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('diff-lcs', 'htmldiff')
data/b/ldiff ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'ldiff' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('diff-lcs', 'ldiff')
data/b/mongrel_rails ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'mongrel_rails' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('mongrel', 'mongrel_rails')
data/b/rackup ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rackup' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rack', 'rackup')
data/b/rake ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rake' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rake', 'rake')
data/b/rake2thor ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rake2thor' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('thor', 'rake2thor')
data/b/redcarpet ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'redcarpet' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('redcarpet', 'redcarpet')
data/b/rspec ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rspec' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rspec-core', 'rspec')
data/b/thor ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'thor' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('thor', 'thor')
data/b/yard ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'yard' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('yard', 'yard')
data/b/yardoc ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'yardoc' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('yard', 'yardoc')
data/b/yri ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'yri' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('yard', 'yri')
@@ -31,7 +31,7 @@ module Webmachine
31
31
  class Handler < ::Mongrel::HttpHandler
32
32
  def initialize(dispatcher)
33
33
  @dispatcher = dispatcher
34
- super
34
+ super()
35
35
  end
36
36
 
37
37
  # Processes an individual request from Mongrel through Webmachine.
@@ -41,7 +41,7 @@ module Webmachine
41
41
  request = Webmachine::Request.new(wreq.params["REQUEST_METHOD"],
42
42
  URI.parse(wreq.params["REQUEST_URI"]),
43
43
  header,
44
- wreq.body || StringIO.new(''))
44
+ RequestBody.new(wreq))
45
45
 
46
46
  response = Webmachine::Response.new
47
47
  @dispatcher.dispatch(request, response)
@@ -81,6 +81,31 @@ module Webmachine
81
81
  end
82
82
  end # class Handler
83
83
 
84
+ # Wraps a Mongrel request body so that it can behave like a
85
+ # String.
86
+ # @api private
87
+ class RequestBody
88
+ # @return the request from Mongrel
89
+ attr_reader :request
90
+
91
+ # @param request the request from Mongrel
92
+ def initialize(request)
93
+ @request = request
94
+ end
95
+
96
+ # @return [String] the request body as a string
97
+ def to_s
98
+ request.body.rewind
99
+ request.body.read
100
+ end
101
+
102
+ # @yield [chunk]
103
+ # @yieldparam [String] chunk a chunk of the request body
104
+ def each(&block)
105
+ request.body.each(&block)
106
+ end
107
+ end # class RequestBody
108
+
84
109
  end # module Mongrel
85
110
  end # module Adapters
86
111
  end # module Webmachine
@@ -51,7 +51,7 @@ module Webmachine
51
51
  request = Webmachine::Request.new(rack_req.request_method,
52
52
  URI.parse(rack_req.url),
53
53
  headers,
54
- rack_req.body)
54
+ RequestBody.new(rack_req))
55
55
 
56
56
  response = Webmachine::Response.new
57
57
  @dispatcher.dispatch(request, response)
@@ -63,6 +63,42 @@ module Webmachine
63
63
 
64
64
  [response.code.to_i, response.headers, body || []]
65
65
  end
66
+
67
+ # Wraps the Rack input so it can be treated like a String or
68
+ # Enumerable.
69
+ # @api private
70
+ class RequestBody
71
+ # @param [Rack::Request] request the Rack request
72
+ def initialize(request)
73
+ @request = request
74
+ end
75
+
76
+ # Converts the body to a String so you can work with the entire
77
+ # thing.
78
+ # @return [String] the request body as a string
79
+ def to_s
80
+ if @value
81
+ @value.join
82
+ else
83
+ @request.body.rewind
84
+ @request.body.read
85
+ end
86
+ end
87
+
88
+ # Iterates over the body in chunks. If the body has previously
89
+ # been read, this method can be called again and get the same
90
+ # sequence of chunks.
91
+ # @yield [chunk]
92
+ # @yieldparam [String] chunk a chunk of the request body
93
+ def each
94
+ if @value
95
+ @value.each {|chunk| yield chunk }
96
+ else
97
+ @value = []
98
+ @request.body.each {|chunk| @value << chunk; yield chunk }
99
+ end
100
+ end
101
+ end # class RequestBody
66
102
  end # class Rack
67
103
 
68
104
  end # module Adapters