diff --git a/lib/apache/config.rb b/lib/apache/config.rb index 0056424..722eea5 100644 --- a/lib/apache/config.rb +++ b/lib/apache/config.rb @@ -14,6 +14,7 @@ module Apache include Apache::Logging include Apache::Performance include Apache::Rewrites + include Apache::MPM # Build the provided configuration only if the current environment matches one of the conditions def build_if(target, *conditions, &block) @@ -144,17 +145,16 @@ module Apache private def writable?(path) - if !File.directory? File.split(path).first - puts "[warn] #{path} may not be writable!" - end + puts "[warn] #{path} may not be writable!" if !File.directory? File.split(path).first end def directory?(path) - if !File.directory? path - puts "[warn] #{path} does not exist!" - end + puts "[warn] #{path} does not exist!" if !File.directory? path end + def exist?(path) + puts "[warn] #{path} does not exist!" if !File.exist?(path) + end end block_methods :virtual_host, :files_match, :location, :files diff --git a/lib/apache/mpm_prefork.rb b/lib/apache/mpm_prefork.rb index a2ef301..98f5756 100644 --- a/lib/apache/mpm_prefork.rb +++ b/lib/apache/mpm_prefork.rb @@ -1,5 +1,17 @@ module Apache module MPM + # Set up the Prefork MPM + # + # The block you pass in to this can take the following methods: + # * start(num) - StartServers + # * spares(min, max) - Min and MaxSpareServers + # * limit(num) - ServerLimit + # * clients(num) - MaxClients + # * max_requests(num) - MaxRequestsPerChild + def prefork_config(&block) + self + Apache::MPM::Prefork.build(&block) + end + class Prefork class << self def build(&block) diff --git a/lib/apache/performance.rb b/lib/apache/performance.rb index f749b6a..a8ed98a 100644 --- a/lib/apache/performance.rb +++ b/lib/apache/performance.rb @@ -11,9 +11,5 @@ module Apache end end end - - def prefork_config(&block) - self + Apache::MPM::Prefork.build(&block) - end end end diff --git a/lib/apache/permissions.rb b/lib/apache/permissions.rb index fa404ef..36db79c 100644 --- a/lib/apache/permissions.rb +++ b/lib/apache/permissions.rb @@ -5,11 +5,15 @@ module Apache deny :from_all end + alias :deny_from_all! :deny_from_all + def allow_from_all order :allow, :deny allow :from_all end + alias :allow_from_all! :allow_from_all + def allow_from(where) allow "from_#{where}".to_sym end @@ -36,6 +40,7 @@ module Apache alias :order! :order def basic_authentication(zone, users_file, requires) + exist? users_file auth_type :basic auth_name zone auth_user_file users_file @@ -44,6 +49,8 @@ module Apache end end + alias :basic_authentication! :basic_authentication + def ldap_authentication(zone, url, requires) auth_type :basic auth_name zone @@ -55,6 +62,8 @@ module Apache end end + alias :ldap_authentication! :ldap_authentication + def apache_require(*opts) self << "Require #{opts * " "}" end diff --git a/lib/apache/rewrites.rb b/lib/apache/rewrites.rb index d9a2a3f..ccedc9b 100644 --- a/lib/apache/rewrites.rb +++ b/lib/apache/rewrites.rb @@ -26,8 +26,12 @@ module Apache class << self attr_accessor :rewrites - def build(&block) + def reset! @rewrites = [] + end + + def build(&block) + reset! self.instance_eval(&block) @@ -49,6 +53,8 @@ module Apache commit! end + alias :rule :rewrite + def cond(*opts) ensure_rewrite! @rewrite.cond(*opts) @@ -75,6 +81,16 @@ module Apache end end + module RegularExpressionMatcher + def test(from, opts = {}) + from = from.gsub(@from, @to.gsub(/\$([0-9])/) { |m| '\\' + $1 }) + opts.each do |opt, value| + from = from.gsub('%{' + opt.to_s.upcase + '}', value) + end + from + end + end + class MatchableThing include Apache::Quoteize @@ -83,14 +99,48 @@ module Apache def initialize @from = nil @to = nil - @options = nil - @conditions = [] end - def rule(from, to, *opts) + def rule(from, to) @from = from @to = to - @options = opts.first + end + + def to_s + "#{tag} #{[quoteize(@from), quoteize(@to)].compact.flatten * " "}" + end + + def to_a + [ to_s ] + end + end + + class RewriteRule < MatchableThing + include RegularExpressionMatcher + + def tag; 'RewriteRule'; end + + def initialize + super + @conditions = [] + @options = nil + end + + def rule(from, to,options = {}) + super(from, to) + + raise "from must be a Regexp" if !from.kind_of?(Regexp) + + options = options.collect do |key, value| + case key + when :last + 'L' + when :preserve_query_string + 'QSA' + end + end + + @options = !options.empty? ? "[#{options * ','}]" : nil end def cond(from, to, *opts) @@ -100,52 +150,58 @@ module Apache @conditions << rewrite_cond end - def test(from, opts) - from = from.gsub(@from, @to.gsub(/\$([0-9])/) { |m| '\\' + $1 }) - opts.each do |opt, value| - from = from.gsub('%{' + opt.to_s.upcase + '}', value) - end - from + def to_s + "#{tag} #{[quoteize(@from.source), quoteize(@to), @options].compact.flatten * " "}" end def to_a output = @conditions.collect(&:to_s) - options = @options.collect do |key, value| - case key - when :last - 'L' - when :preserve_query_string - 'QSA' - end - end - - if !options.empty? - options = "[#{options * ','}]" - else - options = nil - end - - output << "#{tag} #{[quoteize(@from.source), quoteize(@to), options].compact.flatten * " "}" + output += super output end end - class RewriteRule < MatchableThing - def tag; 'RewriteRule'; end - end - class RedirectMatchPermanent < MatchableThing + include RegularExpressionMatcher + def tag; 'RedirectMatch permanent'; end + + def to_s + "#{tag} #{[quoteize(@from.source), quoteize(@to)].compact.flatten * " "}" + end end class RewriteCondition < MatchableThing def tag; 'RewriteCond'; end + + def rule(from, to, *opts) + super(from, to) + + options = opts.collect do |opt| + case opt + when :or + 'OR' + when :case_insensitive + 'NC' + when :no_vary + 'NV' + end + end + + @options = (!options.empty?) ? "[#{options * ','}]" : nil + end + alias :cond :rule + def initialize + super + @options = nil + end + def to_s - "#{tag} #{[quoteize(@from), quoteize(@to), @options].flatten * " "}" + "#{tag} #{[quoteize(@from), quoteize(@to), @options].compact.flatten * " "}" end end end diff --git a/spec/mpm_prefork_spec.rb b/spec/mpm_prefork_spec.rb new file mode 100644 index 0000000..1f7b7a1 --- /dev/null +++ b/spec/mpm_prefork_spec.rb @@ -0,0 +1,28 @@ +require 'spec_helper' + +describe Apache::Config, "prefork MPM" do + let(:apache) { Apache::Config } + before { apache.reset! } + + it "should build the prefork options" do + apache.prefork_config do + start 10 + spares 10, 30 + limit 20 + clients 100 + max_requests 1000 + end + + apache.to_a.should == [ + '', + '# Prefork config', + '', + 'StartServers 10', + 'MinSpareServers 10', + 'MaxSpareServers 30', + 'ServerLimit 20', + 'MaxClients 100', + 'MaxRequestsPerChild 1000' + ] + end +end diff --git a/spec/performance_spec.rb b/spec/performance_spec.rb new file mode 100644 index 0000000..f4b35c3 --- /dev/null +++ b/spec/performance_spec.rb @@ -0,0 +1,16 @@ +require 'spec_helper' + +describe Apache::Config, "performance settings" do + let(:apache) { Apache::Config } + before { apache.reset! } + + it "should set keepalive" do + apache.activate_keepalive({ :timeout => 10, :requests => 100 }) + + apache.to_a.should == [ + 'KeepAlive On', + 'MaxKeepAliveRequests 100', + 'KeepAliveTimeout 10' + ] + end +end diff --git a/spec/permissions_spec.rb b/spec/permissions_spec.rb new file mode 100644 index 0000000..c3f4686 --- /dev/null +++ b/spec/permissions_spec.rb @@ -0,0 +1,34 @@ +require 'spec_helper' + +describe Apache::Config, "permissions" do + let(:apache) { Apache::Config } + before { apache.reset! } + + it "should set up allow and deny groups" do + apache.deny_from_all! + apache.to_a.should == [ 'Order deny,allow', 'Deny from all' ] + + apache.reset! + apache.allow_from_all! + apache.to_a.should == [ 'Order allow,deny', 'Allow from all' ] + end + + it "should allow from somewhere" do + apache.allow_from '1.2.3.4' + apache.to_a.should == [ 'Allow from 1.2.3.4' ] + end + + # Verify the blob output in apache itself, just make sure the method doesn't bomb + it "should verify some blob functions don't fail" do + apache.default_restrictive! + apache.no_htfiles! + + apache.basic_authentication("My site", '/path/to/users/file', :user => :john) + apache.ldap_authentication("My site", 'ldap url', 'ldap-path' => 'path') + end + + it "should add an auth require" do + apache.apache_require 'user', :john, :scott + apache.to_a.should == [ 'Require user john scott' ] + end +end diff --git a/spec/rewrites_spec.rb b/spec/rewrites_spec.rb new file mode 100644 index 0000000..e7159da --- /dev/null +++ b/spec/rewrites_spec.rb @@ -0,0 +1,99 @@ +require 'spec_helper' + +describe Apache::Config, "rewrites" do + let(:apache) { Apache::Config } + before { apache.reset! } + + it "should enable the rewrite engine" do + apache.enable_rewrite_engine :log_level => 1 + apache.to_a.should == [ + '', + 'RewriteEngine on', + 'RewriteLogLevel 1', + '' + ] + end + + it "should add a simple redirect permanent" do + apache.r301 '/here', '/there' + apache.to_a.should == [ + 'Redirect permanent "/here" "/there"' + ] + end + + it "should build rewrites" do + apache.rewrites do + rule %r{^/$}, '/test' + end + apache.to_a.should == [ + 'RewriteRule "^/$" "/test"', '' + ] + end +end + +describe Apache::RewriteManager, "specific rewrite rules" do + let(:rewrite) { Apache::RewriteManager } + before { rewrite.reset! } + + it "should create a rewrite" do + rewrite.build do + cond '%{REQUEST_FILENAME}', 'test' + rule %r{^/$}, '/test' + + r301 %r{^/success$}, '/test' + + rewrite_test '/', '/test' + rewrite_test '/fail', '/test' + rewrite_test '/%{REQUEST_FILENAME}', '/test', :request_filename => 'success' + end.should == [ + 'RewriteCond "%{REQUEST_FILENAME}" "test"', + 'RewriteRule "^/$" "/test"', + 'RedirectMatch permanent "^/success$" "/test"' + ] + end +end + +describe Apache::MatchableThing, "something that can be matched" do + subject do + thing = Apache::MatchableThing.new + thing.rule('here', 'there') + + class << thing + def tag; "RSpec"; end + end + + thing + end + + its(:to_s) { should == 'RSpec "here" "there"' } + its(:to_a) { should == [ 'RSpec "here" "there"' ] } +end + +describe Apache::RewriteRule, "a RewriteRule" do + subject do + rule = Apache::RewriteRule.new + rule.cond('%{REQUEST_FILENAME}', '^/test$') + rule.rule(%r{^/$}, '/test', :last => true, :preserve_query_string => true) + rule + end + + its(:to_s) { should == 'RewriteRule "^/$" "/test" [L,QSA]' } + its(:to_a) { should == [ + 'RewriteCond "%{REQUEST_FILENAME}" "^/test$"', + 'RewriteRule "^/$" "/test" [L,QSA]' + ] } + + it "should pass the test" do + subject.test('/').should == '/test' + end +end + +describe Apache::RewriteCondition, "a RewriteCond" do + subject do + cond = Apache::RewriteCondition.new + cond.cond('%{REQUEST_FILENAME}', '^/test$', :or, :case_insensitive, :no_vary) + cond + end + + its(:to_s) { should == 'RewriteCond "%{REQUEST_FILENAME}" "^/test$" [OR,NC,NV]' } +end