hayabusa 0.0.20 → 0.0.22

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -10,6 +10,7 @@ gem "datet"
10
10
  gem "http2"
11
11
  gem "tpool"
12
12
  gem "fcgi"
13
+ gem "ruby_process"
13
14
 
14
15
  # Add dependencies to develop your gem here.
15
16
  # Include everything needed to run rake, tests, features, etc.
@@ -18,5 +19,6 @@ group :development do
18
19
  gem "rspec", ">= 2.3.0"
19
20
  gem "bundler", ">= 1.0.0"
20
21
  gem "jeweler", "~> 1.6.3"
22
+ gem "rmagick"
21
23
  gem "sqlite3" if RUBY_ENGINE != "jruby"
22
24
  end
@@ -1,49 +1,54 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- datet (0.0.20)
5
- diff-lcs (1.1.3)
4
+ datet (0.0.25)
5
+ diff-lcs (1.2.4)
6
6
  erubis (2.7.0)
7
- fcgi (0.8.8)
7
+ fcgi (0.9.1)
8
8
  git (1.2.5)
9
- http2 (0.0.12)
10
- i18n (0.6.1)
9
+ http2 (0.0.21)
11
10
  jeweler (1.6.4)
12
11
  bundler (~> 1.0)
13
12
  git (>= 1.2.5)
14
13
  rake
15
- json (1.7.5)
16
- knjrbfw (0.0.99)
14
+ json (1.8.0)
15
+ knjrbfw (0.0.105)
17
16
  datet
18
17
  http2
19
18
  php4r
19
+ ruby_process
20
20
  tsafe
21
21
  wref
22
- mail (2.4.4)
23
- i18n (>= 0.4.0)
22
+ mail (2.5.4)
24
23
  mime-types (~> 1.16)
25
24
  treetop (~> 1.4.8)
26
- mime-types (1.19)
27
- php4r (0.0.3)
25
+ mime-types (1.23)
26
+ php4r (0.0.4)
28
27
  datet
29
28
  http2
29
+ string-strtr
30
30
  polyglot (0.3.3)
31
- rake (0.9.2.2)
32
- rspec (2.11.0)
33
- rspec-core (~> 2.11.0)
34
- rspec-expectations (~> 2.11.0)
35
- rspec-mocks (~> 2.11.0)
36
- rspec-core (2.11.1)
37
- rspec-expectations (2.11.3)
38
- diff-lcs (~> 1.1.3)
39
- rspec-mocks (2.11.3)
40
- sqlite3 (1.3.6)
31
+ rake (10.1.0)
32
+ rmagick (2.13.2)
33
+ rspec (2.13.0)
34
+ rspec-core (~> 2.13.0)
35
+ rspec-expectations (~> 2.13.0)
36
+ rspec-mocks (~> 2.13.0)
37
+ rspec-core (2.13.1)
38
+ rspec-expectations (2.13.0)
39
+ diff-lcs (>= 1.1.3, < 2.0)
40
+ rspec-mocks (2.13.1)
41
+ ruby_process (0.0.8)
42
+ tsafe
43
+ wref
44
+ sqlite3 (1.3.7)
45
+ string-strtr (0.0.3)
41
46
  tpool (0.0.4)
42
- treetop (1.4.10)
47
+ treetop (1.4.14)
43
48
  polyglot
44
49
  polyglot (>= 0.3.1)
45
50
  tsafe (0.0.11)
46
- wref (0.0.5)
51
+ wref (0.0.6)
47
52
 
48
53
  PLATFORMS
49
54
  ruby
@@ -58,6 +63,8 @@ DEPENDENCIES
58
63
  json
59
64
  knjrbfw
60
65
  mail
66
+ rmagick
61
67
  rspec (>= 2.3.0)
68
+ ruby_process
62
69
  sqlite3
63
70
  tpool
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.20
1
+ 0.0.22
@@ -4,14 +4,14 @@
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
- s.name = %q{hayabusa}
8
- s.version = "0.0.20"
7
+ s.name = "hayabusa"
8
+ s.version = "0.0.22"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Kasper Johansen"]
12
- s.date = %q{2012-10-12}
13
- s.description = %q{A threadded web/app-server that focuses on threadding, shared ressources, speed and more.}
14
- s.email = %q{k@spernj.org}
12
+ s.date = "2013-06-28"
13
+ s.description = "A threadded web/app-server that focuses on threadding, shared ressources, speed and more."
14
+ s.email = "k@spernj.org"
15
15
  s.executables = ["check_running.rb", "hayabusa_benchmark.rb", "hayabusa_cgi.rb", "hayabusa_fcgi.fcgi", "hayabusa_fcgi.rb", "hayabusa_fcgi_server.rb", "hayabusa_spec_restart.rb", "knjappserver_start.rb"]
16
16
  s.extra_rdoc_files = [
17
17
  "LICENSE.txt",
@@ -96,6 +96,7 @@ Gem::Specification.new do |s|
96
96
  "pages/spec_vars_header.rhtml",
97
97
  "pages/spec_vars_post.rhtml",
98
98
  "pages/spec_vars_post_fileupload.rhtml",
99
+ "pages/testpic.jpeg",
99
100
  "pages/tests.rhtml",
100
101
  "pages/threadded_content_test.rhtml",
101
102
  "spec/fcgi_multiple_processes_spec.rb",
@@ -103,11 +104,11 @@ Gem::Specification.new do |s|
103
104
  "spec/spec_helper.rb",
104
105
  "spec/test_upload.xlsx"
105
106
  ]
106
- s.homepage = %q{http://github.com/kaspernj/hayabusa}
107
+ s.homepage = "http://github.com/kaspernj/hayabusa"
107
108
  s.licenses = ["MIT"]
108
109
  s.require_paths = ["lib"]
109
- s.rubygems_version = %q{1.6.2}
110
- s.summary = %q{A threadded web/app-server that supports stand-alone, CGI and FCGI-modes.}
110
+ s.rubygems_version = "1.8.23"
111
+ s.summary = "A threadded web/app-server that supports stand-alone, CGI and FCGI-modes."
111
112
 
112
113
  if s.respond_to? :specification_version then
113
114
  s.specification_version = 3
@@ -120,10 +121,12 @@ Gem::Specification.new do |s|
120
121
  s.add_runtime_dependency(%q<http2>, [">= 0"])
121
122
  s.add_runtime_dependency(%q<tpool>, [">= 0"])
122
123
  s.add_runtime_dependency(%q<fcgi>, [">= 0"])
124
+ s.add_runtime_dependency(%q<ruby_process>, [">= 0"])
123
125
  s.add_development_dependency(%q<json>, [">= 0"])
124
126
  s.add_development_dependency(%q<rspec>, [">= 2.3.0"])
125
127
  s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
126
128
  s.add_development_dependency(%q<jeweler>, ["~> 1.6.3"])
129
+ s.add_development_dependency(%q<rmagick>, [">= 0"])
127
130
  s.add_development_dependency(%q<sqlite3>, [">= 0"])
128
131
  else
129
132
  s.add_dependency(%q<knjrbfw>, [">= 0"])
@@ -133,10 +136,12 @@ Gem::Specification.new do |s|
133
136
  s.add_dependency(%q<http2>, [">= 0"])
134
137
  s.add_dependency(%q<tpool>, [">= 0"])
135
138
  s.add_dependency(%q<fcgi>, [">= 0"])
139
+ s.add_dependency(%q<ruby_process>, [">= 0"])
136
140
  s.add_dependency(%q<json>, [">= 0"])
137
141
  s.add_dependency(%q<rspec>, [">= 2.3.0"])
138
142
  s.add_dependency(%q<bundler>, [">= 1.0.0"])
139
143
  s.add_dependency(%q<jeweler>, ["~> 1.6.3"])
144
+ s.add_dependency(%q<rmagick>, [">= 0"])
140
145
  s.add_dependency(%q<sqlite3>, [">= 0"])
141
146
  end
142
147
  else
@@ -147,10 +152,12 @@ Gem::Specification.new do |s|
147
152
  s.add_dependency(%q<http2>, [">= 0"])
148
153
  s.add_dependency(%q<tpool>, [">= 0"])
149
154
  s.add_dependency(%q<fcgi>, [">= 0"])
155
+ s.add_dependency(%q<ruby_process>, [">= 0"])
150
156
  s.add_dependency(%q<json>, [">= 0"])
151
157
  s.add_dependency(%q<rspec>, [">= 2.3.0"])
152
158
  s.add_dependency(%q<bundler>, [">= 1.0.0"])
153
159
  s.add_dependency(%q<jeweler>, ["~> 1.6.3"])
160
+ s.add_dependency(%q<rmagick>, [">= 0"])
154
161
  s.add_dependency(%q<sqlite3>, [">= 0"])
155
162
  end
156
163
  end
@@ -34,7 +34,7 @@ class Hayabusa
34
34
  :default_filetype => "text/html",
35
35
  :max_requests_working => 20,
36
36
  :size_send => 1024,
37
- :cleaner_timeout => 300,
37
+ :cleaner_timeout => 60,
38
38
  :mailing_time => 30
39
39
  }.merge(config)
40
40
 
@@ -52,20 +52,20 @@ class Hayabusa
52
52
  [:Tpool, "tpool"]
53
53
  ]
54
54
 
55
- gems.each do |gem|
56
- if Kernel.const_defined?(gem[0])
57
- puts "Gem already loaded: '#{gem[1]}'." if @debug
55
+ gems.each do |gem_i|
56
+ if Kernel.const_defined?(gem_i[0])
57
+ puts "Gem already loaded: '#{gem_i[1]}'." if @debug
58
58
  next
59
59
  end
60
60
 
61
- fpath = "#{@@path}/../../#{gem[1]}/lib/#{gem[1]}.rb"
61
+ fpath = "#{@@path}/../../#{gem_i[1]}/lib/#{gem_i[1]}.rb"
62
62
 
63
63
  if File.exists?(fpath)
64
64
  puts "Loading custom gem-path: '#{fpath}'." if @debug
65
65
  require fpath
66
66
  else
67
- puts "Loading gem: '#{gem[1]}'." if @debug
68
- require gem[1]
67
+ puts "Loading gem: '#{gem_i[1]}'." if @debug
68
+ require gem_i[1]
69
69
  end
70
70
  end
71
71
 
@@ -544,4 +544,4 @@ class Hayabusa
544
544
 
545
545
  return @translations
546
546
  end
547
- end
547
+ end
@@ -110,8 +110,7 @@ class Hayabusa::Cgi_session < Hayabusa::Client_session
110
110
  rescue SystemExit
111
111
  #do nothing - ignore.
112
112
  rescue Timeout::Error
113
- @resp.status = 500
114
- print "The request timed out."
113
+ @resp.status = 408
115
114
  end
116
115
  end
117
116
 
@@ -22,6 +22,14 @@ class Hayabusa::Client_session
22
22
  @cgroup.force_content(newcont)
23
23
  end
24
24
 
25
+ #Forces the output to be read from a file.
26
+ def force_fileread(fpath)
27
+ raise "Invalid filepath given: '#{fpath}'." if !fpath || !File.exists?(fpath)
28
+ @resp.chunked = false
29
+ @resp.header("Content-Length", File.size(fpath))
30
+ @cgroup.new_io(:type => :file, :path => fpath)
31
+ end
32
+
25
33
  #Creates a new Hayabusa::Binding-object and returns the binding for that object.
26
34
  def create_binding
27
35
  return Hayabusa::Http_session::Page_environment.new(:httpsession => self, :hb => @hb).get_binding
@@ -82,6 +90,7 @@ class Hayabusa::Client_session
82
90
  if @handlers_cache.key?(@ext)
83
91
  @hb.log_puts("Calling handler.") if @debug
84
92
  @handlers_cache[@ext].call(self)
93
+ @hb.log_puts("Called handler.") if @debug
85
94
  else
86
95
  #check if we should use a handler for this request.
87
96
  @config[:handlers].each do |handler_info|
@@ -125,7 +134,7 @@ class Hayabusa::Client_session
125
134
  end
126
135
  end
127
136
 
128
- @cgroup.new_io(:type => :file, :path => @page_path)
137
+ self.force_fileread(@page_path)
129
138
  end
130
139
  end
131
140
  end
@@ -133,8 +142,8 @@ class Hayabusa::Client_session
133
142
  rescue SystemExit
134
143
  #do nothing - ignore.
135
144
  rescue Timeout::Error
136
- @resp.status = 500
137
- print "The request timed out."
145
+ @resp.status = 408
146
+ @hb.log_puts "The request timed out."
138
147
  end
139
148
  end
140
149
 
@@ -144,10 +153,7 @@ class Hayabusa::Client_session
144
153
  @hb.log_puts "#{__id__} - Served '#{@meta["REQUEST_URI"]}' in #{Time.now.to_f - @time_start} secs (#{@resp.status})." if @debug
145
154
  @time_start = nil
146
155
  @cgroup.join
147
-
148
- @hb.events.call(:request_done, {
149
- :httpsession => self
150
- }) if @hb.events
156
+ @hb.events.call(:request_done, :httpsession => self) if @hb.events
151
157
  @httpsession_var = {}
152
158
  end
153
- end
159
+ end
@@ -20,7 +20,7 @@ class Hayabusa::Erb_handler
20
20
  httpsess.resp.status = 500 if eruby.error
21
21
  end
22
22
 
23
- #Handels the event when an error in the eruby-instance occurs.
23
+ # Handels the event when an error in the eruby-instance occurs.
24
24
  def on_error(e)
25
25
  _hb.handle_error(e)
26
26
  end
@@ -9,7 +9,6 @@ class Hayabusa
9
9
 
10
10
  def clean
11
11
  self.clean_sessions
12
- self.clean_autorestart
13
12
  end
14
13
 
15
14
  def clean_autorestart
@@ -108,18 +107,17 @@ class Hayabusa
108
107
  #Clean up various inactive sessions.
109
108
  session_not_ids = []
110
109
  time_check = Time.now.to_i - 300
111
- newsessions = {}
112
- @sessions.each do |session_hash, session_data|
110
+ @sessions.delete_if do |session_hash, session_data|
113
111
  session_data[:dbobj].flush
114
112
 
115
- if session_data[:time_lastused].to_i > time_check
116
- newsessions[session_hash] = session_data
113
+ if session_data[:dbobj].date_lastused.to_i > time_check
117
114
  session_not_ids << session_data[:dbobj].id
115
+ false
116
+ else
117
+ true
118
118
  end
119
119
  end
120
120
 
121
- @sessions = newsessions
122
-
123
121
  self.log_puts("Delete sessions...") if @debug
124
122
  @ob.list(:Session, {"id_not" => session_not_ids, "date_lastused_below" => (Time.now - 5356800)}) do |session|
125
123
  idhash = session[:idhash]
@@ -116,7 +116,7 @@ class Hayabusa
116
116
  begin
117
117
  block.call
118
118
  rescue => e
119
- self.alert(e.message).back
119
+ Knj::Web.alert(e.message).back
120
120
  end
121
121
  end
122
122
 
@@ -60,17 +60,17 @@ class Hayabusa
60
60
 
61
61
  #Use subprocessing to avoid the mail-framework (activesupport and so on, also possible memory leaks in those large frameworks).
62
62
  self.log_puts("Starting subprocess for mailing.") if @debug
63
- Knj::Process_meta.new("debug" => @debug, "debug_err" => true, "id" => "hayabusa_mailing") do |subproc|
64
- subproc.static("Object", "require", "rubygems")
65
- subproc.static("Object", "require", "mail")
66
- subproc.static("Object", "require", "#{@config[:knjrbfw_path]}knjrbfw")
67
- subproc.static("Object", "require", "knj/autoload")
63
+ Ruby_process::Cproxy.run do |data|
64
+ subproc = data[:subproc]
65
+ subproc.static(:Object, :require, "rubygems")
66
+ subproc.static(:Object, :require, "mail")
67
+ subproc.static(:Object, :require, "#{Knj.knjrbfw_path}/../knjrbfw.rb")
68
68
 
69
69
  self.log_puts("Flushing emails.") if @debug
70
70
  @mails_waiting.each do |mail|
71
71
  begin
72
72
  self.log_puts("Sending email: #{mail.__id__}") if @debug
73
- if mail.send("proc" => subproc)
73
+ if mail.send(:proc => subproc)
74
74
  self.log_puts("Email sent: #{mail.__id__}") if @debug
75
75
  @mails_waiting.delete(mail)
76
76
  end
@@ -119,25 +119,19 @@ class Hayabusa
119
119
  def send(args = {})
120
120
  @args[:hb].log_puts("Sending mail '#{__id__}'.") if @args[:hb].debug
121
121
 
122
- if args["proc"]
123
- args["proc"].static("Object", "require", "knj/mailobj")
124
- mail = args["proc"].new("Knj::Mailobj", @args[:hb].config[:smtp_args])
125
- mail._pm_send_noret("to=", @args[:to])
126
- mail._pm_send_noret("subject=", @args[:subject]) if @args[:subject]
127
- mail._pm_send_noret("html=", Knj::Strings.email_str_safe(@args[:html])) if @args[:html]
128
- mail._pm_send_noret("text=", Knj::Strings.email_str_safe(@args[:text])) if @args[:text]
129
- mail._pm_send_noret("from=", @args[:from])
130
- mail._pm_send_noret("send")
122
+ if args[:proc]
123
+ mail = args[:proc].new("Knj::Mailobj", @args[:hb].config[:smtp_args])
131
124
  else
132
125
  mail = Knj::Mailobj.new(@args[:hb].config[:smtp_args])
133
- mail.to = @args[:to]
134
- mail.subject = @args[:subject] if @args[:subject]
135
- mail.html = Knj::Strings.email_str_safe(@args[:html]) if @args[:html]
136
- mail.text = Knj::Strings.email_str_safe(@args[:text]) if @args[:text]
137
- mail.from = @args[:from]
138
- mail.send
139
126
  end
140
127
 
128
+ mail.to = @args[:to]
129
+ mail.subject = @args[:subject] if @args[:subject]
130
+ mail.html = Knj::Strings.email_str_safe(@args[:html]) if @args[:html]
131
+ mail.text = Knj::Strings.email_str_safe(@args[:text]) if @args[:text]
132
+ mail.from = @args[:from]
133
+ mail.send
134
+
141
135
  @args[:status] = :sent
142
136
  @args[:hb].log_puts("Sent email #{self.__id__}") if @args[:hb].debug
143
137
  return true
@@ -1,4 +1,6 @@
1
1
  class Hayabusa
2
+ attr_reader :sessions
3
+
2
4
  def initialize_sessions
3
5
  @sessions = Tsafe::MonHash.new
4
6
  end
@@ -13,8 +15,11 @@ class Hayabusa
13
15
  session = @ob.add(:Session, {
14
16
  :idhash => idhash,
15
17
  :user_agent => meta["HTTP_USER_AGENT"],
16
- :ip => ip
18
+ :ip => ip,
19
+ :date_lastused => Time.now
17
20
  })
21
+ else
22
+ session[:date_lastused] = Time.now
18
23
  end
19
24
 
20
25
  hash = {}
@@ -28,8 +33,6 @@ class Hayabusa
28
33
  end
29
34
 
30
35
  raise ArgumentError, "Invalid IP." if ip != "bot" and !session.remember? and ip.to_s != session[:ip].to_s
31
-
32
- @sessions[idhash][:time_lastused] = Time.now
33
36
  return [session, hash]
34
37
  end
35
38
 
@@ -16,10 +16,10 @@ class Hayabusa
16
16
  end
17
17
 
18
18
  #Inits the thread so it has access to the appserver and various magic methods can be used.
19
- def thread_init(thread = nil)
20
- thread = Thread.current if thread == nil
19
+ def thread_init(thread = Thread.current)
21
20
  thread[:hayabusa] = {} if !thread[:hayabusa]
22
21
  thread[:hayabusa][:hb] = self
22
+ return nil
23
23
  end
24
24
 
25
25
  #Spawns a new thread with access to magic methods, _db-method and various other stuff in the appserver.
@@ -72,7 +72,7 @@ class Hayabusa
72
72
  thread[:hayabusa][:hb] = self
73
73
 
74
74
  begin
75
- block.call
75
+ return block.call
76
76
  ensure
77
77
  @ob.db.free_thread if @ob.db.opts[:threadsafe]
78
78
  @db_handler.free_thread if @db_handler.opts[:threadsafe]
@@ -100,7 +100,7 @@ class Hayabusa
100
100
 
101
101
  #Urlencodes a string.
102
102
  #===Examples
103
- # _hb.redirect("mypage.rhtml?arg=#{_hb.urlenc(value_variable)}")
103
+ # Knj::Web.redirect("mypage.rhtml?arg=#{_hb.urlenc(value_variable)}")
104
104
  def urlenc(str)
105
105
  return Knj::Web.urlenc(str)
106
106
  end
@@ -64,7 +64,7 @@ class Hayabusa::Fcgi
64
64
  end
65
65
 
66
66
  if hayabusa_conf[:debug]
67
- @fcgi_proxy[:fp_log] = File.open("/tmp/hayabusa_#{hayabusa_conf[:hayabusa][:title]}_#{Process.pid}.log", "w")
67
+ @fcgi_proxy[:fp_log] = File.open("/tmp/hayabusa_#{hayabusa_conf[:title]}_#{Process.pid}.log", "w")
68
68
  @fcgi_proxy[:fp_log].sync = true
69
69
  end
70
70
  rescue
@@ -82,31 +82,35 @@ class Hayabusa::Http_session < Hayabusa::Client_session
82
82
  @handler.socket_parse(@socket)
83
83
  end
84
84
 
85
- @hb.log_puts "#{__id__} - Done parsing from socket." if @debug
86
-
87
- while @hb.paused? #Check if we should be waiting with executing the pending request.
88
- @hb.log_puts "#{__id__} - Paused! (#{@hb.paused}) - sleeping." if @debug
89
- sleep 0.1
90
- end
91
-
92
- break if @hb.should_restart
93
-
94
- if max_requests_working and @httpserver
95
- while @httpserver.working_count.to_i >= max_requests_working
96
- @hb.log_puts "#{__id__} - Maximum amounts of requests are working (#{@httpserver.working_count}, #{max_requests_working}) - sleeping." if @debug
85
+ begin
86
+ @hb.log_puts "#{__id__} - Done parsing from socket." if @debug
87
+
88
+ while @hb.paused? #Check if we should be waiting with executing the pending request.
89
+ @hb.log_puts "#{__id__} - Paused! (#{@hb.paused}) - sleeping." if @debug
97
90
  sleep 0.1
98
91
  end
99
- end
100
-
101
- #Reserve database connections.
102
- @hb.db_handler.get_and_register_thread if @hb.db_handler.opts[:threadsafe]
103
- @hb.ob.db.get_and_register_thread if @hb.ob.db.opts[:threadsafe]
104
-
105
- @working = true
106
- @hb.log_puts "#{__id__} - Serving." if @debug
107
-
108
- @httpserver.count_block do
109
- self.serve
92
+
93
+ break if @hb.should_restart
94
+
95
+ if max_requests_working and @httpserver
96
+ while @httpserver.working_count.to_i >= max_requests_working
97
+ @hb.log_puts "#{__id__} - Maximum amounts of requests are working (#{@httpserver.working_count}, #{max_requests_working}) - sleeping." if @debug
98
+ sleep 0.1
99
+ end
100
+ end
101
+
102
+ #Reserve database connections.
103
+ @hb.db_handler.get_and_register_thread if @hb.db_handler.opts[:threadsafe]
104
+ @hb.ob.db.get_and_register_thread if @hb.ob.db.opts[:threadsafe]
105
+
106
+ @working = true
107
+ @hb.log_puts "#{__id__} - Serving." if @debug
108
+
109
+ @httpserver.count_block do
110
+ self.serve
111
+ end
112
+ ensure
113
+ @handler.delete_tempfiles
110
114
  end
111
115
  ensure
112
116
  @hb.log_puts "#{__id__} - Closing request." if @debug
@@ -132,11 +136,11 @@ class Hayabusa::Http_session < Hayabusa::Client_session
132
136
  end
133
137
 
134
138
  def self.finalize(id)
135
- @hb.log_puts "Http_session finalize #{id}." if @debug
139
+ @hb.log_puts "Hayabusa: Http_session finalize #{id}." if @debug
136
140
  end
137
141
 
138
142
  def destruct
139
- @hb.log_puts "Http_session destruct (#{@httpserver.http_sessions.length})" if @debug and @httpserver and @httpserver.http_sessions
143
+ @hb.log_puts "Hayabusa: Http_session destruct (#{@httpserver.http_sessions.length})" if @debug and @httpserver and @httpserver.http_sessions
140
144
 
141
145
  begin
142
146
  @socket.close if !@socket.closed?
@@ -153,7 +157,7 @@ class Hayabusa::Http_session < Hayabusa::Client_session
153
157
  end
154
158
 
155
159
  def serve
156
- @hb.log_puts "Generating meta, cookie, get, post and headers." if @debug
160
+ @hb.log_puts "Hayabusa: Generating meta, cookie, get, post and headers." if @debug
157
161
  @meta = @handler.meta.merge(@socket_meta)
158
162
  @cookie = @handler.cookie
159
163
  @get = @handler.get
@@ -184,7 +188,7 @@ class Hayabusa::Http_session < Hayabusa::Client_session
184
188
  @browser = Knj::Web.browser(@meta)
185
189
  @ip = @hb.ip(:meta => @meta)
186
190
 
187
- @hb.log_puts "Figuring out session-ID, session-object and more." if @debug
191
+ @hb.log_puts "Hayabusa: Figuring out session-ID, session-object and more." if @debug
188
192
  if @cookie["HayabusaSession"].to_s.length > 0
189
193
  @session_id = @cookie["HayabusaSession"]
190
194
  elsif @browser["browser"] == "bot"
@@ -213,7 +217,7 @@ class Hayabusa::Http_session < Hayabusa::Client_session
213
217
  end
214
218
 
215
219
  if @config.key?(:logging) and @config[:logging][:access_db]
216
- @hb.log_puts "Doing access-logging." if @debug
220
+ @hb.log_puts "Hayabusa: Doing access-logging." if @debug
217
221
  @ips = [@meta["REMOTE_ADDR"]]
218
222
  @ips << @meta["HTTP_X_FORWARDED_FOR"].split(",")[0].strip if @meta["HTTP_X_FORWARDED_FOR"]
219
223
  @hb.logs_access_pending << {
@@ -3,7 +3,7 @@
3
3
  #This class handels the adding of content and writing to socket. Since this can be done with multiple threads and multiple IO's it can get complicated.
4
4
  class Hayabusa::Http_session::Contentgroup
5
5
  attr_reader :done, :cur_data
6
- attr_accessor :chunked, :socket
6
+ attr_accessor :chunked, :socket, :content_length, :length_written
7
7
  NL = "\r\n"
8
8
 
9
9
  def initialize(args = {})
@@ -13,6 +13,8 @@ class Hayabusa::Http_session::Contentgroup
13
13
  @httpsession = args[:httpsession]
14
14
  @mutex = Mutex.new
15
15
  @debug = false
16
+ @length_written = args[:length_written] ? args[:length_written] : 0
17
+ @content_length = args[:content_length]
16
18
  end
17
19
 
18
20
  def init
@@ -30,6 +32,7 @@ class Hayabusa::Http_session::Contentgroup
30
32
  @done = false
31
33
  @thread = nil
32
34
  @forced = false
35
+ @length_written = 0
33
36
 
34
37
  @mutex.synchronize do
35
38
  self.new_io
@@ -55,7 +58,7 @@ class Hayabusa::Http_session::Contentgroup
55
58
  end
56
59
 
57
60
  def new_thread
58
- cgroup = Hayabusa::Http_session::Contentgroup.new(:socket => @socket, :chunked => @chunked)
61
+ cgroup = Hayabusa::Http_session::Contentgroup.new(:socket => @socket, :chunked => @chunked, :content_length => @content_length)
59
62
  cgroup.init
60
63
 
61
64
  @mutex.synchronize do
@@ -92,6 +95,8 @@ class Hayabusa::Http_session::Contentgroup
92
95
  STDERR.puts "Error while writing."
93
96
  STDERR.puts e.inspect
94
97
  STDERR.puts e.backtrace
98
+
99
+ raise e
95
100
  end
96
101
  end
97
102
  end
@@ -125,7 +130,12 @@ class Hayabusa::Http_session::Contentgroup
125
130
 
126
131
  @ios.each do |data|
127
132
  if data.is_a?(Hayabusa::Http_session::Contentgroup)
133
+ data.length_written = @length_written
134
+ data.content_length = @content_length
135
+ data.chunked = @chunked
128
136
  data.write_to_socket
137
+
138
+ @length_written += data.length_written
129
139
  elsif data.key?(:str)
130
140
  if data[:str].is_a?(Hash) and data[:str][:type] == :file
131
141
  File.open(data[:str][:path], "r") do |file|
@@ -136,6 +146,8 @@ class Hayabusa::Http_session::Contentgroup
136
146
  break
137
147
  end
138
148
 
149
+ add_to_length_written(buf.bytesize)
150
+
139
151
  if @chunked
140
152
  @socket.write("#{buf.length.to_s(16)}#{NL}#{buf}#{NL}")
141
153
  else
@@ -157,6 +169,7 @@ class Hayabusa::Http_session::Contentgroup
157
169
  #512 could take a long time for big pages. 16384 seems to be an optimal number.
158
170
  str.each_slice(16384) do |slice|
159
171
  buf = slice.pack("C*")
172
+ add_to_length_written(buf.bytesize)
160
173
 
161
174
  if @chunked
162
175
  @socket.write("#{buf.length.to_s(16)}#{NL}#{buf}#{NL}")
@@ -173,4 +186,10 @@ class Hayabusa::Http_session::Contentgroup
173
186
 
174
187
  count += 1
175
188
  end
189
+
190
+ # Adds the given size to the length written and raises an exception if it exceeds the sat content-length.
191
+ def add_to_length_written(size)
192
+ @length_written += size
193
+ raise "Content-Length overwritten: #{@length_written}, #{@content_length}" if @content_length != nil && @length_written > @content_length
194
+ end
176
195
  end
@@ -17,6 +17,7 @@ class Hayabusa::Http_session::Post_multipart
17
17
  @clength = 0
18
18
  @headers = {}
19
19
  @counts = {}
20
+ @files_arr = args[:files_arr]
20
21
  str_crlf = nil
21
22
 
22
23
  @args[:io].each do |line|
@@ -112,7 +113,11 @@ class Hayabusa::Http_session::Post_multipart
112
113
  return nil
113
114
  end
114
115
 
115
- @data.close(false) if @data.is_a?(Tempfile)
116
+ if @data.is_a?(Tempfile)
117
+ @data.close(false)
118
+ @files_arr << @data.path if @data.respond_to?(:path)
119
+ end
120
+
116
121
  raise "No 'content-disposition' was given (#{@headers}) (#{@data})." if !@name
117
122
 
118
123
  if @fname
@@ -203,4 +208,8 @@ class Hayabusa::Http_session::Post_multipart::File_upload
203
208
  def to_json(*args)
204
209
  raise "File_upload-objects should not be converted to json."
205
210
  end
211
+
212
+ def unset
213
+
214
+ end
206
215
  end
@@ -7,7 +7,7 @@ end
7
7
 
8
8
  #This class parses the various HTTP requests into easy programmable objects. Get, post, cookie, meta and so on...
9
9
  class Hayabusa::Http_session::Request
10
- attr_reader :get, :post, :cookie, :meta, :page_path, :headers, :http_version, :read, :clength, :speed, :percent, :secs_left
10
+ attr_reader :get, :post, :cookie, :files_arr, :meta, :page_path, :headers, :http_version, :read, :clength, :speed, :percent, :secs_left
11
11
 
12
12
  #Sets the various required data on the object. Hayabusa, crlf and arguments.
13
13
  def initialize(args)
@@ -79,6 +79,7 @@ class Hayabusa::Http_session::Request
79
79
 
80
80
  @page_path = "#{@hb.config[:doc_root]}/#{page_filepath}"
81
81
  @get = Knj::Web.parse_urlquery(uri[:query], :urldecode => true, :force_utf8 => true)
82
+ @files_arr = []
82
83
 
83
84
  if @get["_hb_httpsession_id"]
84
85
  @hb.httpsessions_ids[@get["_hb_httpsession_id"]] = @args[:httpsession]
@@ -187,7 +188,8 @@ class Hayabusa::Http_session::Request
187
188
  post_treated = Hayabusa::Http_session::Post_multipart.new(
188
189
  :io => post_data,
189
190
  :boundary => match[1],
190
- :crlf => @crlf
191
+ :crlf => @crlf,
192
+ :files_arr => @files_arr
191
193
  ).return
192
194
  post_data.close(true)
193
195
 
@@ -237,4 +239,12 @@ class Hayabusa::Http_session::Request
237
239
  Knj::Web.parse_name(seton, varname, value, args)
238
240
  end
239
241
  end
242
+
243
+ #Deletes all tempfiles created by this object. This is useually called from Http_session at the end of a request.
244
+ def delete_tempfiles
245
+ @files_arr.delete_if do |tempfile_path|
246
+ File.unlink(tempfile_path) if File.exists?(tempfile_path)
247
+ true
248
+ end
249
+ end
240
250
  end
@@ -21,6 +21,7 @@ class Hayabusa::Http_session::Response
21
21
  401 => "Unauthorized",
22
22
  403 => "Forbidden",
23
23
  404 => "Not Found",
24
+ 408 => "Request Timeout",
24
25
  500 => "Internal Server Error"
25
26
  }
26
27
  NL = "\r\n"
@@ -40,29 +41,18 @@ class Hayabusa::Http_session::Response
40
41
  @trailers = []
41
42
  @skip_statuscode = true if args[:mode] == :cgi
42
43
  @session_cookie = args[:cookie]
43
-
44
44
  @headers_sent = false
45
45
  @headers_trailing = {}
46
-
47
46
  @mode = args[:mode]
47
+ @cookies = []
48
48
 
49
49
  @headers = {
50
50
  "date" => ["Date", Time.now.httpdate]
51
51
  }
52
52
 
53
- @headers_11 = {
54
- "Connection" => "Keep-Alive"
55
- }
56
53
  if args[:mode] != :cgi and (!args.key?(:chunked) or args[:chunked])
57
- @headers_11["Transfer-Encoding"] = "chunked"
54
+ @chunked = true
58
55
  end
59
-
60
- #Socket-timeout is currently broken in JRuby.
61
- if RUBY_ENGINE != "jruby"
62
- @headers_11["Keep-Alive"] = "timeout=15, max=30"
63
- end
64
-
65
- @cookies = []
66
56
  end
67
57
 
68
58
  def header(key, val)
@@ -70,19 +60,48 @@ class Hayabusa::Http_session::Response
70
60
  raise "Value contains more lines than 1 (#{lines})." if lines > 1
71
61
 
72
62
  if !@headers_sent
73
- @headers[key.to_s.downcase] = [key, val]
63
+ @headers[key.to_s.downcase.strip] = [key, val]
74
64
  else
75
65
  raise "Headers already sent and given header was not in trailing headers: '#{key}'." if @trailers.index(key) == nil
76
- @headers_trailing[key.to_s.downcase] = [key, val]
66
+ @headers_trailing[key.to_s.downcase.strip] = [key, val]
77
67
  end
78
68
  end
79
69
 
70
+ # Returns the value of a header.
71
+ def get_header_value(header)
72
+ header_p = header.to_s.downcase.strip
73
+
74
+ gothrough = [@headers, @headers_trailing]
75
+ gothrough.each do |headers|
76
+ headers.each do |key, val|
77
+ return val[1] if header_p == key
78
+ end
79
+ end
80
+
81
+ return nil
82
+ end
83
+
84
+ # Returns true if the given header-name is sat.
85
+ def has_header?(header)
86
+ header_p = header.to_s.downcase.strip
87
+ return @headers.key?(header_p) || @headers_trailing.key?(header_p)
88
+ end
89
+
80
90
  def cookie(cookie)
81
91
  @cookies << cookie
82
92
  @session_cookie[cookie["name"]] = cookie["value"]
83
93
  end
84
94
 
85
95
  def header_str
96
+ if @http_version == "1.1" && @chunked
97
+ self.header("Connection", "Keep-Alive")
98
+ self.header("Transfer-Encoding", "chunked")
99
+ elsif @http_version == "1.1" && get_header_value("content-length").to_i > 0
100
+ self.header("Connection", "Keep-Alive")
101
+ end
102
+
103
+ self.header("Keep-Alive", "timeout=15, max=30") if self.get_header_value("connection") == "Keep-Alive"
104
+
86
105
  if @skip_statuscode
87
106
  res = ""
88
107
  else
@@ -102,10 +121,6 @@ class Hayabusa::Http_session::Response
102
121
  end
103
122
 
104
123
  if @http_version == "1.1"
105
- @headers_11.each do |key, val|
106
- res << "#{key}: #{val}#{NL}"
107
- end
108
-
109
124
  @trailers.each do |trailer|
110
125
  res << "Trailer: #{trailer}#{NL}"
111
126
  end
@@ -121,8 +136,17 @@ class Hayabusa::Http_session::Response
121
136
  end
122
137
 
123
138
  def write
124
- @headers_sent = true
139
+ # Write headers to socket.
125
140
  @socket.write(self.header_str)
141
+ @headers_sent = true
142
+ @cgroup.chunked = @chunked
143
+
144
+ # Set the content-length on the content-group to enable write-lenght-validation.
145
+ if self.has_header?("content-length")
146
+ @cgroup.content_length = self.get_header_value("content-length").to_i
147
+ else
148
+ @cgroup.content_length = nil
149
+ end
126
150
 
127
151
  if @status == 304
128
152
  #do nothing.
@@ -138,12 +162,19 @@ class Hayabusa::Http_session::Response
138
162
  @socket.write(NL)
139
163
  else
140
164
  @cgroup.write_to_socket
141
- @socket.write("#{NL}#{NL}") if @mode != :cgi
142
165
  end
143
166
  end
144
167
 
168
+ # Validate that no more has been written than given in content-length, since that will corrupt the client.
169
+ if self.has_header?("content-length")
170
+ length = cgroup.length_written
171
+ content_length = self.get_header_value("content-length").to_i
172
+ raise "More written than given in content-length: #{length}, #{content_length}" if length != content_length
173
+ end
174
+
175
+ # Close socket if that should be done.
145
176
  if @close and @mode != :cgi
146
- @hb.log_puts("Closing socket.")
177
+ @hb.log_puts("Hauabusa: Closing socket.")
147
178
  @socket.close
148
179
  end
149
180
  end
@@ -1,7 +1,14 @@
1
1
  <%
2
2
  if _get["choice"] == "dogarbagecollect"
3
+ _hb.clean
3
4
  GC.start
4
- _hb.redirect("?show=debug_memory_usage")
5
+
6
+ #Clean all Knj::Objects used in the application.
7
+ ObjectSpace.each_object(Knj::Objects) do |objects|
8
+ objects.clean_all
9
+ end
10
+
11
+ Knj::Web.redirect("?show=debug_memory_usage")
5
12
  end
6
13
  %>
7
14
 
@@ -11,6 +18,22 @@
11
18
  <input type="button" value="Garbage collect" onclick="location.href='?show=debug_memory_usage&amp;choice=dogarbagecollect';" />
12
19
  </div>
13
20
 
21
+ <h1>Hayabusa sessions</h1>
22
+ <table style="width: 600px;">
23
+ <tbody>
24
+ <tr>
25
+ <td>Active sessions</td>
26
+ <td><%=_hb.num(_hb.sessions.length, 0)%></td>
27
+ </tr>
28
+ <tr>
29
+ <td>Total sessions</td>
30
+ <td><%=_hb.num(_hb.ob.list(:Session, "count" => true), 0)%>
31
+ </tr>
32
+ </tbody>
33
+ </table>
34
+
35
+ <br />
36
+
14
37
  <%
15
38
  Knj::Memory_analyzer.new.write
16
39
  %>
Binary file
@@ -63,21 +63,56 @@ describe "Hayabusa" do
63
63
 
64
64
  raise "Expected thread-pool-priority to be '-3' but it wasnt: '#{$appserver.threadpool.args[:priority]}'." if $appserver.threadpool.args[:priority] != -3
65
65
 
66
- http = Http2.new(:host => "localhost", :port => 80, :encoding_gzip => false, :debug => false)
66
+ http = Http2.new(:host => "localhost", :port => 80, :encoding_gzip => false, :debug => false) rescue nil
67
67
 
68
68
  $testmodes = [{
69
69
  :name => :standalone,
70
70
  :path_pre => "",
71
- :http => Http2.new(:host => "localhost", :port => 1515)
72
- },{
73
- :name => :cgi,
74
- :path_pre => "hayabusa_cgi_test/",
75
- :http => http
76
- },{
77
- :name => :fcgi,
78
- :path_pre => "hayabusa_fcgi_test/",
79
- :http => http
71
+ :http => Http2.new(:host => "localhost", :port => 1515, :debug => false)
80
72
  }]
73
+
74
+ if http
75
+ $testmodes += [{
76
+ :name => :cgi,
77
+ :path_pre => "hayabusa_cgi_test/",
78
+ :http => http
79
+ },{
80
+ :name => :fcgi,
81
+ :path_pre => "hayabusa_fcgi_test/",
82
+ :http => http
83
+ }]
84
+ end
85
+ end
86
+
87
+ it "should be able to get multiple pictures" do
88
+ require "base64"
89
+ require "RMagick"
90
+
91
+ # Symlink 'image.rhtml' first.
92
+ img_from_path = "#{Knj.knjrbfw_path}/webscripts/image.rhtml"
93
+ img_to_path = "#{File.realpath("#{File.dirname(__FILE__)}/../pages")}/image.rhtml"
94
+
95
+ raise "Invalid from path: '#{img_from_path}'." unless File.exists?(img_from_path)
96
+
97
+ File.unlink(img_to_path) if File.symlink?(img_to_path)
98
+ File.symlink(img_from_path, img_to_path)
99
+
100
+ begin
101
+ $testmodes.each do |tdata|
102
+ 5.times do
103
+ path = "#{File.dirname(__FILE__)}/../pages/testpic.jpeg"
104
+
105
+ res = tdata[:http].get("#{tdata[:path_pre]}testpic.jpeg")
106
+ res.body.bytesize.should eql(File.size(path))
107
+
108
+ res.body.bytes.to_a.should eql(File.read(path).bytes.to_a)
109
+
110
+ res = tdata[:http].get("#{tdata[:path_pre]}image.rhtml?force=true&path64=#{Base64.encode64("testpic.jpeg").to_s.strip}")
111
+ end
112
+ end
113
+ ensure
114
+ File.unlink(img_to_path) if File.exists?(img_to_path)
115
+ end
81
116
  end
82
117
 
83
118
  #it "should be able to handle custom urls" do
@@ -128,8 +163,6 @@ describe "Hayabusa" do
128
163
  end
129
164
  end
130
165
 
131
- if false
132
-
133
166
  it "should be able to handle a GET-request." do
134
167
  $testmodes.each do |tdata|
135
168
  res = tdata[:http].get("#{tdata[:path_pre]}spec.rhtml")
@@ -356,8 +389,6 @@ describe "Hayabusa" do
356
389
  end
357
390
  end
358
391
 
359
- end
360
-
361
392
  it "should be able to stop." do
362
393
  $appserver.stop
363
394
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hayabusa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.20
4
+ version: 0.0.22
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,12 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-12 00:00:00.000000000 +02:00
13
- default_executable:
12
+ date: 2013-06-28 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: knjrbfw
17
- requirement: &23615180 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
18
17
  none: false
19
18
  requirements:
20
19
  - - ! '>='
@@ -22,10 +21,15 @@ dependencies:
22
21
  version: '0'
23
22
  type: :runtime
24
23
  prerelease: false
25
- version_requirements: *23615180
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
26
30
  - !ruby/object:Gem::Dependency
27
31
  name: erubis
28
- requirement: &23614160 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
29
33
  none: false
30
34
  requirements:
31
35
  - - ! '>='
@@ -33,10 +37,15 @@ dependencies:
33
37
  version: '0'
34
38
  type: :runtime
35
39
  prerelease: false
36
- version_requirements: *23614160
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
37
46
  - !ruby/object:Gem::Dependency
38
47
  name: mail
39
- requirement: &23613380 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
40
49
  none: false
41
50
  requirements:
42
51
  - - ! '>='
@@ -44,10 +53,15 @@ dependencies:
44
53
  version: '0'
45
54
  type: :runtime
46
55
  prerelease: false
47
- version_requirements: *23613380
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
48
62
  - !ruby/object:Gem::Dependency
49
63
  name: datet
50
- requirement: &23612560 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
51
65
  none: false
52
66
  requirements:
53
67
  - - ! '>='
@@ -55,10 +69,15 @@ dependencies:
55
69
  version: '0'
56
70
  type: :runtime
57
71
  prerelease: false
58
- version_requirements: *23612560
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
59
78
  - !ruby/object:Gem::Dependency
60
79
  name: http2
61
- requirement: &23611880 !ruby/object:Gem::Requirement
80
+ requirement: !ruby/object:Gem::Requirement
62
81
  none: false
63
82
  requirements:
64
83
  - - ! '>='
@@ -66,10 +85,15 @@ dependencies:
66
85
  version: '0'
67
86
  type: :runtime
68
87
  prerelease: false
69
- version_requirements: *23611880
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
70
94
  - !ruby/object:Gem::Dependency
71
95
  name: tpool
72
- requirement: &23611160 !ruby/object:Gem::Requirement
96
+ requirement: !ruby/object:Gem::Requirement
73
97
  none: false
74
98
  requirements:
75
99
  - - ! '>='
@@ -77,10 +101,31 @@ dependencies:
77
101
  version: '0'
78
102
  type: :runtime
79
103
  prerelease: false
80
- version_requirements: *23611160
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
81
110
  - !ruby/object:Gem::Dependency
82
111
  name: fcgi
83
- requirement: &23610420 !ruby/object:Gem::Requirement
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: ruby_process
128
+ requirement: !ruby/object:Gem::Requirement
84
129
  none: false
85
130
  requirements:
86
131
  - - ! '>='
@@ -88,10 +133,15 @@ dependencies:
88
133
  version: '0'
89
134
  type: :runtime
90
135
  prerelease: false
91
- version_requirements: *23610420
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
92
142
  - !ruby/object:Gem::Dependency
93
143
  name: json
94
- requirement: &23609720 !ruby/object:Gem::Requirement
144
+ requirement: !ruby/object:Gem::Requirement
95
145
  none: false
96
146
  requirements:
97
147
  - - ! '>='
@@ -99,10 +149,15 @@ dependencies:
99
149
  version: '0'
100
150
  type: :development
101
151
  prerelease: false
102
- version_requirements: *23609720
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
103
158
  - !ruby/object:Gem::Dependency
104
159
  name: rspec
105
- requirement: &23609120 !ruby/object:Gem::Requirement
160
+ requirement: !ruby/object:Gem::Requirement
106
161
  none: false
107
162
  requirements:
108
163
  - - ! '>='
@@ -110,10 +165,15 @@ dependencies:
110
165
  version: 2.3.0
111
166
  type: :development
112
167
  prerelease: false
113
- version_requirements: *23609120
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: 2.3.0
114
174
  - !ruby/object:Gem::Dependency
115
175
  name: bundler
116
- requirement: &23606820 !ruby/object:Gem::Requirement
176
+ requirement: !ruby/object:Gem::Requirement
117
177
  none: false
118
178
  requirements:
119
179
  - - ! '>='
@@ -121,10 +181,15 @@ dependencies:
121
181
  version: 1.0.0
122
182
  type: :development
123
183
  prerelease: false
124
- version_requirements: *23606820
184
+ version_requirements: !ruby/object:Gem::Requirement
185
+ none: false
186
+ requirements:
187
+ - - ! '>='
188
+ - !ruby/object:Gem::Version
189
+ version: 1.0.0
125
190
  - !ruby/object:Gem::Dependency
126
191
  name: jeweler
127
- requirement: &23606100 !ruby/object:Gem::Requirement
192
+ requirement: !ruby/object:Gem::Requirement
128
193
  none: false
129
194
  requirements:
130
195
  - - ~>
@@ -132,10 +197,31 @@ dependencies:
132
197
  version: 1.6.3
133
198
  type: :development
134
199
  prerelease: false
135
- version_requirements: *23606100
200
+ version_requirements: !ruby/object:Gem::Requirement
201
+ none: false
202
+ requirements:
203
+ - - ~>
204
+ - !ruby/object:Gem::Version
205
+ version: 1.6.3
206
+ - !ruby/object:Gem::Dependency
207
+ name: rmagick
208
+ requirement: !ruby/object:Gem::Requirement
209
+ none: false
210
+ requirements:
211
+ - - ! '>='
212
+ - !ruby/object:Gem::Version
213
+ version: '0'
214
+ type: :development
215
+ prerelease: false
216
+ version_requirements: !ruby/object:Gem::Requirement
217
+ none: false
218
+ requirements:
219
+ - - ! '>='
220
+ - !ruby/object:Gem::Version
221
+ version: '0'
136
222
  - !ruby/object:Gem::Dependency
137
223
  name: sqlite3
138
- requirement: &23605540 !ruby/object:Gem::Requirement
224
+ requirement: !ruby/object:Gem::Requirement
139
225
  none: false
140
226
  requirements:
141
227
  - - ! '>='
@@ -143,7 +229,12 @@ dependencies:
143
229
  version: '0'
144
230
  type: :development
145
231
  prerelease: false
146
- version_requirements: *23605540
232
+ version_requirements: !ruby/object:Gem::Requirement
233
+ none: false
234
+ requirements:
235
+ - - ! '>='
236
+ - !ruby/object:Gem::Version
237
+ version: '0'
147
238
  description: A threadded web/app-server that focuses on threadding, shared ressources,
148
239
  speed and more.
149
240
  email: k@spernj.org
@@ -239,13 +330,13 @@ files:
239
330
  - pages/spec_vars_header.rhtml
240
331
  - pages/spec_vars_post.rhtml
241
332
  - pages/spec_vars_post_fileupload.rhtml
333
+ - pages/testpic.jpeg
242
334
  - pages/tests.rhtml
243
335
  - pages/threadded_content_test.rhtml
244
336
  - spec/fcgi_multiple_processes_spec.rb
245
337
  - spec/hayabusa_spec.rb
246
338
  - spec/spec_helper.rb
247
339
  - spec/test_upload.xlsx
248
- has_rdoc: true
249
340
  homepage: http://github.com/kaspernj/hayabusa
250
341
  licenses:
251
342
  - MIT
@@ -261,7 +352,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
261
352
  version: '0'
262
353
  segments:
263
354
  - 0
264
- hash: -2750597640536201998
355
+ hash: 4203364333015306411
265
356
  required_rubygems_version: !ruby/object:Gem::Requirement
266
357
  none: false
267
358
  requirements:
@@ -270,7 +361,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
270
361
  version: '0'
271
362
  requirements: []
272
363
  rubyforge_project:
273
- rubygems_version: 1.6.2
364
+ rubygems_version: 1.8.23
274
365
  signing_key:
275
366
  specification_version: 3
276
367
  summary: A threadded web/app-server that supports stand-alone, CGI and FCGI-modes.