public
Description: A very fast & simple Ruby web server
Homepage: http://code.macournoyer.com/thin/
Clone URL: git://github.com/macournoyer/thin.git
Search Repo:
Merge branch 'master' of git@github.com:macournoyer/thin
kevwil (author)
Mon Jan 21 07:46:33 -0800 2008
commit  45a2c426a56ae0a448b97345c12a180b13071ffc
tree    79a91700bb07f13c3be228da111a19e1a69c5b41
parent  ba0358b125faa89c72ce68f8b8c6302e626480fa parent  c06d16415c8b47870513ba44b508c29857790df6
...
1
 
 
2
3
4
...
1
2
3
4
5
6
0
@@ -1,4 +1,6 @@
0
 == 0.5.5 Pony release
0
+ * Alter response headers to output directly to a string.
0
+ * Improve specs stability.
0
  * Move request body to a Tempfile if too big (> 112 MB)
0
  * Remove useless check for max header size in Request (already done in the parser)
0
 
...
8
9
10
11
 
...
8
9
10
 
11
0
@@ -8,5 +8,5 @@
0
 
0
 Dir['tasks/**/*.rake'].each { |rake| load rake }
0
 
0
-task :default => [:compile, :spec]
0
+task :default => :spec
...
26
27
28
29
 
30
31
32
...
26
27
28
 
29
30
31
32
0
@@ -26,7 +26,7 @@
0
     end
0
     
0
     def pid
0
- File.exist?(pid_file) ? open(pid_file).read : nil
0
+ File.exist?(pid_file) ? open(pid_file).read.to_i : nil
0
     end
0
     
0
     # Turns the current script into a daemon process that detaches from the console.
...
1
2
 
 
3
4
5
6
7
8
9
 
10
11
12
13
14
15
16
17
 
18
19
 
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 
35
36
37
...
1
 
2
3
4
5
6
7
8
9
 
10
11
12
13
 
 
 
 
 
14
15
 
16
17
18
19
 
 
 
 
 
 
 
 
 
 
20
 
21
22
23
24
0
@@ -1,37 +1,24 @@
0
 module Thin
0
- # Acts like a Hash, but allows duplicated keys
0
+ # Store HTTP header name-value pairs direcly to a string
0
+ # and allow duplicated entries on some names.
0
   class Headers
0
     HEADER_FORMAT = "%s: %s\r\n".freeze
0
     ALLOWED_DUPLICATES = %w(Set-Cookie Set-Cookie2 Warning WWW-Authenticate).freeze
0
     
0
     def initialize
0
       @sent = {}
0
- @items = []
0
+ @out = ''
0
     end
0
     
0
     def []=(key, value)
0
- if @sent.has_key?(key) && !ALLOWED_DUPLICATES.include?(key)
0
- # If we don't allow duplicate for that field
0
- # we overwrite the one that is already there
0
- @items.assoc(key)[1] = value
0
- else
0
+ if !@sent[key] || ALLOWED_DUPLICATES.include?(key)
0
         @sent[key] = true
0
- @items << [key, value]
0
+ @out << HEADER_FORMAT % [key, value]
0
       end
0
     end
0
     
0
- def [](key)
0
- if item = @items.assoc(key)
0
- item[1]
0
- end
0
- end
0
-
0
- def size
0
- @items.size
0
- end
0
-
0
     def to_s
0
- @items.inject('') { |out, (name, value)| out << HEADER_FORMAT % [name, value] }
0
+ @out
0
     end
0
   end
0
 end
...
2
3
4
5
 
6
7
8
9
 
10
11
...
2
3
4
 
5
6
7
8
 
9
10
11
0
@@ -2,11 +2,11 @@
0
   module VERSION #:nodoc:
0
     MAJOR = 0
0
     MINOR = 5
0
- TINY = 4
0
+ TINY = 5
0
     
0
     STRING = [MAJOR, MINOR, TINY].join('.')
0
     
0
- CODENAME = 'Flying Mustard'
0
+ CODENAME = 'Pony'
0
   end
0
 end
...
23
24
25
26
 
27
28
29
...
89
90
91
 
92
93
...
23
24
25
 
26
27
28
29
...
89
90
91
92
93
94
0
@@ -23,7 +23,7 @@
0
     File.exist?(@server.pid_file).should be_true
0
     @pid = @server.pid
0
 
0
- proc { sleep 0.1 while File.exist?(@server.pid_file) }.should take_less_then(2)
0
+ proc { sleep 0.1 while File.exist?(@server.pid_file) }.should take_less_then(5)
0
   end
0
   
0
   it 'should redirect stdio to a log file' do
0
@@ -89,6 +89,7 @@
0
   
0
   after do
0
     Process.kill(9, @pid.to_i) if @pid && Process.running?(@pid.to_i)
0
+ Process.kill(9, @server.pid) if @server.pid && Process.running?(@server.pid)
0
   end
0
 end
...
9
10
11
12
 
13
14
15
16
17
18
19
20
21
22
23
24
25
 
26
27
28
...
9
10
11
 
12
13
14
15
16
17
 
18
 
 
 
 
 
 
19
20
21
22
0
@@ -9,20 +9,14 @@
0
     @headers['Set-Cookie'] = 'twice'
0
     @headers['Set-Cookie'] = 'is cooler the once'
0
     
0
- @headers.size.should == 2
0
+ @headers.to_s.should == "Set-Cookie: twice\r\nSet-Cookie: is cooler the once\r\n"
0
   end
0
   
0
   it 'should overwrite value on non duplicate fields' do
0
     @headers['Host'] = 'this is unique'
0
     @headers['Host'] = 'so is this'
0
- @headers['Host'] = 'so this will overwrite ^'
0
 
0
- @headers['Host'].should == 'so this will overwrite ^'
0
- end
0
-
0
- it 'should return first header value' do
0
- @headers['Set-Cookie'] = 'hi'
0
- @headers['Set-Cookie'].should == 'hi'
0
+ @headers.to_s.should == "Host: this is unique\r\n"
0
   end
0
   
0
   it 'should output to string' do
...
209
210
211
212
213
 
 
214
215
216
...
226
227
228
229
 
230
231
232
...
209
210
211
 
 
212
213
214
215
216
...
226
227
228
 
229
230
231
232
0
@@ -209,8 +209,8 @@
0
     proc { R("GET / HTTP/1.1\r\n#{big_headers}\r\n") }.should raise_error(InvalidRequest)
0
   end
0
   
0
- it "should be faster then #{max_parsing_time = 0.2} ms" do
0
- body = <<-EOS.chomp
0
+ it "should be faster then #{max_parsing_time = 0.0002} RubySeconds" do
0
+ body = <<-EOS.chomp.gsub("\n", "\r\n")
0
 POST /postit HTTP/1.1
0
 Host: localhost:3000
0
 User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.9) Gecko/20071025 Firefox/2.0.0.9
0
@@ -226,7 +226,7 @@
0
 hi=there&name=marc&email=macournoyer@gmail.com
0
 EOS
0
     
0
- proc { R(body, true) }.should be_faster_then(max_parsing_time)
0
+ proc { R(body) }.should be_faster_then(max_parsing_time)
0
   end
0
   
0
   it 'should be comparable to Mongrel parser' do
...
52
53
54
55
 
56
57
58
...
52
53
54
 
55
56
57
58
0
@@ -52,7 +52,7 @@
0
     out.should include("\r\n\r\n<html></html>")
0
   end
0
   
0
- it "should be faster then #{max_parsing_time = 0.07} ms" do
0
+ it "should be faster then #{max_parsing_time = 0.00011} RubySecond" do
0
     @response.body << <<-EOS
0
 <html><head><title>Dir listing</title></head>
0
 <body><h1>Listing stuff</h1><ul>
...
49
50
51
52
 
53
54
55
56
57
 
 
58
59
60
...
49
50
51
 
52
53
54
55
 
 
56
57
58
59
60
0
@@ -49,12 +49,12 @@
0
     post('/', :big => big).size.should == big.size + 4
0
   end
0
   
0
- it "should handle GET in less then #{get_request_time = 5} ms" do
0
+ it "should handle GET in less then #{get_request_time = 0.004} RubySecond" do
0
     proc { get('/') }.should be_faster_then(get_request_time)
0
   end
0
   
0
- it "should handle POST in less then #{post_request_time = 6} ms" do
0
- proc { post('/', :file => 'X' * 1000) }.should be_faster_then(get_request_time)
0
+ it "should handle POST in less then #{post_request_time = 0.007} RubySecond" do
0
+ proc { post('/', :file => 'X' * 1000) }.should be_faster_then(post_request_time)
0
   end
0
   
0
   after do
...
4
5
6
 
7
8
9
10
...
31
32
33
34
35
36
37
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
39
40
41
 
42
43
44
...
4
5
6
7
8
9
10
11
...
32
33
34
 
 
 
 
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
 
61
62
63
64
0
@@ -4,6 +4,7 @@
0
 require 'benchmark'
0
 require 'timeout'
0
 require 'fileutils'
0
+require 'benchmark_unit'
0
 
0
 include Thin
0
 
0
0
@@ -31,14 +32,33 @@
0
       @max_time = max_time
0
     end
0
 
0
- def matches?(target)
0
- @target = target
0
- @time = Benchmark.measure { @target.call }.real * 1000
0
- @time <= @max_time
0
+ # Base on benchmark_unit/assertions#compare_benchmarks
0
+ def matches?(proc)
0
+ @time, multiplier = 0, 1
0
+
0
+ while (@time < 0.01) do
0
+ @time = Benchmark::Unit.measure do
0
+ multiplier.times &proc
0
+ end
0
+ multiplier *= 10
0
+ end
0
+
0
+ multiplier /= 10
0
+
0
+ iterations = (Benchmark::Unit::CLOCK_TARGET / @time).to_i * multiplier
0
+ iterations = 1 if iterations < 1
0
+
0
+ total = Benchmark::Unit.measure do
0
+ iterations.times &proc
0
+ end
0
+
0
+ @time = total / iterations
0
+
0
+ @time < @max_time
0
     end
0
     
0
     def failure_message(less_more=:less)
0
- "took #{@time} ms, should take #{less_more} then #{@max_time} ms"
0
+ "took <#{@time.inspect} RubySeconds>, should take #{less_more} than #{@max_time} RubySeconds."
0
     end
0
 
0
     def negative_failure_message
...
22
23
24
25
 
26
27
28
...
22
23
24
 
25
26
27
28
0
@@ -22,7 +22,7 @@
0
   end
0
 
0
   s.files = %w(COPYING CHANGELOG README Rakefile) +
0
- Dir.glob("{benchmark,bin,doc,example,lib,spec}/**/*") +
0
+ Dir.glob("{benchmark,bin,doc,example,lib,spec,tasks}/**/*") +
0
                             Dir.glob("ext/**/*.{h,c,rb,rl}")
0
   
0
   if WIN
...
12
13
14
 
 
 
 
 
 
 
 
 
 
 
15
...
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
0
@@ -12,5 +12,16 @@
0
   Spec::Rake::SpecTask.new('spec') do |t|
0
     t.spec_files = FileList['spec/**/*_spec.rb']
0
   end
0
+
0
+ task :check_spec_gems do
0
+ begin
0
+ require 'spec'
0
+ require 'benchmark_unit'
0
+ rescue LoadError
0
+ abort "To run specs, install rspec and benchmark_unit gems"
0
+ end
0
+ end
0
+
0
+ task :spec => [:check_spec_gems, :compile]
0
 end

Comments

    No one has commented yet.