hayabusa 0.0.17 → 0.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.17
1
+ 0.0.18
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{hayabusa}
8
- s.version = "0.0.17"
8
+ s.version = "0.0.18"
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-05}
12
+ s.date = %q{2012-10-10}
13
13
  s.description = %q{A threadded web/app-server that focuses on threadding, shared ressources, speed and more.}
14
14
  s.email = %q{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"]
@@ -100,7 +100,8 @@ Gem::Specification.new do |s|
100
100
  "pages/threadded_content_test.rhtml",
101
101
  "spec/fcgi_multiple_processes_spec.rb",
102
102
  "spec/hayabusa_spec.rb",
103
- "spec/spec_helper.rb"
103
+ "spec/spec_helper.rb",
104
+ "spec/test_upload.xlsx"
104
105
  ]
105
106
  s.homepage = %q{http://github.com/kaspernj/hayabusa}
106
107
  s.licenses = ["MIT"]
@@ -1,15 +1,23 @@
1
+ require "tempfile"
2
+
1
3
  class Hayabusa::Cgi_tools
2
4
  attr_accessor :cgi
3
5
 
4
6
  #Converts CGI-like-post hashes to the normal Hayabusa-type hash.
5
- def convert_fcgi_post(params)
7
+ def convert_fcgi_post(params, args = nil)
6
8
  post_hash = {}
7
9
 
8
10
  params.each do |key, realval|
9
11
  val = realval.first
12
+ classn = val.class.name
10
13
 
11
14
  #Sometimes uploaded files are given as StringIO's.
12
- val = val.string if val.is_a?(StringIO)
15
+ if classn == "StringIO" or classn == "Tempfile"
16
+ val = Hayabusa::Http_session::Post_multipart::File_upload.new(
17
+ :fname => val.original_filename,
18
+ :data => val
19
+ )
20
+ end
13
21
 
14
22
  post_hash[key] = val
15
23
  end
@@ -22,6 +30,22 @@ class Hayabusa::Cgi_tools
22
30
  return post_ret
23
31
  end
24
32
 
33
+ #Converts the post-hash to valid hash for Http2 regarding file uploads (when proxied to host-process via Http2-framework).
34
+ def convert_fcgi_post_fileuploads_to_http2(hash)
35
+ hash.each do |key, val|
36
+ if val.is_a?(Hayabusa::Http_session::Post_multipart::File_upload)
37
+ hash[key] = {
38
+ :filename => val.filename,
39
+ :content => val.to_s
40
+ }
41
+ elsif val.is_a?(Hash) or val.is_a?(Array)
42
+ hash[key] = self.convert_fcgi_post_fileuploads_to_http2(val)
43
+ end
44
+ end
45
+
46
+ return hash
47
+ end
48
+
25
49
  def env_table
26
50
  return ENV
27
51
  end
@@ -91,7 +115,7 @@ class Hayabusa::Cgi_tools
91
115
  count = 0
92
116
  http.post_multipart(
93
117
  :url => url,
94
- :post => self.convert_fcgi_post(cgi.params),
118
+ :post => self.convert_fcgi_post_fileuploads_to_http2(self.convert_fcgi_post(cgi.params, :http2_compatible => true)),
95
119
  :default_headers => headers,
96
120
  :cookies => false,
97
121
  :on_content => proc{|line|
@@ -103,7 +127,7 @@ class Hayabusa::Cgi_tools
103
127
  count = 0
104
128
  http.post(
105
129
  :url => url,
106
- :post => self.convert_fcgi_post(cgi.params),
130
+ :post => self.convert_fcgi_post(cgi.params, :http2_compatible => true),
107
131
  :default_headers => headers,
108
132
  :cookies => false,
109
133
  :on_content => proc{|line|
@@ -308,8 +308,6 @@ class Hayabusa
308
308
  html = $stdout
309
309
  end
310
310
 
311
- html = ""
312
-
313
311
  html << "<table class=\"list hayabusa_log_table\">"
314
312
  html << "<thead>"
315
313
  html << "<tr>"
@@ -46,7 +46,7 @@ class Hayabusa
46
46
  @mails_mutex.synchronize do
47
47
  self.log_puts("Flushing mails.") if @debug
48
48
 
49
- if @mails_waiting.length <= 0
49
+ if @mails_waiting.empty?
50
50
  self.log_puts("No mails to flush - skipping.") if @debug
51
51
  return false
52
52
  end
@@ -57,7 +57,7 @@ class Hayabusa::Fcgi
57
57
  Knj.gem_require(:Http2)
58
58
 
59
59
  begin
60
- @fcgi_proxy[:http] = Http2.new(:host => "localhost", :port => @fcgi_proxy[:port].to_i)
60
+ @fcgi_proxy[:http] = Http2.new(:host => "localhost", :port => @fcgi_proxy[:port].to_i, :raise_errors => false)
61
61
  rescue Errno::ECONNREFUSED
62
62
  #The host-process has properly closed - evaluate mode again.
63
63
  raise Errno::EAGAIN
@@ -84,11 +84,23 @@ class Hayabusa::Fcgi
84
84
  cmd << " --title=#{Knj::Strings.unixsafe(hayabusa_conf[:title])}" if hayabusa_conf[:title]
85
85
 
86
86
  $stderr.puts("Executing command to start FCGI-server: #{cmd}")
87
- io_out, io_in, io_err = Open3.popen3(cmd)
87
+
88
+ if RUBY_ENGINE == "jruby"
89
+ pid, io_out, io_in, io_err = IO.popen4(cmd)
90
+ else
91
+ io_out, io_in, io_err, wait_thr = Open3.popen3(cmd)
92
+ pid = wait_thr.pid
93
+ end
88
94
 
89
95
  #Get data that should contain PID and port.
90
96
  read = io_in.gets
91
- raise "Host-process didnt return required data." if !read
97
+
98
+ if !read and !Knj::Unix_proc.pid_running?(pid)
99
+ err_str = io_err.read
100
+ raise "An error occurred while trying to start host-process: #{err_str}" if !err_str.to_s.strip.empty?
101
+ raise "Host-process died unexpectedly with no read, PID '#{pid}' and using cmd '#{cmd}'."
102
+ raise "Host-process didnt return required data."
103
+ end
92
104
 
93
105
  #Parse data from the host-process (port and PID).
94
106
  begin
@@ -167,13 +167,35 @@ class Hayabusa::Http_session::Post_multipart::File_upload
167
167
 
168
168
  #Returns the content of the file-upload as a string.
169
169
  def to_s
170
- return File.read(@args[:data].path)
170
+ if @args[:data].is_a?(StringIO)
171
+ return @args[:data].string
172
+ else
173
+ return File.read(@args[:data].path)
174
+ end
175
+ end
176
+
177
+ #Returns an IO to read from the upload wherever it is a temporary file or a string.
178
+ def io(&blk)
179
+ if @args[:data].is_a?(StringIO)
180
+ return @args[:data]
181
+ else
182
+ return File.open(@args[:data].path, "r", &blk)
183
+ end
171
184
  end
172
185
 
173
186
  #Saves the content of the fileupload to a given path.
174
187
  def save_to(filepath)
175
188
  File.open(filepath, "w") do |fp|
176
- fp.write(self.to_s)
189
+ if @args[:data].is_a?(StringIO)
190
+ fp.write(@args[:data].string)
191
+ else
192
+ #Stream output to avoid using too much memory.
193
+ self.io do |fp_read|
194
+ fp_read.lines do |line|
195
+ fp.write(line)
196
+ end
197
+ end
198
+ end
177
199
  end
178
200
  end
179
201
 
@@ -1,9 +1,19 @@
1
1
  <%
2
2
  pdata = {}
3
3
  _post.each do |key, val|
4
- pdata[key] = val.to_s
4
+ data = {
5
+ "class" => val.class.name
6
+ }
7
+
8
+ if val.is_a?(Hayabusa::Http_session::Post_multipart::File_upload)
9
+ data["val"] = val.to_s
10
+ else
11
+ data["val"] = val
12
+ end
13
+
14
+ pdata[key] = data
5
15
  end
6
16
 
7
17
  require "json"
8
- print JSON.generate(pdata)
18
+ print Marshal.dump(pdata)
9
19
  %>
@@ -89,28 +89,41 @@ describe "Hayabusa" do
89
89
 
90
90
  it "should be able to upload files" do
91
91
  $testmodes.each do |tdata|
92
- fpath = "#{File.realpath(File.dirname(__FILE__))}/../pages/spec_thread_joins.rhtml"
92
+ fpaths = {
93
+ "fpath1" => "#{File.realpath(File.dirname(__FILE__))}/../pages/spec_thread_joins.rhtml",
94
+ "fpath2" => "#{File.realpath(File.dirname(__FILE__))}/test_upload.xlsx"
95
+ }
93
96
 
94
97
  res = tdata[:http].post_multipart(:url => "#{tdata[:path_pre]}spec_vars_post_fileupload.rhtml", :post => {
95
- "testfile" => {
98
+ "testfile1" => {
96
99
  :filename => "spec_thread_joins.rhtml",
97
- :fpath => fpath
100
+ :fpath => fpaths["fpath1"]
101
+ },
102
+ "testfile2" => {
103
+ :filename => "test_upload.xlsx",
104
+ :fpath => fpaths["fpath2"]
98
105
  }
99
106
  })
100
107
 
101
- data = JSON.parse(res.body)
102
-
103
- if data["testfile"] != File.read(fpath)
104
- File.open("/tmp/hayabusa_spec_testfile1", "w") do |fp|
105
- fp.puts("Class: #{data["testfile"].class.name}")
106
- fp.write(data["testfile"])
107
- end
108
+ 1.upto(2) do |count|
109
+ data = Marshal.load(res.body)
108
110
 
109
- File.open("/tmp/hayabusa_spec_testfile2", "w") do |fp|
110
- fp.write(File.read(fpath))
111
+ if count != 2
112
+ if data["testfile#{count}"]["val"] != File.read(fpaths["fpath#{count}"])
113
+ File.open("/tmp/hayabusa_spec_testfile#{count}_1", "w") do |fp|
114
+ fp.puts("Class: #{data["testfile#{count}"].class.name}")
115
+ fp.write(data["testfile#{count}"])
116
+ end
117
+
118
+ File.open("/tmp/hayabusa_spec_testfile#{count}_2", "w") do |fp|
119
+ fp.write(File.read(fpaths["fpath#{count}"]))
120
+ end
121
+
122
+ raise "Expected uploaded data for mode '#{tdata[:name]}' to be the same but it wasnt:\n\"#{data["testfile#{count}"]}\"\n\n\"#{File.read(fpaths["fpath#{count}"])}\""
123
+ end
111
124
  end
112
125
 
113
- raise "Expected uploaded data for mode '#{tdata[:name]}' to be the same but it wasnt:\n\"#{data["testfile"]}\"\n\n\"#{File.read(fpath)}\""
126
+ raise "Expected 'testfile' class to be 'Hayabusa::Http_session::Post_multipart::File_upload' in mode '#{tdata[:name]}' but it wasnt: '#{data["testfile#{count}"]["class"]}'." if data["testfile#{count}"]["class"] != "Hayabusa::Http_session::Post_multipart::File_upload"
114
127
  end
115
128
  end
116
129
  end
Binary file
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.17
4
+ version: 0.0.18
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,12 +9,12 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-05 00:00:00.000000000 +02:00
12
+ date: 2012-10-10 00:00:00.000000000 +02:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: knjrbfw
17
- requirement: &20656500 !ruby/object:Gem::Requirement
17
+ requirement: &11988240 !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: *20656500
25
+ version_requirements: *11988240
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: erubis
28
- requirement: &20655480 !ruby/object:Gem::Requirement
28
+ requirement: &11987480 !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: *20655480
36
+ version_requirements: *11987480
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: mail
39
- requirement: &20653320 !ruby/object:Gem::Requirement
39
+ requirement: &11986740 !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: :runtime
46
46
  prerelease: false
47
- version_requirements: *20653320
47
+ version_requirements: *11986740
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: datet
50
- requirement: &20634900 !ruby/object:Gem::Requirement
50
+ requirement: &11985940 !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: :runtime
57
57
  prerelease: false
58
- version_requirements: *20634900
58
+ version_requirements: *11985940
59
59
  - !ruby/object:Gem::Dependency
60
60
  name: http2
61
- requirement: &20634080 !ruby/object:Gem::Requirement
61
+ requirement: &11985200 !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: :runtime
68
68
  prerelease: false
69
- version_requirements: *20634080
69
+ version_requirements: *11985200
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: tpool
72
- requirement: &20633360 !ruby/object:Gem::Requirement
72
+ requirement: &11984320 !ruby/object:Gem::Requirement
73
73
  none: false
74
74
  requirements:
75
75
  - - ! '>='
@@ -77,10 +77,10 @@ dependencies:
77
77
  version: '0'
78
78
  type: :runtime
79
79
  prerelease: false
80
- version_requirements: *20633360
80
+ version_requirements: *11984320
81
81
  - !ruby/object:Gem::Dependency
82
82
  name: fcgi
83
- requirement: &20632600 !ruby/object:Gem::Requirement
83
+ requirement: &11983260 !ruby/object:Gem::Requirement
84
84
  none: false
85
85
  requirements:
86
86
  - - ! '>='
@@ -88,10 +88,10 @@ dependencies:
88
88
  version: '0'
89
89
  type: :runtime
90
90
  prerelease: false
91
- version_requirements: *20632600
91
+ version_requirements: *11983260
92
92
  - !ruby/object:Gem::Dependency
93
93
  name: json
94
- requirement: &20631660 !ruby/object:Gem::Requirement
94
+ requirement: &11981880 !ruby/object:Gem::Requirement
95
95
  none: false
96
96
  requirements:
97
97
  - - ! '>='
@@ -99,10 +99,10 @@ dependencies:
99
99
  version: '0'
100
100
  type: :development
101
101
  prerelease: false
102
- version_requirements: *20631660
102
+ version_requirements: *11981880
103
103
  - !ruby/object:Gem::Dependency
104
104
  name: rspec
105
- requirement: &20630700 !ruby/object:Gem::Requirement
105
+ requirement: &11980560 !ruby/object:Gem::Requirement
106
106
  none: false
107
107
  requirements:
108
108
  - - ! '>='
@@ -110,10 +110,10 @@ dependencies:
110
110
  version: 2.3.0
111
111
  type: :development
112
112
  prerelease: false
113
- version_requirements: *20630700
113
+ version_requirements: *11980560
114
114
  - !ruby/object:Gem::Dependency
115
115
  name: bundler
116
- requirement: &20629600 !ruby/object:Gem::Requirement
116
+ requirement: &11978460 !ruby/object:Gem::Requirement
117
117
  none: false
118
118
  requirements:
119
119
  - - ! '>='
@@ -121,10 +121,10 @@ dependencies:
121
121
  version: 1.0.0
122
122
  type: :development
123
123
  prerelease: false
124
- version_requirements: *20629600
124
+ version_requirements: *11978460
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: jeweler
127
- requirement: &20628260 !ruby/object:Gem::Requirement
127
+ requirement: &11977700 !ruby/object:Gem::Requirement
128
128
  none: false
129
129
  requirements:
130
130
  - - ~>
@@ -132,10 +132,10 @@ dependencies:
132
132
  version: 1.6.3
133
133
  type: :development
134
134
  prerelease: false
135
- version_requirements: *20628260
135
+ version_requirements: *11977700
136
136
  - !ruby/object:Gem::Dependency
137
137
  name: sqlite3
138
- requirement: &20627220 !ruby/object:Gem::Requirement
138
+ requirement: &11977060 !ruby/object:Gem::Requirement
139
139
  none: false
140
140
  requirements:
141
141
  - - ! '>='
@@ -143,7 +143,7 @@ dependencies:
143
143
  version: '0'
144
144
  type: :development
145
145
  prerelease: false
146
- version_requirements: *20627220
146
+ version_requirements: *11977060
147
147
  description: A threadded web/app-server that focuses on threadding, shared ressources,
148
148
  speed and more.
149
149
  email: k@spernj.org
@@ -244,6 +244,7 @@ files:
244
244
  - spec/fcgi_multiple_processes_spec.rb
245
245
  - spec/hayabusa_spec.rb
246
246
  - spec/spec_helper.rb
247
+ - spec/test_upload.xlsx
247
248
  has_rdoc: true
248
249
  homepage: http://github.com/kaspernj/hayabusa
249
250
  licenses:
@@ -260,7 +261,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
260
261
  version: '0'
261
262
  segments:
262
263
  - 0
263
- hash: -1944218330295904971
264
+ hash: -1407369577175640998
264
265
  required_rubygems_version: !ruby/object:Gem::Requirement
265
266
  none: false
266
267
  requirements: