rack-combobot 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rack-combobot (0.0.2)
4
+ rack-combobot (0.0.3)
5
5
  rack
6
6
  rake
7
7
 
@@ -12,7 +12,7 @@ GEM
12
12
  guard (0.10.0)
13
13
  ffi (>= 0.5.0)
14
14
  thor (~> 0.14.6)
15
- guard-minitest (0.4.0)
15
+ guard-minitest (0.5.0)
16
16
  guard (~> 0.4)
17
17
  minitest (2.10.0)
18
18
  rack (1.4.0)
data/Guardfile CHANGED
@@ -1,6 +1,5 @@
1
1
  guard 'minitest' do
2
2
  watch(%r|^spec/(.*)_spec\.rb|)
3
- watch(%r|^lib/(.*)\.rb|) { |m| "spec/#{m[1]}_spec.rb" }
4
- watch(%r|^lib/rack/(.*)\.rb|) { |m| "spec/rack_#{m[1]}_spec.rb" }
5
- watch(%r|^spec/spec_helper\.rb|) { "spec" }
3
+ watch(%r|^lib/(.*)\.rb|) { |m| "spec/#{m[1]}_spec.rb" }
4
+ watch(%r|^spec/spec_helper\.rb|) { "spec" }
6
5
  end
data/Rakefile CHANGED
@@ -7,7 +7,7 @@ require 'rake'
7
7
  require 'rake/testtask'
8
8
 
9
9
  Rake::TestTask.new do |t|
10
- t.pattern = "spec/*_spec.rb"
10
+ t.pattern = "spec/**/*_spec.rb"
11
11
  end
12
12
 
13
13
  task :default => [:test]
data/config.ru ADDED
@@ -0,0 +1,6 @@
1
+ require 'rack'
2
+ require './lib/rack-combobot'
3
+
4
+ use Rack::Combobot, :root => 'spec/public'
5
+
6
+ run Proc.new {|env| [200, {"Content-Type" => "text/html"}, ["Dummy App"]] }
@@ -0,0 +1,33 @@
1
+ # encoding: UTF-8
2
+
3
+ module Rack
4
+ class Combobot
5
+ class Combination
6
+ def initialize(root, file_names)
7
+ @root = root
8
+
9
+ @file_contents = fetch_file_contents file_names if file_names
10
+ end
11
+
12
+ def fetch_file_contents(file_names = [])
13
+ file_names.map do |file_name|
14
+
15
+ raise PathError if file_name.include?('..') || file_name.include?("~")
16
+
17
+ root_prefix = ::File.expand_path(".", @root) + "/"
18
+ file_path = ::File.expand_path(file_name, @root)
19
+
20
+ raise PathError unless file_path.start_with?(root_prefix) && ::File.exist?(file_path)
21
+
22
+ file_content = ::File.open(file_path, 'r') { |f| f.read }
23
+ end
24
+ end
25
+
26
+ def combine
27
+ @combo ||= @file_contents.join
28
+ end
29
+
30
+ class PathError < ArgumentError; end
31
+ end
32
+ end
33
+ end
data/lib/rack/combobot.rb CHANGED
@@ -1,32 +1,45 @@
1
+ # encoding: UTF-8
2
+
1
3
  require "rack/combobot/config"
4
+ require "rack/combobot/combination"
2
5
  require "pathname"
3
6
  require "uri"
4
7
 
5
8
  module Rack
6
9
  class Combobot
7
- def self.configure(*args)
8
- new(*args)
9
- end
10
10
 
11
11
  MIME_TYPES = {
12
12
  "js" => "text/javascript",
13
13
  "css" => "text/css"
14
14
  }
15
15
 
16
- def initialize(options = {})
16
+ def initialize(app, options = {})
17
+ @app = app
18
+
17
19
  root = Pathname.new(options[:root] || Dir.pwd)
18
20
  @config = Rack::Combobot::Config.new(root)
19
21
  end
20
22
 
21
23
  # rack request handler
22
24
  def call(env)
25
+ if Rack::Request.new(env).path == '/combobot'
26
+ combine(env)
27
+ else
28
+ @app.call(env)
29
+ end
30
+ end
31
+
32
+ def combine(env)
23
33
  params = env["QUERY_STRING"]
24
34
  file_names = params.split("&")
25
- extention = file_names[0].split(".").last
35
+
36
+ return not_found if file_names.empty?
37
+
38
+ extension = file_names[0].split(".").last
26
39
 
27
40
  begin
28
41
  combo = Combination.new(@config.root, file_names).combine
29
- [200, {"Content-Type" => MIME_TYPES[extention]}, [combo]]
42
+ [200, {"Content-Type" => MIME_TYPES[extension]}, [combo]]
30
43
  rescue Combination::PathError
31
44
  not_found
32
45
  end
@@ -36,30 +49,5 @@ module Rack
36
49
  [404, {'Content-Type' => 'text/html'}, ['File not found']]
37
50
  end
38
51
 
39
- class Combination
40
- def initialize(root, file_names)
41
- @file_contents = combine_files(root, file_names)
42
- end
43
-
44
- def combine_files(root, file_names = [])
45
- file_names.map do |file_name|
46
-
47
- raise PathError if file_name.include?('..') || file_name.include?("~")
48
-
49
- root_prefix = ::File.expand_path(".", root) + "/"
50
- file_path = ::File.expand_path(file_name, root)
51
-
52
- raise PathError unless file_path.start_with?(root_prefix) && ::File.exist?(file_path)
53
-
54
- file_content = ::File.open(file_path, 'r') { |f| f.read }
55
- end
56
- end
57
-
58
- def combine
59
- @combo ||= @file_contents.join
60
- end
61
-
62
- class PathError < ArgumentError; end
63
- end
64
52
  end
65
53
  end
@@ -4,7 +4,7 @@ $:.push File.expand_path("../lib", __FILE__)
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = "rack-combobot"
7
- s.version = "0.0.3"
7
+ s.version = "0.1.0"
8
8
  s.authors = ["Simon Højberg", "Christopher Meiklejohn"]
9
9
  s.email = ["r.hackr@gmail.com", "christopher.meiklejohn@gmail.com"]
10
10
  s.homepage = "https://github.com/hojberg/rack-combobot"
@@ -0,0 +1,41 @@
1
+ require File.dirname(__FILE__) + '/../../../spec_helper'
2
+
3
+ describe Rack::Combobot::Combination do
4
+
5
+ let(:combination) { Rack::Combobot::Combination.new(File.dirname(__FILE__) + '/../../../public', ['js1.js', 'js2.js']) }
6
+
7
+ describe 'fetch' do
8
+
9
+ it 'fetches files content' do
10
+ contents = combination.fetch_file_contents(['js1.js', 'js2.js'])
11
+ contents.must_equal(["function lorem() { return \"a\"; }\n", "function ipsum() { return \"b\"; }\n"])
12
+ end
13
+
14
+ describe 'error handling' do
15
+ it 'raises PathError when files are not found' do
16
+ proc {
17
+ combination.fetch_file_contents(['js3.js'])
18
+ }.must_raise Rack::Combobot::Combination::PathError
19
+ end
20
+
21
+ it 'raises PathError when trying to move outside the root' do
22
+ proc {
23
+ combination.fetch_file_contents(['js1.js', '../../etc/hosts'])
24
+ }.must_raise Rack::Combobot::Combination::PathError
25
+ end
26
+ end
27
+ end
28
+
29
+ describe 'combination' do
30
+
31
+ before do
32
+ combination.fetch_file_contents(['js1.js', 'js2.js'])
33
+ end
34
+
35
+ it 'combines file content' do
36
+ combination.combine.must_equal("function lorem() { return \"a\"; }\nfunction ipsum() { return \"b\"; }\n")
37
+ end
38
+
39
+ end
40
+
41
+ end
@@ -0,0 +1,49 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe Rack::Combobot do
4
+ include Rack::Test::Methods
5
+
6
+ # the dummy app represents any other middleware in the rack stack
7
+ let(:dummy_app_response) { [200, {"Content-Type" => "text/html"}, ["Dummy App"]] }
8
+ let(:dummy_app) { Proc.new {|env| dummy_app_response } }
9
+
10
+ before do
11
+ @app = Rack::Combobot.new(dummy_app, :root => File.dirname(__FILE__) + '/../../public')
12
+ end
13
+
14
+ describe 'routing' do
15
+
16
+ # request helpers
17
+ let(:combobot_request) { { 'PATH_INFO' => '/combobot' } }
18
+ let(:combobot_js_request) { combobot_request.merge({ "QUERY_STRING" => "js1.js&js2.js" }) }
19
+ let(:combobot_css_request) { combobot_request.merge({ "QUERY_STRING" => "css1.css&css2.css" }) }
20
+ let(:combobot_404_request) { combobot_request.merge({ "QUERY_STRING" => "js3.js&js4.js" }) }
21
+ let(:combobot_hack_request) { combobot_request.merge({ "QUERY_STRING" => "js3.js&../../js4.js" }) }
22
+
23
+ # response helpers
24
+ let(:combobot_js_response) { [200, {"Content-Type" => "text/javascript"}, ["function lorem() { return \"a\"; }\nfunction ipsum() { return \"b\"; }\n"]] }
25
+ let(:combobot_css_response) { [200, {"Content-Type" => "text/css"}, [".lorem { background: blue; }\n#lipsum { border: 1px solid red }\n"]] }
26
+ let(:combobot_404_response) { [404, {'Content-Type' => 'text/html'}, ['File not found']] }
27
+
28
+ it 'should not respond to anything other than "/combobot"' do
29
+ @app.call({}).must_equal(dummy_app_response)
30
+ end
31
+
32
+ it "combines javascript" do
33
+ @app.call(combobot_js_request).must_equal(combobot_js_response)
34
+ end
35
+
36
+ it "combines css" do
37
+ @app.call(combobot_css_request).must_equal(combobot_css_response)
38
+ end
39
+
40
+ it "returns 404 when it can't find files" do
41
+ @app.call(combobot_404_request).must_equal(combobot_404_response)
42
+ end
43
+
44
+ it 'returns 404 when trying to move up from the root dir' do
45
+ @app.call(combobot_hack_request).must_equal(combobot_404_response)
46
+ end
47
+ end
48
+
49
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-combobot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-03-09 00:00:00.000000000 Z
13
+ date: 2012-03-14 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rake
17
- requirement: &2154066720 !ruby/object:Gem::Requirement
17
+ requirement: &2153707180 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: '0'
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *2154066720
25
+ version_requirements: *2153707180
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: rack
28
- requirement: &2154066280 !ruby/object:Gem::Requirement
28
+ requirement: &2153706740 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ! '>='
@@ -33,10 +33,10 @@ dependencies:
33
33
  version: '0'
34
34
  type: :runtime
35
35
  prerelease: false
36
- version_requirements: *2154066280
36
+ version_requirements: *2153706740
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: minitest
39
- requirement: &2154065860 !ruby/object:Gem::Requirement
39
+ requirement: &2153706320 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
42
  - - ! '>='
@@ -44,10 +44,10 @@ dependencies:
44
44
  version: '0'
45
45
  type: :development
46
46
  prerelease: false
47
- version_requirements: *2154065860
47
+ version_requirements: *2153706320
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: rack-test
50
- requirement: &2154065440 !ruby/object:Gem::Requirement
50
+ requirement: &2153705900 !ruby/object:Gem::Requirement
51
51
  none: false
52
52
  requirements:
53
53
  - - ! '>='
@@ -55,10 +55,10 @@ dependencies:
55
55
  version: '0'
56
56
  type: :development
57
57
  prerelease: false
58
- version_requirements: *2154065440
58
+ version_requirements: *2153705900
59
59
  - !ruby/object:Gem::Dependency
60
60
  name: guard
61
- requirement: &2154065020 !ruby/object:Gem::Requirement
61
+ requirement: &2153705480 !ruby/object:Gem::Requirement
62
62
  none: false
63
63
  requirements:
64
64
  - - ! '>='
@@ -66,10 +66,10 @@ dependencies:
66
66
  version: '0'
67
67
  type: :development
68
68
  prerelease: false
69
- version_requirements: *2154065020
69
+ version_requirements: *2153705480
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: guard-minitest
72
- requirement: &2154064600 !ruby/object:Gem::Requirement
72
+ requirement: &2153705060 !ruby/object:Gem::Requirement
73
73
  none: false
74
74
  requirements:
75
75
  - - ! '>='
@@ -77,7 +77,7 @@ dependencies:
77
77
  version: '0'
78
78
  type: :development
79
79
  prerelease: false
80
- version_requirements: *2154064600
80
+ version_requirements: *2153705060
81
81
  description: combines assets to server 1 file
82
82
  email:
83
83
  - r.hackr@gmail.com
@@ -94,15 +94,18 @@ files:
94
94
  - Guardfile
95
95
  - README.md
96
96
  - Rakefile
97
+ - config.ru
97
98
  - lib/rack-combobot.rb
98
99
  - lib/rack/combobot.rb
100
+ - lib/rack/combobot/combination.rb
99
101
  - lib/rack/combobot/config.rb
100
102
  - rack-combobot.gemspec
103
+ - spec/lib/rack/combobot/combination_spec.rb
104
+ - spec/lib/rack/combobot_spec.rb
101
105
  - spec/public/css1.css
102
106
  - spec/public/css2.css
103
107
  - spec/public/js1.js
104
108
  - spec/public/js2.js
105
- - spec/rack_combobot_spec.rb
106
109
  - spec/spec_helper.rb
107
110
  homepage: https://github.com/hojberg/rack-combobot
108
111
  licenses: []
@@ -129,9 +132,10 @@ signing_key:
129
132
  specification_version: 3
130
133
  summary: asset combinator
131
134
  test_files:
135
+ - spec/lib/rack/combobot/combination_spec.rb
136
+ - spec/lib/rack/combobot_spec.rb
132
137
  - spec/public/css1.css
133
138
  - spec/public/css2.css
134
139
  - spec/public/js1.js
135
140
  - spec/public/js2.js
136
- - spec/rack_combobot_spec.rb
137
141
  - spec/spec_helper.rb
@@ -1,50 +0,0 @@
1
- require File.dirname(__FILE__) + '/spec_helper'
2
-
3
- describe "combing assets from query string" do
4
- include Rack::Test::Methods
5
-
6
- before(:each) do
7
- @app = Rack::Combobot.configure(:root => File.dirname(__FILE__) + '/public')
8
- end
9
-
10
- it "combines javascript" do
11
- @app.call({
12
- "QUERY_STRING" => "js1.js&js2.js"
13
- }).must_equal([
14
- 200,
15
- {"Content-Type" => "text/javascript"},
16
- ["function lorem() { return \"a\"; }\nfunction ipsum() { return \"b\"; }\n"]
17
- ])
18
- end
19
-
20
- it "combines css" do
21
- @app.call({
22
- "QUERY_STRING" => "css1.css&css2.css"
23
- }).must_equal([
24
- 200,
25
- {"Content-Type" => "text/css"},
26
- [".lorem { background: blue; }\n#lipsum { border: 1px solid red }\n"]
27
- ])
28
- end
29
-
30
- it "returns 404 when it can't find files" do
31
- @app.call({
32
- "QUERY_STRING" => "js3.js&js4.js"
33
- }).must_equal([
34
- 404,
35
- {'Content-Type' => 'text/html'},
36
- ['File not found']
37
- ])
38
- end
39
-
40
- it 'returns 404 when trying to move up from the root dir' do
41
- @app.call({
42
- "QUERY_STRING" => "js3.js&../../js4.js"
43
- }).must_equal([
44
- 404,
45
- {'Content-Type' => 'text/html'},
46
- ['File not found']
47
- ])
48
- end
49
-
50
- end