hayabusa 0.0.11 → 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. data/Gemfile.lock +2 -2
  2. data/VERSION +1 -1
  3. data/hayabusa.gemspec +12 -20
  4. data/lib/hayabusa.rb +23 -3
  5. data/lib/hayabusa_cgi_session.rb +5 -91
  6. data/lib/hayabusa_cgi_tools.rb +6 -3
  7. data/lib/hayabusa_client_session.rb +151 -0
  8. data/lib/hayabusa_ext/threadding.rb +19 -2
  9. data/lib/hayabusa_fcgi.rb +2 -1
  10. data/lib/hayabusa_http_server.rb +22 -16
  11. data/lib/hayabusa_http_session.rb +4 -122
  12. data/lib/hayabusa_http_session_request.rb +1 -1
  13. data/lib/hayabusa_http_session_response.rb +2 -1
  14. data/pages/config_cgi.rb +19 -0
  15. data/pages/config_fcgi.rb +19 -0
  16. data/{tests/fcgi_test/multiple_threads.rhtml → pages/spec_multiple_threads.rhtml} +0 -0
  17. data/{tests/fcgi_test/sleeper.rhtml → pages/spec_sleeper.rhtml} +0 -0
  18. data/{tests/cgi_test/vars_get_test.rhtml → pages/spec_vars_get.rhtml} +0 -0
  19. data/{tests/cgi_test/vars_header_test.rhtml → pages/spec_vars_header.rhtml} +0 -0
  20. data/{tests/cgi_test/vars_post_test.rhtml → pages/spec_vars_post.rhtml} +0 -0
  21. data/{tests/cgi_test → pages}/threadded_content_test.rhtml +0 -0
  22. data/spec/fcgi_multiple_processes_spec.rb +3 -3
  23. data/spec/hayabusa_spec.rb +156 -47
  24. metadata +12 -20
  25. data/pages/spec_post.rhtml +0 -3
  26. data/spec/cgi_spec.rb +0 -49
  27. data/spec/custom_urls_spec.rb +0 -35
  28. data/spec/fcgi_spec.rb +0 -71
  29. data/tests/cgi_test/config_cgi.rb +0 -6
  30. data/tests/fcgi_test/config_fcgi.rb +0 -6
  31. data/tests/fcgi_test/index.rhtml +0 -3
  32. data/tests/fcgi_test/threadded_content_test.rhtml +0 -23
  33. data/tests/fcgi_test/vars_get_test.rhtml +0 -4
  34. data/tests/fcgi_test/vars_header_test.rhtml +0 -3
  35. data/tests/fcgi_test/vars_post_test.rhtml +0 -4
@@ -12,7 +12,7 @@ GEM
12
12
  git (>= 1.2.5)
13
13
  rake
14
14
  json (1.7.5)
15
- knjrbfw (0.0.94)
15
+ knjrbfw (0.0.97)
16
16
  datet
17
17
  http2
18
18
  php4r
@@ -37,7 +37,7 @@ GEM
37
37
  diff-lcs (~> 1.1.2)
38
38
  rspec-mocks (2.3.0)
39
39
  sqlite3 (1.3.6)
40
- tpool (0.0.3)
40
+ tpool (0.0.4)
41
41
  treetop (1.4.10)
42
42
  polyglot
43
43
  polyglot (>= 0.3.1)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.11
1
+ 0.0.12
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "hayabusa"
8
- s.version = "0.0.11"
8
+ s.version = "0.0.12"
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 = "2012-09-12"
12
+ s.date = "2012-09-18"
13
13
  s.description = "A threadded web/app-server that focuses on threadding, shared ressources, speed and more."
14
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", "knjappserver_start.rb"]
@@ -39,6 +39,7 @@ Gem::Specification.new do |s|
39
39
  "lib/hayabusa.rb",
40
40
  "lib/hayabusa_cgi_session.rb",
41
41
  "lib/hayabusa_cgi_tools.rb",
42
+ "lib/hayabusa_client_session.rb",
42
43
  "lib/hayabusa_custom_io.rb",
43
44
  "lib/hayabusa_database.rb",
44
45
  "lib/hayabusa_erb_handler.rb",
@@ -74,6 +75,8 @@ Gem::Specification.new do |s|
74
75
  "pages/benchmark_print.rhtml",
75
76
  "pages/benchmark_simple.rhtml",
76
77
  "pages/benchmark_threadded_content.rhtml",
78
+ "pages/config_cgi.rb",
79
+ "pages/config_fcgi.rb",
77
80
  "pages/debug_database_connections.rhtml",
78
81
  "pages/debug_http_sessions.rhtml",
79
82
  "pages/debug_memory_usage.rhtml",
@@ -81,30 +84,19 @@ Gem::Specification.new do |s|
81
84
  "pages/logs_latest.rhtml",
82
85
  "pages/logs_show.rhtml",
83
86
  "pages/spec.rhtml",
84
- "pages/spec_post.rhtml",
87
+ "pages/spec_multiple_threads.rhtml",
88
+ "pages/spec_sleeper.rhtml",
85
89
  "pages/spec_test_multiple_clients.rhtml",
86
90
  "pages/spec_thread_joins.rhtml",
87
91
  "pages/spec_threadded_content.rhtml",
92
+ "pages/spec_vars_get.rhtml",
93
+ "pages/spec_vars_header.rhtml",
94
+ "pages/spec_vars_post.rhtml",
88
95
  "pages/tests.rhtml",
89
- "spec/cgi_spec.rb",
90
- "spec/custom_urls_spec.rb",
96
+ "pages/threadded_content_test.rhtml",
91
97
  "spec/fcgi_multiple_processes_spec.rb",
92
- "spec/fcgi_spec.rb",
93
98
  "spec/hayabusa_spec.rb",
94
- "spec/spec_helper.rb",
95
- "tests/cgi_test/config_cgi.rb",
96
- "tests/cgi_test/threadded_content_test.rhtml",
97
- "tests/cgi_test/vars_get_test.rhtml",
98
- "tests/cgi_test/vars_header_test.rhtml",
99
- "tests/cgi_test/vars_post_test.rhtml",
100
- "tests/fcgi_test/config_fcgi.rb",
101
- "tests/fcgi_test/index.rhtml",
102
- "tests/fcgi_test/multiple_threads.rhtml",
103
- "tests/fcgi_test/sleeper.rhtml",
104
- "tests/fcgi_test/threadded_content_test.rhtml",
105
- "tests/fcgi_test/vars_get_test.rhtml",
106
- "tests/fcgi_test/vars_header_test.rhtml",
107
- "tests/fcgi_test/vars_post_test.rhtml"
99
+ "spec/spec_helper.rb"
108
100
  ]
109
101
  s.homepage = "http://github.com/kaspernj/hayabusa"
110
102
  s.licenses = ["MIT"]
@@ -84,6 +84,10 @@ class Hayabusa
84
84
  ]
85
85
  end
86
86
 
87
+ if @config[:handlers_extra]
88
+ @config[:handlers] += @config[:handlers_extra]
89
+ end
90
+
87
91
 
88
92
  #Add extra handlers if given.
89
93
  @config[:handlers] += @config[:handlers_extra] if @config[:handlers_extra]
@@ -105,11 +109,15 @@ class Hayabusa
105
109
  @debug_log = false
106
110
  end
107
111
 
108
- if !@config.key?(:debug_print) or @config[:debug_print]
112
+ if @config[:debug_print]
109
113
  @debug_print = true
110
114
  else
111
115
  @debug_print = false
112
116
  end
117
+
118
+ if !@config.key?(:debug_print_err) or @config[:debug_print_err]
119
+ @debug_print_err = true
120
+ end
113
121
  end
114
122
 
115
123
  @paused = 0
@@ -346,8 +354,20 @@ class Hayabusa
346
354
 
347
355
  #Outputs to stderr and logs it.
348
356
  def log_puts(str)
349
- @log_fp.puts str if @debug_log
350
- STDOUT.puts str if @debug_print
357
+ if @debug_log
358
+ @log_fp.sync = true
359
+ @log_fp.puts str
360
+ end
361
+
362
+ if @debug_print
363
+ STDOUT.sync = true
364
+ STDOUT.puts str
365
+ end
366
+
367
+ if @debug_print_err
368
+ STDERR.sync = true
369
+ STDERR.puts str
370
+ end
351
371
  end
352
372
 
353
373
  def no_date(event, classname)
@@ -1,6 +1,6 @@
1
- class Hayabusa::Cgi_session
2
- attr_accessor :data, :alert_sent
3
- attr_reader :cookie, :get, :headers, :ip, :session, :session_id, :session_hash, :hb, :active, :out, :eruby, :browser, :debug, :resp, :page_path, :post, :cgroup, :meta, :httpsession_var, :working
1
+ class Hayabusa::Cgi_session < Hayabusa::Client_session
2
+ attr_accessor :alert_sent, :data, :page_path
3
+ attr_reader :cookie, :get, :headers, :ip, :session, :session_id, :session_hash, :hb, :active, :out, :eruby, :browser, :debug, :resp, :post, :cgroup, :meta, :httpsession_var, :working
4
4
 
5
5
  def initialize(args)
6
6
  @args = args
@@ -105,24 +105,8 @@ class Hayabusa::Cgi_session
105
105
 
106
106
 
107
107
  begin
108
- @hb.events.call(:request_begin, :httpsession => self) if @hb.events
109
-
110
- Timeout.timeout(@hb.config[:timeout]) do
111
- if @handlers_cache.key?(@ext)
112
- @hb.log_puts "Calling handler." if @debug
113
- @handlers_cache[@ext].call(self)
114
- else
115
- raise "CGI-mode shouldnt serve static files: '#{@page_path}'."
116
- end
117
- end
118
-
119
- @cgroup.mark_done
120
- @cgroup.write_output
121
- @cgroup.join
122
-
123
- @hb.events.call(:request_done, {
124
- :httpsession => self
125
- }) if @hb.events
108
+ self.execute_page
109
+ self.execute_done
126
110
  rescue SystemExit
127
111
  #do nothing - ignore.
128
112
  rescue Timeout::Error
@@ -134,74 +118,4 @@ class Hayabusa::Cgi_session
134
118
  def handler
135
119
  return self
136
120
  end
137
-
138
- #Parses the if-modified-since header and returns it as a Time-object. Returns false is no if-modified-since-header is given or raises an RuntimeError if it cant be parsed.
139
- def modified_since
140
- return @modified_since if @modified_since
141
- return false if !@meta["HTTP_IF_MODIFIED_SINCE"]
142
-
143
- mod_match = @meta["HTTP_IF_MODIFIED_SINCE"].match(/^([A-z]+),\s+(\d+)\s+([A-z]+)\s+(\d+)\s+(\d+):(\d+):(\d+)\s+(.+)$/)
144
- raise "Could not parse 'HTTP_IF_MODIFIED_SINCE'." if !mod_match
145
-
146
- month_no = Datet.month_str_to_no(mod_match[3])
147
- @modified_since = Time.utc(mod_match[4].to_i, month_no, mod_match[2].to_i, mod_match[5].to_i, mod_match[6].to_i, mod_match[7].to_i)
148
-
149
- return @modified_since
150
- end
151
-
152
- #Forces the content to be the input - nothing else can be added after calling this.
153
- def force_content(newcont)
154
- @cgroup.force_content(newcont)
155
- end
156
-
157
- #Creates a new Hayabusa::Binding-object and returns the binding for that object.
158
- def create_binding
159
- return Hayabusa::Http_session::Page_environment.new(:httpsession => self, :hb => @hb).get_binding
160
- end
161
-
162
- #Is called when content is added and begings to write the output if it goes above the limit.
163
- def add_size(size)
164
- @written_size += size
165
- @cgroup.write_output if @written_size >= @size_send
166
- end
167
-
168
- #Called from content-group.
169
- def write(str)
170
- @out.print(str)
171
- end
172
-
173
- def threadded_content(block)
174
- raise "No block was given." if !block
175
- cgroup = Thread.current[:hayabusa][:contentgroup].new_thread
176
-
177
- Thread.new do
178
- begin
179
- self.init_thread
180
- cgroup.register_thread
181
-
182
- @hb.db_handler.get_and_register_thread if @hb and @hb.db_handler.opts[:threadsafe]
183
- @hb.ob.db.get_and_register_thread if @hb and @hb.ob.db.opts[:threadsafe]
184
-
185
- block.call
186
- rescue Exception => e
187
- Thread.current[:hayabusa][:contentgroup].write Knj::Errors.error_str(e, {:html => true})
188
- _hb.handle_error(e)
189
- ensure
190
- Thread.current[:hayabusa][:contentgroup].mark_done
191
- @hb.ob.db.free_thread if @hb and @hb.ob.db.opts[:threadsafe]
192
- @hb.db_handler.free_thread if @hb and @hb.db_handler.opts[:threadsafe]
193
- end
194
- end
195
- end
196
-
197
- def init_thread
198
- Thread.current[:hayabusa] = {
199
- :hb => @hb,
200
- :httpsession => self,
201
- :get => @get,
202
- :post => @post,
203
- :meta => @meta,
204
- :cookie => @cookie
205
- }
206
- end
207
121
  end
@@ -71,8 +71,11 @@ class Hayabusa::Cgi_tools
71
71
 
72
72
  fp_log.puts("Proxying URL: '#{url}'.") if fp_log
73
73
 
74
- require "timeout"
75
- Timeout.timeout(ttime) do
74
+ #The HTTP-connection can have closed mean while, so we have to test it.
75
+ raise Errno::ECONNABORTED if !http.socket_working?
76
+
77
+ #require "timeout"
78
+ #Timeout.timeout(ttime) do
76
79
  if cgi.request_method == "POST" and cgi.content_type.to_s.downcase.index("multipart/form-data") != nil
77
80
  count = 0
78
81
  http.post_multipart(
@@ -109,6 +112,6 @@ class Hayabusa::Cgi_tools
109
112
  }
110
113
  )
111
114
  end
112
- end
115
+ #end
113
116
  end
114
117
  end
@@ -0,0 +1,151 @@
1
+ #Various client-sessions should extend this class.
2
+ class Hayabusa::Client_session
3
+ attr_accessor :alert_sent, :data, :page_path
4
+ attr_reader :cookie, :get, :headers, :ip, :session, :session_id, :session_hash, :hb, :active, :out, :eruby, :browser, :debug, :resp, :post, :cgroup, :meta, :httpsession_var, :working
5
+
6
+ #Parses the if-modified-since header and returns it as a Time-object. Returns false is no if-modified-since-header is given or raises an RuntimeError if it cant be parsed.
7
+ def modified_since
8
+ return @modified_since if @modified_since
9
+ return false if !@meta["HTTP_IF_MODIFIED_SINCE"]
10
+
11
+ mod_match = @meta["HTTP_IF_MODIFIED_SINCE"].match(/^([A-z]+),\s+(\d+)\s+([A-z]+)\s+(\d+)\s+(\d+):(\d+):(\d+)\s+(.+)$/)
12
+ raise "Could not parse 'HTTP_IF_MODIFIED_SINCE'." if !mod_match
13
+
14
+ month_no = Datet.month_str_to_no(mod_match[3])
15
+ @modified_since = Time.utc(mod_match[4].to_i, month_no, mod_match[2].to_i, mod_match[5].to_i, mod_match[6].to_i, mod_match[7].to_i)
16
+
17
+ return @modified_since
18
+ end
19
+
20
+ #Forces the content to be the input - nothing else can be added after calling this.
21
+ def force_content(newcont)
22
+ @cgroup.force_content(newcont)
23
+ end
24
+
25
+ #Creates a new Hayabusa::Binding-object and returns the binding for that object.
26
+ def create_binding
27
+ return Hayabusa::Http_session::Page_environment.new(:httpsession => self, :hb => @hb).get_binding
28
+ end
29
+
30
+ #Is called when content is added and begings to write the output if it goes above the limit.
31
+ def add_size(size)
32
+ @written_size += size
33
+ @cgroup.write_output if @written_size >= @size_send
34
+ end
35
+
36
+ #Called from content-group.
37
+ def write(str)
38
+ @out.print(str)
39
+ end
40
+
41
+ def threadded_content(block)
42
+ raise "No block was given." if !block
43
+ cgroup = Thread.current[:hayabusa][:contentgroup].new_thread
44
+
45
+ Thread.new do
46
+ begin
47
+ self.init_thread
48
+ cgroup.register_thread
49
+
50
+ @hb.db_handler.get_and_register_thread if @hb and @hb.db_handler.opts[:threadsafe]
51
+ @hb.ob.db.get_and_register_thread if @hb and @hb.ob.db.opts[:threadsafe]
52
+
53
+ block.call
54
+ rescue Exception => e
55
+ Thread.current[:hayabusa][:contentgroup].write Knj::Errors.error_str(e, {:html => true})
56
+ _hb.handle_error(e)
57
+ ensure
58
+ Thread.current[:hayabusa][:contentgroup].mark_done
59
+ @hb.ob.db.free_thread if @hb and @hb.ob.db.opts[:threadsafe]
60
+ @hb.db_handler.free_thread if @hb and @hb.db_handler.opts[:threadsafe]
61
+ end
62
+ end
63
+ end
64
+
65
+ def init_thread
66
+ Thread.current[:hayabusa] = {} if !Thread.current[:hayabusa]
67
+ Thread.current[:hayabusa][:hb] = @hb
68
+ Thread.current[:hayabusa][:httpsession] = self
69
+ Thread.current[:hayabusa][:session] = @session
70
+ Thread.current[:hayabusa][:get] = @get
71
+ Thread.current[:hayabusa][:post] = @post
72
+ Thread.current[:hayabusa][:meta] = @meta
73
+ Thread.current[:hayabusa][:cookie] = @cookie
74
+ end
75
+
76
+ def execute_page
77
+ begin
78
+ @hb.events.call(:request_begin, :httpsession => self) if @hb.events
79
+
80
+ Timeout.timeout(@hb.config[:timeout]) do
81
+ if @handlers_cache.key?(@ext)
82
+ @hb.log_puts("Calling handler.") if @debug
83
+ @handlers_cache[@ext].call(self)
84
+ else
85
+ #check if we should use a handler for this request.
86
+ @config[:handlers].each do |handler_info|
87
+ if handler_info.key?(:file_ext) and handler_info[:file_ext] == @ext
88
+ handler_info[:callback].call(self)
89
+ break
90
+ elsif handler_info.key?(:path) and handler_info[:mount] and @meta["SCRIPT_NAME"].slice(0, handler_info[:path].length) == handler_info[:path]
91
+ @page_path = "#{handler_info[:mount]}#{@meta["SCRIPT_NAME"].slice(handler_info[:path].length, @meta["SCRIPT_NAME"].length)}"
92
+ break
93
+ elsif handler_info.key?(:regex) and @meta["REQUEST_URI"].to_s.match(handler_info[:regex])
94
+ handler_info[:callback].call(:httpsession => self)
95
+ break
96
+ end
97
+ end
98
+
99
+ if @page_path
100
+ if !File.exists?(@page_path)
101
+ @resp.status = 404
102
+ @resp.header("Content-Type", "text/html")
103
+ @cgroup.write("File you are looking for was not found: '#{@meta["REQUEST_URI"]}'.")
104
+ else
105
+ if @headers["cache-control"] and @headers["cache-control"][0]
106
+ cache_control = {}
107
+ @headers["cache-control"][0].scan(/(.+)=(.+)/) do |match|
108
+ cache_control[match[1]] = match[2]
109
+ end
110
+ end
111
+
112
+ cache_dont = true if cache_control and cache_control.key?("max-age") and cache_control["max-age"].to_i <= 0
113
+ lastmod = File.mtime(@page_path)
114
+
115
+ @resp.header("Last-Modified", lastmod.httpdate)
116
+ @resp.header("Expires", (Time.now + 86400).httpdate) #next day.
117
+
118
+ if !cache_dont and @headers["if-modified-since"] and @headers["if-modified-since"][0]
119
+ request_mod = Datet.in(@headers["if-modified-since"].first).time
120
+
121
+ if request_mod == lastmod
122
+ @resp.status = 304
123
+ return nil
124
+ end
125
+ end
126
+
127
+ @cgroup.new_io(:type => :file, :path => @page_path)
128
+ end
129
+ end
130
+ end
131
+ end
132
+ rescue SystemExit
133
+ #do nothing - ignore.
134
+ rescue Timeout::Error
135
+ @resp.status = 500
136
+ print "The request timed out."
137
+ end
138
+ end
139
+
140
+ def execute_done
141
+ @cgroup.mark_done
142
+ @cgroup.write_output
143
+ @hb.log_puts "#{__id__} - Served '#{@meta["REQUEST_URI"]}' in #{Time.now.to_f - time_start} secs (#{@resp.status})." if @debug
144
+ @cgroup.join
145
+
146
+ @hb.events.call(:request_done, {
147
+ :httpsession => self
148
+ }) if @hb.events
149
+ @httpsession_var = {}
150
+ end
151
+ end
@@ -11,8 +11,8 @@ class Hayabusa
11
11
  end
12
12
 
13
13
  #Callback for when an error occurs in the threadpool.
14
- def threadpool_on_error(error)
15
- self.handle_error(error)
14
+ def threadpool_on_error(args)
15
+ self.handle_error(args[:error])
16
16
  end
17
17
 
18
18
  #Inits the thread so it has access to the appserver and various magic methods can be used.
@@ -65,6 +65,23 @@ class Hayabusa
65
65
  return thread_obj
66
66
  end
67
67
 
68
+ #If a custom thread is spawned, you can run whatever code within this block, and it will have its own database-connection and so on like normal Hayabusa-threads.
69
+ def thread_block(&block)
70
+ @ob.db.get_and_register_thread if @ob.db.opts[:threadsafe]
71
+ @db_handler.get_and_register_thread if @db_handler.opts[:threadsafe]
72
+
73
+ thread = Thread.current
74
+ thread[:hayabusa] = {} if !thread[:hayabusa]
75
+ thread[:hayabusa][:hb] = self
76
+
77
+ begin
78
+ block.call
79
+ ensure
80
+ @ob.db.free_thread if @ob.db.opts[:threadsafe]
81
+ @db_handler.free_thread if @db_handler.opts[:threadsafe]
82
+ end
83
+ end
84
+
68
85
  #Runs a proc every number of seconds.
69
86
  def timeout(args = {}, &block)
70
87
  return Hayabusa::Threadding_timeout.new({