rackables 0.2.0 → 0.3.0

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