restrack 1.7.0 → 1.8.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -1,7 +1,7 @@
1
1
  # RESTRack
2
2
  - serving JSON and XML with REST and pleasure.
3
3
 
4
- ## Description:
4
+ ## Description
5
5
  RESTRack is a [Rack](http://rack.rubyforge.org/)-based [MVC](http://en.wikipedia.org/wiki/Model%E2%80%93View%E2%80%93Controller)
6
6
  framework that makes it extremely easy to develop [REST](http://en.wikipedia.org/wiki/Representational_State_Transfer)ful
7
7
  data services. It is inspired by [Rails](http://rubyonrails.org), and follows a few of its conventions. But it has no routes
@@ -17,12 +17,8 @@ view directory grouped by controller name subdirectories \(`view/<controller>/<a
17
17
  requests will then render the view template with the builder gem, rather than generating XML with XmlSimple.
18
18
 
19
19
 
20
- ## Installation:
21
- ### Using [RubyGems](http://rubygems.org):
22
- <sudo> gem install restrack
23
-
24
-
25
- ## Why RESTRack when there is Rails?
20
+ ## Rationale
21
+ ### Why RESTRack when there is Rails?
26
22
  [Rails](http://rubyonrails.org/) is a powerful tool for full web applications. RESTRack is targeted at making
27
23
  development of lightweight data services as easy as possible, while still giving you a performant and extensible
28
24
  framework. The primary goal of of the development of RESTRack was to add as little as possible to the framework to give
@@ -32,10 +28,15 @@ Rails 3 instantiates approximately 80K more objects than RESTRack to do a hello
32
28
  the default setup. Trimming Rails down by eliminating ActiveRecord, ActionMailer, and ActiveResource, it still
33
29
  instantiates over 47K more objects than RESTRack.
34
30
 
35
- ## OK, so why RESTRack when there is Sinatra?
31
+ ### OK, so why RESTRack when there is Sinatra?
36
32
  RESTRack provides a full, albeit small, framework for developing RESTful MVC applications.
37
33
 
38
34
 
35
+ ## Installation
36
+ ### Using [RubyGems](http://rubygems.org):
37
+ <sudo> gem install restrack
38
+
39
+
39
40
  ## CLI Usage:
40
41
  ### Generate a new service \(FooBar::WebService\)
41
42
  - restrack generate service foo\_bar
data/README.markdown.html CHANGED
@@ -1,10 +1,19 @@
1
- <h1>RESTRack</h1>
1
+
2
+ <!doctype html>
3
+ <html lang="fr">
4
+ <head>
5
+ <meta charset="utf-8">
6
+ <title>RESTRack</title>
7
+ <link rel="stylesheet" href="http://covertprestige.info/public/css/all.css" />
8
+ </head>
9
+ <body>
10
+ <h1>RESTRack</h1>
2
11
 
3
12
  <ul>
4
13
  <li>serving JSON and XML with REST and pleasure.</li>
5
14
  </ul>
6
15
 
7
- <h2>Description:</h2>
16
+ <h2>Description</h2>
8
17
 
9
18
  <p>RESTRack is a <a href="http://rack.rubyforge.org/">Rack</a>-based <a href="http://en.wikipedia.org/wiki/Model%E2%80%93View%E2%80%93Controller">MVC</a>
10
19
  framework that makes it extremely easy to develop <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">REST</a>ful
@@ -20,14 +29,9 @@ file, routing relationships are done through supplying custom code blocks to cla
20
29
  view directory grouped by controller name subdirectories (<code>view/&lt;controller&gt;/&lt;action&gt;.xml.builder</code>). XML format
21
30
  requests will then render the view template with the builder gem, rather than generating XML with XmlSimple.</p>
22
31
 
23
- <h2>Installation:</h2>
32
+ <h2>Rationale</h2>
24
33
 
25
- <h3>Using <a href="http://rubygems.org">RubyGems</a>:</h3>
26
-
27
- <pre><code>&lt;sudo&gt; gem install restrack
28
- </code></pre>
29
-
30
- <h2>Why RESTRack when there is Rails?</h2>
34
+ <h3>Why RESTRack when there is Rails?</h3>
31
35
 
32
36
  <p><a href="http://rubyonrails.org/">Rails</a> is a powerful tool for full web applications. RESTRack is targeted at making
33
37
  development of lightweight data services as easy as possible, while still giving you a performant and extensible
@@ -38,10 +42,17 @@ the web developer a good application space for developing JSON and XML services.
38
42
  the default setup. Trimming Rails down by eliminating ActiveRecord, ActionMailer, and ActiveResource, it still
39
43
  instantiates over 47K more objects than RESTRack.</p>
40
44
 
41
- <h2>OK, so why RESTRack when there is Sinatra?</h2>
45
+ <h3>OK, so why RESTRack when there is Sinatra?</h3>
42
46
 
43
47
  <p>RESTRack provides a full, albeit small, framework for developing RESTful MVC applications.</p>
44
48
 
49
+ <h2>Installation</h2>
50
+
51
+ <h3>Using <a href="http://rubygems.org">RubyGems</a>:</h3>
52
+
53
+ <pre><code>&lt;sudo&gt; gem install restrack
54
+ </code></pre>
55
+
45
56
  <h2>CLI Usage:</h2>
46
57
 
47
58
  <h3>Generate a new service (FooBar::WebService)</h3>
@@ -345,3 +356,7 @@ Software.</p>
345
356
  WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
346
357
  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
347
358
  OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</p>
359
+
360
+ </body>
361
+ </html>
362
+
data/Rakefile CHANGED
@@ -38,8 +38,12 @@ Rake::TestTask.new('test4') { |t|
38
38
  t.pattern = 'test/sample_app_4/**/test_*.rb'
39
39
  }
40
40
 
41
-
42
41
  desc 'Run sample_app_5 tests.'
43
42
  Rake::TestTask.new('test5') { |t|
44
43
  t.pattern = 'test/sample_app_5/**/test_*.rb'
45
44
  }
45
+
46
+ desc 'Run async app 1 tests.'
47
+ Rake::TestTask.new('asynctest1') { |t|
48
+ t.pattern = 'test/sample_app_async_1/**/test_*.rb'
49
+ }
data/bin/restrack CHANGED
@@ -12,7 +12,10 @@ when :generate, :gen, :g
12
12
  case noun.to_sym
13
13
  when :service, :serv, :s
14
14
  puts "Generating new RESTRack service #{name}..."
15
- RESTRack::Generator.generate_service( name )
15
+ RESTRack::Generator.generate_synchronous_service( name )
16
+ when :asynchronous_service, :asynch_service, :async_serv, :async, :as
17
+ puts "Generating new RESTRack service #{name}..."
18
+ RESTRack::Generator.generate_asynchronous_service( name )
16
19
  when :controller, :cont, :c
17
20
  predicate = ARGV[3] ? ARGV[3].to_sym : nil
18
21
  case predicate
@@ -30,6 +33,6 @@ when :server, :s
30
33
  options = { :Port => noun || 9292, :config => 'config.ru' }
31
34
  options.merge({ :environment => ARGV[2] }) unless ARGV[2].nil?
32
35
  Rack::Server.start( options )
33
- end
34
-
35
- # TODO: Print current version of RESTrack via command-line call
36
+ when :version, :v
37
+ puts "Currently using RESTRack version " + RESTRack::VERSION.to_s + "."
38
+ end
data/lib/restrack.rb CHANGED
@@ -22,8 +22,3 @@ end
22
22
 
23
23
  include HTTPStatus
24
24
  include ActiveSupport::Inflector
25
-
26
- # TODO: configurable list of params to strip before logging
27
- # TODO: update README
28
- # TODO: markdown to html generator
29
- # TODO: async plugin
@@ -0,0 +1,30 @@
1
+ require 'eventmachine'
2
+
3
+ module RESTRack
4
+ class AsyncWebService
5
+ AsyncResponse = [-1, {}, []].freeze
6
+
7
+ # Establish the namespace pointer.
8
+ def initialize
9
+ RESTRack::CONFIG[:SERVICE_NAME] = self.class.to_s.split('::')[0].to_sym
10
+ @request_hook = RESTRack::Hooks.new if RESTRack.const_defined?(:Hooks)
11
+ end
12
+
13
+ # Handle requests in the Rack way.
14
+ def call( env )
15
+ EventMachine::defer do
16
+ resource_request = RESTRack::ResourceRequest.new( :request => Rack::Request.new(env) )
17
+ unless @request_hook.nil? or (RESTRack::CONFIG.has_key?(:PRE_PROCESSOR_DISABLED) and RESTRack::CONFIG[:PRE_PROCESSOR_DISABLED])
18
+ @request_hook.pre_processor(resource_request)
19
+ end
20
+ response = RESTRack::Response.new(resource_request)
21
+ unless @request_hook.nil? or (RESTRack::CONFIG.has_key?(:POST_PROCESSOR_DISABLED) and RESTRack::CONFIG[:POST_PROCESSOR_DISABLED])
22
+ @request_hook.post_processor(response)
23
+ end
24
+ env['async.callback'].call response.output
25
+ end
26
+ AsyncResponse
27
+ end # method call
28
+
29
+ end # class WebService
30
+ end # module RESTRack
@@ -12,7 +12,8 @@ module RESTRack
12
12
  :constants => 'constants.yaml.erb',
13
13
  :controller => 'controller.rb.erb',
14
14
  :descendant_controller => 'descendant_controller.rb.erb',
15
- :hooks => 'hooks.rb.erb'
15
+ :hooks => 'hooks.rb.erb',
16
+ :gemfile => 'Gemfile.erb'
16
17
  }
17
18
 
18
19
  class << self
@@ -36,7 +37,9 @@ module RESTRack
36
37
  FileUtils.makedirs("#{base_dir}/views/#{name}")
37
38
  end
38
39
 
39
- # Generate a new RESTRack service
40
+ # The guts for generating a new RESTRack service. The loader.rb template
41
+ # will create a RESTRack::WebService or RESTRack::AsyncWebService based on
42
+ # the value of @async.
40
43
  def generate_service(name)
41
44
  FileUtils.makedirs("#{name}/config")
42
45
  FileUtils.makedirs("#{name}/controllers")
@@ -59,6 +62,25 @@ module RESTRack
59
62
  template = get_template_for( :hooks )
60
63
  resultant_string = template.result( get_binding_for_service( name ) )
61
64
  File.open("#{name}/hooks.rb", 'w') {|f| f.puts resultant_string }
65
+
66
+ # Added following lines to generate 'Gemfile' automatically.
67
+ template = get_template_for( :gemfile )
68
+ resultant_string = template.result( get_binding_for_service( name ) )
69
+ File.open("#{name}/Gemfile", 'w') {|f| f.puts resultant_string }
70
+ end
71
+ # Generate a new RESTRack service. This does not use EventMachine and can
72
+ # be used with any Rack supported web server.
73
+ def generate_synchronous_service(name)
74
+ @async = false
75
+ generate_service(name)
76
+ @async = nil
77
+ end
78
+ # Generate a new RESTRack service that uses EventMachine. This can only be
79
+ # used with web servers that use or support EventMachine (Thin, Rainbows).
80
+ def generate_asynchronous_service(name)
81
+ @async = true
82
+ generate_service(name)
83
+ @async = nil
62
84
  end
63
85
 
64
86
  private
@@ -0,0 +1,4 @@
1
+ source :rubygems
2
+
3
+ gem "restrack","~><%= RESTRack::VERSION.to_s %>"
4
+ <%= @async ? 'gem "eventmachine"' : '' %>
@@ -22,3 +22,34 @@
22
22
  :ROOT_RESOURCE_ACCEPT: []
23
23
  # These are the resources which cannot be accessed from the root of your web service. Use either this or ROOT_RESOURCE_ACCEPT as a blacklist or whitelist to establish routing (relationships defined in resource controllers define further routing).
24
24
  :ROOT_RESOURCE_DENY: []
25
+
26
+ # A list of input parameters which should not be output to logs:
27
+ #:PARAMS_NOT_LOGGABLE: [:password]
28
+
29
+ # :TRANSCODE: and :FORCE_ENCODING: are optional config settings
30
+ # String#encode will be called when this value is set
31
+ #:TRANSCODE: ISO-8859-1 #or UTF-8 etc
32
+ # String#force_encoding will be called when this value is set
33
+ #:FORCE_ENCODING: ISO-8859-1
34
+
35
+ # :CORS: is an optional config setting
36
+ # CORS Header configuration
37
+ # Supported:
38
+ # - Access-Control-Allow-Origin: http://localhost
39
+ # - Access-Control-Allow-Methods: POST, GET
40
+ # List of all:
41
+ # - Access-Control-Allow-Origin: <origin> | *
42
+ # e.g. Access-Control-Allow-Origin: http://mozilla.com
43
+ # - Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header
44
+ # - Access-Control-Max-Age: <delta-seconds>
45
+ # - Access-Control-Allow-Credentials: true | false
46
+ # - Access-Control-Allow-Methods: <method>[, <method>]*
47
+ # e.g. Access-Control-Allow-Methods: POST, GET
48
+ # - Access-Control-Allow-Headers: <field-name>[, <field-name>]*
49
+ #:CORS:
50
+ # Access-Control-Allow-Origin: http://restrack.me
51
+ # Access-Control-Allow-Methods: POST, GET
52
+
53
+ # :PRE_PROCESSOR_DISABLED: and :POST_PROCESSOR_DISABLED: are optional config settings and are false by default
54
+ #:PRE_PROCESSOR_DISABLED: true
55
+ #:POST_PROCESSOR_DISABLED: true
@@ -1,7 +1,7 @@
1
1
  require 'restrack'
2
2
 
3
3
  module <%= @service_name.camelize %>; end
4
- class <%= @service_name.camelize %>::WebService < RESTRack::WebService; end
4
+ class <%= @service_name.camelize %>::WebService < RESTRack::<%= @async ? 'Async' : '' %>WebService; end
5
5
 
6
6
  RESTRack::CONFIG = RESTRack::load_config(File.join(File.dirname(__FILE__), 'config/constants.yaml'))
7
7
  RESTRack::CONFIG[:ROOT] = File.dirname(__FILE__)
@@ -15,9 +15,6 @@ module RESTRack
15
15
  @request.env.select {|k,v| k.start_with? 'HTTP_'}.each do |k,v|
16
16
  @headers[k.sub(/^HTTP_/, '')] = v
17
17
  end
18
- end
19
-
20
- def prepare
21
18
  # MIME type should be determined before raising any exceptions for proper error reporting
22
19
  # Set up the initial routing.
23
20
  @url_chain = @request.path_info.split('/')
@@ -32,16 +29,17 @@ module RESTRack
32
29
  end
33
30
  # Determine MIME type from extension
34
31
  @mime_type = get_mime_type_from( extension )
32
+ end
33
+
34
+ def prepare
35
35
  # Now safe to raise exceptions
36
36
  raise HTTP400BadRequest, "Request path of #{@request.path_info} is invalid" if @request.path_info.include?('//')
37
-
38
37
  # For CORS support
39
38
  if RESTRack::CONFIG[:CORS]
40
39
  raise HTTP403Forbidden if @headers['Origin'].nil?
41
40
  raise HTTP403Forbidden unless RESTRack::CONFIG[:CORS]['Access-Control-Allow-Origin'] == '*' or RESTRack::CONFIG[:CORS]['Access-Control-Allow-Origin'].include?(@headers['Origin'])
42
41
  raise HTTP403Forbidden unless @request.env['REQUEST_METHOD'] == 'OPTIONS' or RESTRack::CONFIG[:CORS]['Access-Control-Allow-Methods'] == '*' or RESTRack::CONFIG[:CORS]['Access-Control-Allow-Methods'].include?(@request.env['REQUEST_METHOD'])
43
42
  end
44
-
45
43
  # Pull input data from POST body
46
44
  @post_params = parse_body( @request )
47
45
  @get_params = parse_query_string( @request )
@@ -53,7 +51,6 @@ module RESTRack
53
51
  end
54
52
  @params.symbolize!
55
53
  log_request_params(@params)
56
-
57
54
  # Pull first controller from URL
58
55
  @active_resource_name = @url_chain.shift
59
56
  unless @active_resource_name.nil? or RESTRack.controller_exists?(@active_resource_name)
@@ -69,7 +66,13 @@ module RESTRack
69
66
  end
70
67
 
71
68
  def log_request_params(params_hash)
72
- RESTRack.request_log.debug 'Combined Request Params: ' + params_hash.inspect
69
+ params_to_log = params_hash.clone
70
+ if RESTRack::CONFIG[:PARAMS_NOT_LOGGABLE]
71
+ params_to_log.each_key do |param|
72
+ params_to_log[param] = '*****' if RESTRack::CONFIG[:PARAMS_NOT_LOGGABLE].include?(param.to_s)
73
+ end
74
+ end
75
+ RESTRack.request_log.debug 'Combined Request Params: ' + params_to_log.inspect
73
76
  end
74
77
 
75
78
  # Call the next entity in the path stack.
@@ -1,3 +1,3 @@
1
1
  module RESTRack
2
- VERSION = "1.7.0"
2
+ VERSION = "1.8.1"
3
3
  end
@@ -27,6 +27,9 @@
27
27
  # The stack trace will not be added to 500 response body by default, set to true to enable.
28
28
  :SHOW_STACK: true
29
29
 
30
+ # A list of input parameters which should not be output to logs:
31
+ :PARAMS_NOT_LOGGABLE: [ password ]
32
+
30
33
  # :TRANSCODE: and :FORCE_ENCODING: are optional config settings
31
34
  # String#encode will be called when this value is set
32
35
  #:TRANSCODE: ISO-8859-1 #or UTF-8 etc
@@ -21,7 +21,7 @@ class SampleApp::TestControllerInputs < Test::Unit::TestCase
21
21
  test_val = { :test => '1', :hello => 'world', 'get?' => 'true' }.to_json
22
22
  assert_equal test_val, output[2][0]
23
23
  end
24
-
24
+
25
25
  def test_FUBAR_params
26
26
  env = Rack::MockRequest.env_for('/foo_bar/echo_get?test=1&hello=world', {
27
27
  :method => 'DELETE'
@@ -60,7 +60,7 @@ class SampleApp::TestControllerInputs < Test::Unit::TestCase
60
60
  end
61
61
  assert_equal test_val, output[2][0]
62
62
  end
63
-
63
+
64
64
  def test_post_xml
65
65
  test_val = XmlSimple.xml_out({ :echo => 'niner' }, 'AttrPrefix' => true, 'XmlDeclaration' => true, 'NoIndent' => true)
66
66
  env = Rack::MockRequest.env_for('/foo_bar/echo.xml', {
@@ -74,7 +74,7 @@ class SampleApp::TestControllerInputs < Test::Unit::TestCase
74
74
  end
75
75
  assert_equal test_val, output[2][0]
76
76
  end
77
-
77
+
78
78
  def test_post_text
79
79
  test_val = 'OPCODE=PEBKAC'
80
80
  env = Rack::MockRequest.env_for('/foo_bar/echo.txt', {
@@ -88,4 +88,18 @@ class SampleApp::TestControllerInputs < Test::Unit::TestCase
88
88
  end
89
89
  assert_equal test_val, output[2][0]
90
90
  end
91
+
92
+ def test_post_password_param_no_log
93
+ test_val = { :echo => 'niner', :password => 'my_password' }.to_json
94
+ env = Rack::MockRequest.env_for('/foo_bar/echo', {
95
+ :method => 'POST',
96
+ :input => test_val,
97
+ 'CONTENT_TYPE' => 'application/json'
98
+ })
99
+ output = ''
100
+ assert_nothing_raised do
101
+ output = @ws.call(env)
102
+ end
103
+ assert_equal test_val, output[2][0]
104
+ end
91
105
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: restrack
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.0
4
+ version: 1.8.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-03 00:00:00.000000000 Z
12
+ date: 2013-01-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rack
@@ -164,7 +164,9 @@ files:
164
164
  - Rakefile
165
165
  - bin/restrack
166
166
  - lib/restrack.rb
167
+ - lib/restrack/async_web_service.rb
167
168
  - lib/restrack/generator.rb
169
+ - lib/restrack/generator/Gemfile.erb
168
170
  - lib/restrack/generator/config.ru.erb
169
171
  - lib/restrack/generator/constants.yaml.erb
170
172
  - lib/restrack/generator/controller.rb.erb
@@ -255,7 +257,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
255
257
  version: '0'
256
258
  requirements: []
257
259
  rubyforge_project: restrack
258
- rubygems_version: 1.8.21
260
+ rubygems_version: 1.8.24
259
261
  signing_key:
260
262
  specification_version: 3
261
263
  summary: A lightweight MVC framework developed specifically for JSON (and XML) REST