rackables 0.2.0 → 0.3.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d191aa7afff2efbffbd223c9dfb3f6af2478bb1c
4
+ data.tar.gz: 0f1a3b94ea1abe80b4c3f009e018b123b1a73dd9
5
+ SHA512:
6
+ metadata.gz: 31be665cf4d47cc8d2ae746f52314725cfc50c93562bb690fc1ea972c534135cf09d465c525abdab1f4c6e41451b5e72928dc1ebc21ad1301db6559cecb19548
7
+ data.tar.gz: 5f032269df7a43c136c6ebedde5ccf1b2c6310115133c17942631df1ae9bad68f93ecc61551221170a1e09f1d9c1680ca75a72f04cfa1c18a6e6bff04f217918
@@ -2,7 +2,8 @@ module Rackables
2
2
  autoload :Branch, 'rackables/branch'
3
3
  autoload :CacheControl, 'rackables/cache_control'
4
4
  autoload :DefaultCharset, 'rackables/default_charset'
5
- autoload :Get, 'rackables/get'
6
5
  autoload :HideExceptions, 'rackables/hide_exceptions'
6
+ autoload :ResponseHeaders, 'rackables/response_headers'
7
+ autoload :SimpleEndpoint, 'rackables/simple_endpoint'
7
8
  autoload :TrailingSlashRedirect, 'rackables/trailing_slash_redirect'
8
9
  end
@@ -25,6 +25,17 @@ module Rackables
25
25
  # end
26
26
  #
27
27
  # run MyEndpointApp
28
+ #
29
+ # If the app returned from the block responds with an X-Cascade: pass header,
30
+ # control will be passed back to the main rack pipeline.
31
+ #
32
+ # In this contrived example, MyEndpointApp will always be called:
33
+ #
34
+ # use Rackables::Branch do |env|
35
+ # Proc.new { [404, 'X-Cascade' => 'pass', []] }
36
+ # end
37
+ #
38
+ # run MyEndpointApp
28
39
  class Branch
29
40
  def initialize(app, &block)
30
41
  @app = app
@@ -32,8 +43,13 @@ module Rackables
32
43
  end
33
44
 
34
45
  def call(env)
35
- app = @block.call(env) || @app
36
- app.call(env)
46
+ if branch_app = @block.call(env)
47
+ response = branch_app.call(env)
48
+ cascade = response[1]['X-Cascade']
49
+ cascade == 'pass' ? @app.call(env) : response
50
+ else
51
+ @app.call(env)
52
+ end
37
53
  end
38
54
  end
39
55
  end
@@ -1,3 +1,5 @@
1
+ require 'rack/utils'
2
+
1
3
  module Rackables
2
4
  class CacheControl
3
5
  # Lets you set the Cache-Control response header from middleware. Does not overwrite
@@ -24,42 +26,39 @@ module Rackables
24
26
  end
25
27
 
26
28
  def call(env)
27
- response = @app.call(env)
28
- headers = response[1]
29
+ status, headers, body = @app.call(env)
30
+ headers = ::Rack::Utils::HeaderHash.new(headers)
29
31
  unless headers.has_key?('Cache-Control')
30
- value = @hash.empty? ? @directives : "#{@directives}, #{stringify_hash}"
31
- headers['Cache-Control'] = value
32
+ headers['Cache-Control'] = directives
32
33
  end
33
- response
34
+ [status, headers, body]
34
35
  end
35
-
36
+
36
37
  private
37
38
  def extract_hash!(array)
38
39
  array.last.kind_of?(Hash) ? array.pop : {}
39
40
  end
40
-
41
+
41
42
  def extract_non_callable_values_from_hash!
42
43
  @hash.reject! { |k,v| v == false }
43
44
  @hash.reject! { |k,v| @directives << k if v == true }
44
45
  @hash.reject! { |k,v| @directives << "#{k}=#{v.inspect}" if !v.respond_to?(:call) }
45
46
  end
46
-
47
+
47
48
  def stringify_hash_keys!
48
- @hash.each do |key, value|
49
- @hash[stringify_directive(key)] = @hash.delete(key)
50
- end
49
+ @hash = @hash.inject({}) {|memo, (k, v)| memo[stringify_directive(k)] = v; memo}
51
50
  end
52
-
51
+
53
52
  def stringify_directives!
54
53
  @directives = @directives.map {|d| stringify_directive(d)}.join(', ')
55
54
  end
56
-
57
- def stringify_hash
58
- @hash.inject([]) {|arr, (k, v)| arr << "#{k}=#{v.call.inspect}"}.join(', ')
59
- end
60
-
55
+
61
56
  def stringify_directive(directive)
62
57
  directive.to_s.tr('_','-')
63
58
  end
59
+
60
+ def directives
61
+ @hash.inject(@directives) {|str, (k, v)| "#{str}, #{k}=#{v.call.inspect}"}
62
+ end
64
63
  end
65
64
  end
@@ -1,10 +1,12 @@
1
+ require 'rack/utils'
2
+
1
3
  module Rackables
2
4
  # Adds the specified charset to the Content-Type header, if one isn't
3
5
  # already there.
4
6
  #
5
7
  # Ideal for use with Sinatra, which by default doesn't set charset
6
8
  class DefaultCharset
7
- HAS_CHARSET = /charset=/
9
+ HAS_CHARSET = /;\s*charset\s*=\s*/i
8
10
 
9
11
  def initialize(app, value = 'utf-8')
10
12
  @app = app
@@ -12,13 +14,13 @@ module Rackables
12
14
  end
13
15
 
14
16
  def call(env)
15
- response = @app.call(env)
16
- headers = response[1]
17
+ status, headers, body = @app.call(env)
18
+ headers = ::Rack::Utils::HeaderHash.new(headers)
17
19
  content_type = headers['Content-Type']
18
20
  if content_type && content_type !~ HAS_CHARSET
19
21
  headers['Content-Type'] = "#{content_type}; charset=#{@value}"
20
22
  end
21
- response
23
+ [status, headers, body]
22
24
  end
23
25
  end
24
26
  end
@@ -0,0 +1,25 @@
1
+ require 'rack/utils'
2
+
3
+ module Rackables
4
+ # Allows you to tap into the response headers. Yields a Rack::Utils::HeaderHash
5
+ # of current response headers to the block. Example:
6
+ #
7
+ # use Rackables::ResponseHeaders do |headers|
8
+ # headers['X-Foo'] = 'bar'
9
+ # headers.delete('X-Baz')
10
+ # end
11
+ #
12
+ class ResponseHeaders
13
+ def initialize(app, &block)
14
+ @app = app
15
+ @block = block
16
+ end
17
+
18
+ def call(env)
19
+ status, headers, body = @app.call(env)
20
+ headers = ::Rack::Utils::HeaderHash.new(headers)
21
+ @block.call(headers)
22
+ [status, headers, body]
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,78 @@
1
+ require 'rack'
2
+
3
+ module Rackables
4
+ # Simplest example:
5
+ #
6
+ # use Rackables::SimpleEndpoint, '/ping_monitor' do
7
+ # 'pong'
8
+ # end
9
+ #
10
+ # HTTP verb requirements can optionally be specified:
11
+ #
12
+ # use Rackables::SimpleEndpoint, '/ping_monitor' => :get do
13
+ # 'only GET requests will match'
14
+ # end
15
+ #
16
+ # use Rackables::SimpleEndpoint, '/ping_monitor' => [:get, :post] do
17
+ # 'only GET and POST requests will match'
18
+ # end
19
+ #
20
+ # Rack::Request Rack::Response objects are yielded to block:
21
+ #
22
+ # use Rackables::SimpleEndpoint, '/json' do |request, response|
23
+ # response['Content-Type'] = 'application/json'
24
+ # %({"foo": "#{request[:foo]}"})
25
+ # end
26
+ #
27
+ # Example with regular expression -- match data object is yielded as third argument to block
28
+ #
29
+ # use Rackables::SimpleEndpoint, %r{^/(john|paul|george|ringo)} do |request, response, match|
30
+ # "Hello, #{match[1]}"
31
+ # end
32
+ #
33
+ # A :pass symbol returned from block will not return a response; control will continue down the
34
+ # Rack stack:
35
+ #
36
+ # use Rackables::SimpleEndpoint, '/api_key' do |request, response|
37
+ # request.env['myapp.user'].authorized? ? '12345' : :pass
38
+ # end
39
+ #
40
+ # # Unauthorized access to /api_key will receive a 404
41
+ # run NotFoundApp
42
+ class SimpleEndpoint
43
+ def initialize(app, arg, &block)
44
+ @app = app
45
+ @path = extract_path(arg)
46
+ @verbs = extract_verbs(arg)
47
+ @block = block
48
+ end
49
+
50
+ def call(env)
51
+ match = match_path(env['PATH_INFO'])
52
+ if match && valid_method?(env['REQUEST_METHOD'])
53
+ request, response = ::Rack::Request.new(env), ::Rack::Response.new
54
+ response.body = @block.call(request, response, (match unless match == true))
55
+ response.body == :pass ? @app.call(env) : response.finish
56
+ else
57
+ @app.call(env)
58
+ end
59
+ end
60
+
61
+ private
62
+ def extract_path(arg)
63
+ arg.is_a?(Hash) ? arg.keys.first : arg
64
+ end
65
+
66
+ def extract_verbs(arg)
67
+ arg.is_a?(Hash) ? [arg.values.first].flatten.map {|verb| verb.to_s.upcase} : []
68
+ end
69
+
70
+ def match_path(path)
71
+ @path.is_a?(Regexp) ? @path.match(path.to_s) : @path == path.to_s
72
+ end
73
+
74
+ def valid_method?(method)
75
+ @verbs.empty? || @verbs.include?(method)
76
+ end
77
+ end
78
+ end
@@ -1,3 +1,5 @@
1
+ require 'rack'
2
+
1
3
  module Rackables
2
4
  # Request paths with a trailing slash are 301 redirected to the version without, e.g.:
3
5
  #
@@ -10,10 +12,10 @@ module Rackables
10
12
  end
11
13
 
12
14
  def call(env)
13
- if env['PATH_INFO'] =~ HAS_TRAILING_SLASH
14
- location = "#{env['rack.url_scheme']}://#{env['HTTP_HOST']}/#{$1}"
15
- location = "#{location}?#{env['QUERY_STRING']}" if env['QUERY_STRING'].to_s =~ /\S/
16
- [301, {"Location" => location}, []]
15
+ req = Rack::Request.new(env)
16
+ if req.path_info =~ HAS_TRAILING_SLASH
17
+ req.path_info = "/#{$1}"
18
+ [301, {"Location" => req.url}, []]
17
19
  else
18
20
  @app.call(env)
19
21
  end
metadata CHANGED
@@ -1,77 +1,80 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: rackables
3
- version: !ruby/object:Gem::Version
4
- version: 0.2.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
5
  platform: ruby
6
- authors:
6
+ authors:
7
7
  - Geoff Buesing
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
-
12
- date: 2010-01-15 00:00:00 -06:00
13
- default_executable:
14
- dependencies: []
15
-
16
- description: "Bundles Rack middleware: CacheControl, DefaultCharset, PublicExceptionPage, TrailingSlashRedirect"
11
+ date: 2013-06-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rack
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rack-test
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description:
17
42
  email: gbuesing@gmail.com
18
43
  executables: []
19
-
20
44
  extensions: []
21
-
22
- extra_rdoc_files:
23
- - README.rdoc
24
- files:
25
- - README.rdoc
26
- - Rakefile
27
- - VERSION
45
+ extra_rdoc_files: []
46
+ files:
28
47
  - lib/rackables.rb
29
48
  - lib/rackables/branch.rb
30
49
  - lib/rackables/cache_control.rb
31
50
  - lib/rackables/default_charset.rb
32
- - lib/rackables/get.rb
33
51
  - lib/rackables/hide_exceptions.rb
34
- - lib/rackables/more/env_inquirer.rb
52
+ - lib/rackables/response_headers.rb
53
+ - lib/rackables/simple_endpoint.rb
35
54
  - lib/rackables/trailing_slash_redirect.rb
36
- - test/fixtures/custom_500.html
37
- - test/test_branch.rb
38
- - test/test_cache_control.rb
39
- - test/test_default_charset.rb
40
- - test/test_get.rb
41
- - test/test_hide_exceptions.rb
42
- - test/test_trailing_slash_redirect.rb
43
- has_rdoc: true
44
- homepage: http://github.com/gbuesing/rackables
45
- licenses: []
46
-
55
+ - lib/rackables/more/env_inquirer.rb
56
+ homepage: https://github.com/gbuesing/rackables
57
+ licenses:
58
+ - MIT
59
+ metadata: {}
47
60
  post_install_message:
48
- rdoc_options:
49
- - --charset=UTF-8
50
- require_paths:
61
+ rdoc_options: []
62
+ require_paths:
51
63
  - lib
52
- required_ruby_version: !ruby/object:Gem::Requirement
53
- requirements:
54
- - - ">="
55
- - !ruby/object:Gem::Version
56
- version: "0"
57
- version:
58
- required_rubygems_version: !ruby/object:Gem::Requirement
59
- requirements:
60
- - - ">="
61
- - !ruby/object:Gem::Version
62
- version: "0"
63
- version:
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - '>='
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
64
74
  requirements: []
65
-
66
75
  rubyforge_project:
67
- rubygems_version: 1.3.5
76
+ rubygems_version: 2.0.0
68
77
  signing_key:
69
- specification_version: 3
70
- summary: Bundle of useful Rack middleware
71
- test_files:
72
- - test/test_branch.rb
73
- - test/test_cache_control.rb
74
- - test/test_default_charset.rb
75
- - test/test_get.rb
76
- - test/test_hide_exceptions.rb
77
- - test/test_trailing_slash_redirect.rb
78
+ specification_version: 4
79
+ summary: A collection of useful Rack middleware
80
+ test_files: []
@@ -1,50 +0,0 @@
1
- = Rackables
2
-
3
- == Middleware
4
-
5
- Rackables bundles the following Rack middlewares:
6
-
7
- * Rackables::Branch - Conditionally re-routes the Rack stack at runtime to an alternate endpoint
8
- * Rackables::CacheControl - Sets response Cache-Control header
9
- * Rackables::DefaultCharset - Sets charset directive in Content-Type header
10
- * Rackables::Get - Allows creation of simple endpoints and path routing with a syntax similar to Sinatra's get method
11
- * Rackables::HideExceptions - Rescues exceptions with a static exception page
12
- * Rackables::TrailingSlashRedirect - 301 Redirects requests paths with a trailing slash
13
-
14
- == More
15
-
16
- Rackables also bundles a Rack environment inquirer similar to Rails.env:
17
-
18
- Rack.env # => "development"
19
- Rack.env.development? # => true
20
-
21
- == Use
22
-
23
- Requiring 'rackables' will add autoloads for all Rackables middlewares. To use the Rack.env inquirer,
24
- you must explicitly require "rackables/more/env_inquirer".
25
-
26
- Example config.ru:
27
-
28
- require 'rackables'
29
- require 'rackables/more/env_inquirer'
30
- require 'my_endpont_app'
31
-
32
- if Rack.env.development?
33
- use Rack::ShowExceptions
34
- else
35
- use Rackables::HideExceptions, 'public/500.html'
36
- end
37
-
38
- use Rackables::TrailingSlashRedirect
39
- use Rackables::CacheControl, :public, :max_age => 60
40
- use Rackables::DefaultCharset, 'utf-8'
41
-
42
- use Rackables::Get, '/ping_monitor' do
43
- "pong"
44
- end
45
-
46
- use Rackables::Branch do |env|
47
- Rack::Lobster if env["PATH_INFO"] =~ /^\/lobster$/
48
- end
49
-
50
- run MyEndpointApp
data/Rakefile DELETED
@@ -1,22 +0,0 @@
1
- require 'rake/testtask'
2
-
3
- Rake::TestTask.new do |t|
4
- t.libs << "test"
5
- t.test_files = FileList['test/test*.rb']
6
- t.verbose = true
7
- end
8
- task :default => :test
9
-
10
- begin
11
- require 'jeweler'
12
- Jeweler::Tasks.new do |gemspec|
13
- gemspec.name = "rackables"
14
- gemspec.summary = "Bundle of useful Rack middleware"
15
- gemspec.description = "Bundles Rack middleware: CacheControl, DefaultCharset, PublicExceptionPage, TrailingSlashRedirect"
16
- gemspec.email = "gbuesing@gmail.com"
17
- gemspec.homepage = "http://github.com/gbuesing/rackables"
18
- gemspec.authors = ["Geoff Buesing"]
19
- end
20
- rescue LoadError
21
- puts "Jeweler not available. Install it with: gem install jeweler"
22
- end
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.2.0
@@ -1,45 +0,0 @@
1
- module Rackables
2
- # Simplest example:
3
- #
4
- # use Rackables::Get, '/ping_monitor' do
5
- # 'pong'
6
- # end
7
- #
8
- # Rack::Response object is yielded as second argument to block:
9
- #
10
- # use Rackables::Get, '/json' do |env, response|
11
- # response['Content-Type'] = 'application/json'
12
- # %({"foo": "bar"})
13
- # end
14
- #
15
- # Example with regular expression -- match data object is yielded as third argument to block
16
- #
17
- # use Rackables::Get, %r{^/(john|paul|george|ringo)} do |env, response, match|
18
- # "Hello, #{match[1]}"
19
- # end
20
- #
21
- # A false/nil return from block will not return a response; control will continue down the
22
- # Rack stack:
23
- #
24
- # use Rackables::Get, '/api_key' do |env, response|
25
- # '12345' if env['myapp.user'].authorized?
26
- # end
27
- class Get
28
- def initialize(app, path, &block)
29
- @app = app
30
- @path = path
31
- @block = block
32
- end
33
-
34
- def call(env)
35
- path, method = env['PATH_INFO'].to_s, env['REQUEST_METHOD']
36
- if method == 'GET' && ((@path.is_a?(Regexp) && match = @path.match(path)) || @path == path)
37
- response = ::Rack::Response.new
38
- response.body = @block.call(env, response, match)
39
- response.body ? response.finish : @app.call(env)
40
- else
41
- @app.call(env)
42
- end
43
- end
44
- end
45
- end
@@ -1 +0,0 @@
1
- <h1>Custom 500 page</h1>
@@ -1,26 +0,0 @@
1
- require 'test/unit'
2
- require 'rackables'
3
-
4
- class TestBranch < Test::Unit::TestCase
5
-
6
- def test_calls_app_returned_from_block
7
- app = Proc.new { [200, {}, ["Downstream app"]] }
8
- blog = Proc.new { [200, {}, ["Blog"]] }
9
- middleware = Rackables::Branch.new(app) do |env|
10
- blog if env['PATH_INFO'] =~ /^\/blog/
11
- end
12
- status, headers, body = middleware.call('PATH_INFO' => '/blog')
13
- assert_equal 'Blog', body[0]
14
- end
15
-
16
- def test_calls_app_passed_in_to_initialize_when_block_returns_false
17
- app = Proc.new { [200, {}, ["Downstream app"]] }
18
- blog = Proc.new { [200, {}, ["Blog"]] }
19
- middleware = Rackables::Branch.new(app) do |env|
20
- blog if env['PATH_INFO'] =~ /^\/blog/
21
- end
22
- status, headers, body = middleware.call('PATH_INFO' => '/foo')
23
- assert_equal 'Downstream app', body[0]
24
- end
25
-
26
- end
@@ -1,57 +0,0 @@
1
- require 'test/unit'
2
- require 'rackables'
3
-
4
- class TestCacheControl < Test::Unit::TestCase
5
-
6
- def test_sets_cache_control_with_value_set_as_integer
7
- app = Proc.new { [200, {}, []]}
8
- middleware = Rackables::CacheControl.new(app, :public, :max_age => 5)
9
- status, headers, body = middleware.call({})
10
- assert_equal 'public, max-age=5', headers['Cache-Control']
11
- end
12
-
13
- def test_sets_cache_control_with_value_set_as_string
14
- app = Proc.new { [200, {}, []]}
15
- middleware = Rackables::CacheControl.new(app, :public, :community => "UCI")
16
- status, headers, body = middleware.call({})
17
- assert_equal %(public, community="UCI"), headers['Cache-Control']
18
- end
19
-
20
- def test_sets_cache_control_with_value_specified_as_proc_which_is_called_at_runtime
21
- app = Proc.new { [200, {}, []]}
22
- value = 7 #compile-time value
23
- middleware = Rackables::CacheControl.new(app, :public, :max_age => Proc.new {value})
24
- value = 5 #runtime value
25
- status, headers, body = middleware.call({})
26
- assert_equal 'public, max-age=5', headers['Cache-Control']
27
- end
28
-
29
- def test_sets_cache_control_with_multiple_values
30
- app = Proc.new { [200, {}, []]}
31
- middleware = Rackables::CacheControl.new(app, :private, :no_cache, :must_revalidate)
32
- status, headers, body = middleware.call({})
33
- assert_equal %(private, no-cache, must-revalidate), headers['Cache-Control']
34
- end
35
-
36
- def test_sets_true_value
37
- app = Proc.new { [200, {}, []]}
38
- middleware = Rackables::CacheControl.new(app, :private, :must_revalidate => true)
39
- status, headers, body = middleware.call({})
40
- assert_equal 'private, must-revalidate', headers['Cache-Control']
41
- end
42
-
43
- def test_does_not_set_false_value
44
- app = Proc.new { [200, {}, []]}
45
- middleware = Rackables::CacheControl.new(app, :private, :must_revalidate => false)
46
- status, headers, body = middleware.call({})
47
- assert_equal 'private', headers['Cache-Control']
48
- end
49
-
50
- def test_respects_existing_cache_control_header
51
- app = Proc.new { [200, {'Cache-Control' => 'private'}, []]}
52
- middleware = Rackables::CacheControl.new(app, :public, :max_age => 5)
53
- status, headers, body = middleware.call({})
54
- assert_equal 'private', headers['Cache-Control']
55
- end
56
-
57
- end
@@ -1,27 +0,0 @@
1
- require 'test/unit'
2
- require 'rackables'
3
-
4
- class TestDefaultCharset < Test::Unit::TestCase
5
-
6
- def test_adds_utf8_charset_by_default
7
- app = Proc.new { [200, {'Content-Type' => 'text/html'}, []]}
8
- middleware = Rackables::DefaultCharset.new(app)
9
- status, headers, body = middleware.call({})
10
- assert_equal 'text/html; charset=utf-8', headers['Content-Type']
11
- end
12
-
13
- def test_adds_specified_charset
14
- app = Proc.new { [200, {'Content-Type' => 'text/html'}, []]}
15
- middleware = Rackables::DefaultCharset.new(app, 'us-ascii')
16
- status, headers, body = middleware.call({})
17
- assert_equal 'text/html; charset=us-ascii', headers['Content-Type']
18
- end
19
-
20
- def test_does_not_overwrite_existing_charset_value
21
- app = Proc.new { [200, {'Content-Type' => 'text/html; charset=us-ascii'}, []]}
22
- middleware = Rackables::DefaultCharset.new(app, 'iso-8859-2')
23
- status, headers, body = middleware.call({})
24
- assert_equal 'text/html; charset=us-ascii', headers['Content-Type']
25
- end
26
-
27
- end
@@ -1,80 +0,0 @@
1
- require 'test/unit'
2
- require 'rackables'
3
- require 'rubygems'
4
- require 'rack'
5
-
6
- class TestGet < Test::Unit::TestCase
7
-
8
- def setup
9
- @app = Proc.new { [200, {}, ["Downstream app"]] }
10
- end
11
-
12
- def test_calls_downstream_app_when_no_match
13
- middleware = Rackables::Get.new(@app, '/foo') { 'bar' }
14
- status, headers, body = middleware.call('PATH_INFO' => '/bar', 'REQUEST_METHOD' => 'GET')
15
- assert_equal 200, status
16
- assert_equal 'Downstream app', body[0]
17
- end
18
-
19
- def test_calls_downstream_app_when_path_matches_but_request_method_is_not_get
20
- middleware = Rackables::Get.new(@app, '/foo') { 'bar' }
21
- status, headers, body = middleware.call('PATH_INFO' => '/foo', 'REQUEST_METHOD' => 'POST')
22
- assert_equal 200, status
23
- assert_equal 'Downstream app', body[0]
24
- end
25
-
26
- def test_calls_downstream_app_when_path_matches_but_block_returns_nil
27
- middleware = Rackables::Get.new(@app, '/foo') { }
28
- status, headers, body = middleware.call('PATH_INFO' => '/foo', 'REQUEST_METHOD' => 'GET')
29
- assert_equal 200, status
30
- assert_equal 'Downstream app', body[0]
31
- end
32
-
33
- def test_get_returns_response_when_string_path_arg_matches_path_info
34
- middleware = Rackables::Get.new(@app, '/foo') { 'bar' }
35
- status, headers, body = middleware.call('PATH_INFO' => '/foo', 'REQUEST_METHOD' => 'GET')
36
- assert_equal 200, status
37
- assert_equal 'bar', body.body
38
- end
39
-
40
- def test_get_returns_response_when_string_path_arg_matches_regex
41
- middleware = Rackables::Get.new(@app, /foo/) { 'bar' }
42
- status, headers, body = middleware.call('PATH_INFO' => '/bar/foo', 'REQUEST_METHOD' => 'GET')
43
- assert_equal 200, status
44
- assert_equal 'bar', body.body
45
- end
46
-
47
- def test_block_yields_env
48
- env = {'PATH_INFO' => '/foo', 'REQUEST_METHOD' => 'GET'}
49
- middleware = Rackables::Get.new(@app, '/foo') do |e, resp|
50
- assert_equal env, e
51
- end
52
- status, headers, body = middleware.call(env)
53
- end
54
-
55
- def test_block_yields_response_obj
56
- env = {'PATH_INFO' => '/foo', 'REQUEST_METHOD' => 'GET'}
57
- middleware = Rackables::Get.new(@app, '/foo') do |e, resp|
58
- assert_instance_of ::Rack::Response, resp
59
- end
60
- status, headers, body = middleware.call(env)
61
- end
62
-
63
- def test_block_yields_match_data
64
- env = {'PATH_INFO' => '/foobar', 'REQUEST_METHOD' => 'GET'}
65
- middleware = Rackables::Get.new(@app, /foo(.+)/) do |e, resp, match|
66
- assert_instance_of MatchData, match
67
- assert_equal 'bar', match[1]
68
- end
69
- status, headers, body = middleware.call(env)
70
- end
71
-
72
- def test_response_honors_headers_set_in_block
73
- middleware = Rackables::Get.new(@app, '/foo') {|e, r| r['X-Foo'] = 'bar'; 'baz' }
74
- status, headers, body = middleware.call('PATH_INFO' => '/foo', 'REQUEST_METHOD' => 'GET')
75
- assert_equal 200, status
76
- assert_equal 'bar', headers['X-Foo']
77
- assert_equal 'baz', body.body
78
- end
79
-
80
- end
@@ -1,30 +0,0 @@
1
- require 'test/unit'
2
- require 'rackables'
3
-
4
- class TestHideExceptions < Test::Unit::TestCase
5
-
6
- def test_returns_downstream_app_response_when_no_exception_raised
7
- app = Proc.new { [200, {'Content-Type' => 'text/html'}, ['Downstream app']]}
8
- middleware = Rackables::HideExceptions.new(app)
9
- status, headers, body = middleware.call({})
10
- assert_equal 200, status
11
- assert_equal ['Downstream app'], body
12
- end
13
-
14
- def test_returns_500_with_default_exception_page_when_exception_raised_by_downstream_app
15
- app = Proc.new { raise }
16
- middleware = Rackables::HideExceptions.new(app)
17
- status, headers, body = middleware.call({})
18
- assert_equal 500, status
19
- assert_match /We\'re sorry, but something went wrong/, body[0]
20
- end
21
-
22
- def test_returns_500_with_custom_exception_page_when_file_path_specified
23
- app = Proc.new { raise }
24
- middleware = Rackables::HideExceptions.new(app, 'test/fixtures/custom_500.html')
25
- status, headers, body = middleware.call({})
26
- assert_equal 500, status
27
- assert_match /Custom 500 page/, body[0]
28
- end
29
-
30
- end
@@ -1,39 +0,0 @@
1
- require 'test/unit'
2
- require 'rackables'
3
-
4
- class TestTrailingSlashRedirect < Test::Unit::TestCase
5
-
6
- def test_passes_to_downstream_app_when_no_trailing_slash_on_path_info
7
- app = Proc.new { [200, {'Content-Type' => 'text/html'}, ['Downstream app']]}
8
- middleware = Rackables::TrailingSlashRedirect.new(app)
9
- status, headers, body = middleware.call({'PATH_INFO' => '/foo'})
10
- assert_equal 200, status
11
- assert_equal ['Downstream app'], body
12
- assert_nil headers['Location']
13
- end
14
-
15
- def test_returns_301_when_trailing_slash_on_path_info
16
- app = Proc.new { [200, {'Content-Type' => 'text/html'}, ['Downstream app']]}
17
- middleware = Rackables::TrailingSlashRedirect.new(app)
18
- status, headers, body = middleware.call({'rack.url_scheme' => 'http', 'HTTP_HOST' => 'bar.com', 'PATH_INFO' => '/foo/'})
19
- assert_equal 301, status
20
- assert_equal 'http://bar.com/foo', headers['Location']
21
- end
22
-
23
- def test_301_respects_query_string
24
- app = Proc.new { [200, {'Content-Type' => 'text/html'}, ['Downstream app']]}
25
- middleware = Rackables::TrailingSlashRedirect.new(app)
26
- status, headers, body = middleware.call({'rack.url_scheme' => 'http', 'HTTP_HOST' => 'bar.com', 'PATH_INFO' => '/foo/', 'QUERY_STRING' => 'baz=hi'})
27
- assert_equal 301, status
28
- assert_equal 'http://bar.com/foo?baz=hi', headers['Location']
29
- end
30
-
31
- def test_301_respects_https
32
- app = Proc.new { [200, {'Content-Type' => 'text/html'}, ['Downstream app']]}
33
- middleware = Rackables::TrailingSlashRedirect.new(app)
34
- status, headers, body = middleware.call({'rack.url_scheme' => 'https', 'HTTP_HOST' => 'bar.com', 'PATH_INFO' => '/foo/', 'QUERY_STRING' => 'baz=hi'})
35
- assert_equal 301, status
36
- assert_equal 'https://bar.com/foo?baz=hi', headers['Location']
37
- end
38
-
39
- end