http_spew 0.4.1 → 0.7.1
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.
- checksums.yaml +7 -0
- data/.document +0 -1
- data/.gitignore +1 -4
- data/.manifest +3 -3
- data/.olddoc.yml +6 -0
- data/COPYING +288 -623
- data/GIT-VERSION-FILE +1 -1
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +2 -3
- data/LATEST +4 -2
- data/LICENSE +8 -11
- data/NEWS +55 -0
- data/README +5 -6
- data/benchmark/bm_content_md5.rb +52 -0
- data/benchmark/bm_content_md5_input_spray.rb +59 -0
- data/http_spew.gemspec +14 -18
- data/lib/http_spew/chunky_pipe.rb +14 -3
- data/lib/http_spew/class_methods.rb +40 -12
- data/lib/http_spew/content_md5.rb +6 -6
- data/lib/http_spew/headers.rb +8 -17
- data/lib/http_spew/input_spray.rb +1 -0
- data/lib/http_spew/request.rb +46 -33
- data/lib/http_spew/version.rb +1 -1
- data/lib/http_spew.rb +14 -14
- data/pkg.mk +27 -52
- data/test/helper.rb +3 -1
- data/test/test_content_md5.rb +1 -1
- data/test/test_hit_n_run.rb +5 -5
- data/test/test_input_spray_with_md5.rb +3 -3
- data/test/test_mirror.rb +1 -1
- data/test/test_request.rb +5 -7
- data/test/test_unexpected_response.rb +2 -2
- data/test/test_upload.rb +6 -3
- metadata +31 -76
- data/.wrongdoc.yml +0 -4
- data/ChangeLog +0 -546
- data/Gemfile +0 -5
data/GIT-VERSION-FILE
CHANGED
@@ -1 +1 @@
|
|
1
|
-
GIT_VERSION = 0.
|
1
|
+
GIT_VERSION = 0.7.1
|
data/GIT-VERSION-GEN
CHANGED
data/GNUmakefile
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
all::
|
2
|
-
RSYNC_DEST :=
|
3
|
-
rfproject := rainbows
|
2
|
+
RSYNC_DEST := yhbt.net:/srv/yhbt/http_spew
|
4
3
|
rfpackage := http_spew
|
5
4
|
|
6
5
|
RUBY_VERSION_FILE = lib/http_spew/version.rb
|
@@ -10,7 +9,7 @@ include pkg.mk
|
|
10
9
|
$(RUBY_VERSION_FILE): GIT-VERSION-FILE
|
11
10
|
@$(RM) -f $@+
|
12
11
|
@echo >> $@+ '# -*- encoding: binary -*-'
|
13
|
-
@echo >> $@+ 'HTTP_Spew.const_set :VERSION, "$(GIT_VERSION)"'
|
12
|
+
@echo >> $@+ 'HTTP_Spew.const_set :VERSION, "$(GIT_VERSION)".freeze'
|
14
13
|
@mv $@+ $@
|
15
14
|
|
16
15
|
build: $(RUBY_VERSION_FILE)
|
data/LATEST
CHANGED
data/LICENSE
CHANGED
@@ -1,17 +1,14 @@
|
|
1
|
-
|
1
|
+
http_spew is copyrighted Free Software by all contributors, see logs in
|
2
2
|
revision control for names and email addresses of all of them.
|
3
3
|
|
4
4
|
You can redistribute it and/or modify it under the terms of the GNU
|
5
|
-
General Public License
|
6
|
-
|
7
|
-
(Eric Wong) reserves the right to relicense HTTP Spew under future versions
|
8
|
-
of the GPL.
|
5
|
+
General Public License as published by the Free Software Foundation;
|
6
|
+
either version 2 of the License, or (at your option) any later version.
|
9
7
|
|
10
|
-
|
8
|
+
http_spew is distributed in the hope that it will be useful, but WITHOUT
|
11
9
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
12
|
-
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
13
|
-
|
10
|
+
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
11
|
+
for more details.
|
14
12
|
|
15
|
-
You should have received a copy of the GNU General Public License
|
16
|
-
|
17
|
-
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
13
|
+
You should have received a copy of the GNU General Public License along
|
14
|
+
with this program; if not, see https://www.gnu.org/licenses/gpl-2.0.txt
|
data/NEWS
CHANGED
@@ -1,3 +1,58 @@
|
|
1
|
+
=== http_spew 0.7.1 / 2022-01-16 08:45 UTC
|
2
|
+
|
3
|
+
2 changes since v0.7.0:
|
4
|
+
doc: s/bogomips.org/yhbt.net/
|
5
|
+
fix mismatched indentation warnings
|
6
|
+
|
7
|
+
=== http_spew 0.7.0 - modernizing for newer Rubies / 2017-06-12 22:00 UTC
|
8
|
+
|
9
|
+
Ruby 2.3+ is now required as kgio dependencies are gone.
|
10
|
+
This is unlikely to be a problem in practice, as hardly
|
11
|
+
anybody uses this at the moment.
|
12
|
+
|
13
|
+
5 changes since 0.6.0:
|
14
|
+
|
15
|
+
remove most uses of kgio
|
16
|
+
make kgio entirely optional
|
17
|
+
update to only use public email address
|
18
|
+
http_spew: remove kgio require at top level
|
19
|
+
gemspec: remove olddoc as a build dependency
|
20
|
+
|
21
|
+
=== http_spew 0.6.0 - even less / 2016-11-05 02:15 UTC
|
22
|
+
|
23
|
+
Rack "to_path" support is dropped since few servers can
|
24
|
+
take advantage of this in a non-buggy way.
|
25
|
+
|
26
|
+
As a consolation, #each should be less GC-intensive by
|
27
|
+
with explicit calls to String#clear to reduce memory
|
28
|
+
pressure.
|
29
|
+
|
30
|
+
3 changes since 0.5.0
|
31
|
+
|
32
|
+
pkg.mk: avoid network for "gem install"
|
33
|
+
request: drop to_path support
|
34
|
+
explicitly clear large buf when it is obviously safe
|
35
|
+
|
36
|
+
=== http_spew 0.5.0 / 2016-10-31 20:43 UTC
|
37
|
+
|
38
|
+
This release requires Ruby 2.1 or later.
|
39
|
+
|
40
|
+
13 changes since 0.4.1:
|
41
|
+
|
42
|
+
gemspec: require kcar >= 0.3.1
|
43
|
+
test/helper: explicit redirect for Ruby 2.0.0
|
44
|
+
update packaging + docs (website)
|
45
|
+
allow all future GPL versions
|
46
|
+
add benchmark scripts
|
47
|
+
relax dependency on unicorn
|
48
|
+
declare empty classes with constant assignment
|
49
|
+
test_upload: use object_id to check matches
|
50
|
+
use frozen string literals for Ruby 2.1+
|
51
|
+
merge into kcar project and mailing list
|
52
|
+
dedicated mailing list
|
53
|
+
rely on opt_str_freeze in more places
|
54
|
+
use monotonic clock for timing
|
55
|
+
|
1
56
|
=== http_spew 0.4.1 / 2012-09-23 00:01 UTC
|
2
57
|
|
3
58
|
Fix formatting of user-supplied headers.
|
data/README
CHANGED
@@ -11,7 +11,6 @@ Use HTTP Spew if you wish you could kinda multicast with HTTP...
|
|
11
11
|
* No support for DNS resolution (WONTFIX, ever)
|
12
12
|
* No support for HTTPS
|
13
13
|
* No support for keepalive (yet?)
|
14
|
-
* No support for Ruby 1.8, this is Ruby 1.9-only
|
15
14
|
* Not remotely RFC-compliant
|
16
15
|
* Messes up analytics/reporting on servers
|
17
16
|
* Resets server connections
|
@@ -33,13 +32,13 @@ It's also completely untested and unused anywhere!
|
|
33
32
|
|
34
33
|
You can get the latest source via git from the following locations:
|
35
34
|
|
36
|
-
git://
|
35
|
+
git://yhbt.net/http_spew.git
|
37
36
|
git://repo.or.cz/http_spew.git (mirror)
|
38
37
|
|
39
38
|
You may browse the code from the web and download the latest snapshot
|
40
39
|
tarballs here:
|
41
40
|
|
42
|
-
*
|
41
|
+
* https://yhbt.net/http_spew.git
|
43
42
|
* http://repo.or.cz/w/http_spew.git (gitweb)
|
44
43
|
|
45
44
|
Inline patches (from "git format-patch") to the mailing list are
|
@@ -54,8 +53,8 @@ don't email the git mailing list or maintainer with http_spew patches.
|
|
54
53
|
== Contact
|
55
54
|
|
56
55
|
All feedback (bug reports, user/development discussion, patches, pull
|
57
|
-
requests) go to the mailing list: mailto:
|
56
|
+
requests) go to the mailing list: mailto:http_spew-public@yhbt.net
|
58
57
|
|
59
|
-
Mailing list archives
|
58
|
+
Mailing list archives may be viewed and downloaded here:
|
60
59
|
|
61
|
-
|
60
|
+
https://yhbt.net/http_spew-public/
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
require "./test/helper"
|
3
|
+
require "benchmark"
|
4
|
+
|
5
|
+
class TestBMContentMD5 < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
@addr, @port, @srv = start_server("./test/content-md5.ru", 1)
|
8
|
+
@sockaddr = Socket.pack_sockaddr_in(@port, @addr)
|
9
|
+
@env = {
|
10
|
+
"REQUEST_METHOD" => "PUT",
|
11
|
+
"REQUEST_URI" => "/",
|
12
|
+
"HTTP_HOST" => "example.com",
|
13
|
+
}
|
14
|
+
@tmpfiles = []
|
15
|
+
@bs = ENV['bs'] ? ENV['bs'].to_i : 1024 * 1024
|
16
|
+
@count = ENV['count'] ? ENV['count'].to_i : 1000
|
17
|
+
@cmd = %w(dd if=/dev/zero)
|
18
|
+
@cmd << "bs=#@bs"
|
19
|
+
@cmd << "count=#@count"
|
20
|
+
end
|
21
|
+
|
22
|
+
def teardown
|
23
|
+
Process.kill(:QUIT, @srv)
|
24
|
+
Process.waitpid2(@srv)
|
25
|
+
@tmpfiles.each { |tmp| tmp.closed? or tmp.close! }
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_upload_with_md5
|
29
|
+
rd, wr = IO.pipe
|
30
|
+
pid = fork do
|
31
|
+
$stdout.reopen(wr)
|
32
|
+
rd.close
|
33
|
+
wr.close
|
34
|
+
exec(*@cmd)
|
35
|
+
end
|
36
|
+
wr.close
|
37
|
+
@env["CONTENT_LENGTH"] = (@bs * @count).to_s
|
38
|
+
@env["rack.input"] = rd
|
39
|
+
input = HTTP_Spew::ContentMD5.new(@env)
|
40
|
+
assert_nil @env["CONTENT_LENGTH"]
|
41
|
+
assert_equal "chunked", @env["HTTP_TRANSFER_ENCODING"]
|
42
|
+
req = HTTP_Spew::Request.new(@env, input, @sockaddr)
|
43
|
+
rv = nil
|
44
|
+
res = Benchmark.measure do
|
45
|
+
rv = req.run(100000)
|
46
|
+
end
|
47
|
+
assert_equal 200, rv[0].to_i
|
48
|
+
pid, status = Process.waitpid2(pid)
|
49
|
+
assert status.success?
|
50
|
+
p res
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "./test/helper"
|
2
|
+
require "benchmark"
|
3
|
+
|
4
|
+
class TestBMContentMD5InputSpray < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
@nr = 4
|
7
|
+
@addr, @port, @srv = start_server("./test/content-md5.ru", @nr)
|
8
|
+
@sockaddr = Socket.pack_sockaddr_in(@port, @addr)
|
9
|
+
@env = {
|
10
|
+
"REQUEST_METHOD" => "PUT",
|
11
|
+
"REQUEST_URI" => "/",
|
12
|
+
"HTTP_HOST" => "example.com",
|
13
|
+
}
|
14
|
+
@tmpfiles = []
|
15
|
+
@bs = ENV['bs'] ? ENV['bs'].to_i : 1024 * 1024
|
16
|
+
@count = ENV['count'] ? ENV['count'].to_i : 1000
|
17
|
+
@cmd = %w(dd if=/dev/zero)
|
18
|
+
@cmd << "bs=#@bs"
|
19
|
+
@cmd << "count=#@count"
|
20
|
+
end
|
21
|
+
|
22
|
+
def teardown
|
23
|
+
Process.kill(:QUIT, @srv)
|
24
|
+
Process.waitpid2(@srv)
|
25
|
+
@tmpfiles.each { |tmp| tmp.closed? or tmp.close! }
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_spray_with_md5
|
29
|
+
rd, wr = IO.pipe
|
30
|
+
pid = fork do
|
31
|
+
$stdout.reopen(wr)
|
32
|
+
rd.close
|
33
|
+
wr.close
|
34
|
+
exec(*@cmd)
|
35
|
+
end
|
36
|
+
wr.close
|
37
|
+
@env["CONTENT_LENGTH"] = (@bs * @count).to_s
|
38
|
+
@env["rack.input"] = rd
|
39
|
+
input = HTTP_Spew::ContentMD5.new(@env)
|
40
|
+
sprayer = HTTP_Spew::InputSpray.new(@env, @nr, input)
|
41
|
+
assert_nil @env["CONTENT_LENGTH"]
|
42
|
+
assert_equal "chunked", @env["HTTP_TRANSFER_ENCODING"]
|
43
|
+
reqs = sprayer.readers.map do |md5_input|
|
44
|
+
HTTP_Spew::Request.new(@env, md5_input, @sockaddr)
|
45
|
+
end
|
46
|
+
assert_equal @nr, reqs.size
|
47
|
+
rv = nil
|
48
|
+
res = Benchmark.measure do
|
49
|
+
rv = HTTP_Spew.wait_mt reqs.size, reqs, 3600
|
50
|
+
end
|
51
|
+
assert_equal @nr, rv.size
|
52
|
+
rv.each do |resp|
|
53
|
+
assert_equal 200, resp.response[0].to_i
|
54
|
+
end
|
55
|
+
pid, status = Process.waitpid2(pid)
|
56
|
+
assert status.success?
|
57
|
+
p res
|
58
|
+
end
|
59
|
+
end
|
data/http_spew.gemspec
CHANGED
@@ -1,24 +1,20 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'wrongdoc'
|
4
|
-
extend Wrongdoc::Gemspec
|
5
|
-
name, summary, title = readme_metadata
|
1
|
+
manifest = File.exist?('.manifest') ?
|
2
|
+
IO.readlines('.manifest').map!(&:chomp!) : `git ls-files`.split("\n")
|
6
3
|
|
7
4
|
Gem::Specification.new do |s|
|
8
5
|
s.name = %q{http_spew}
|
9
|
-
s.version = ENV[
|
10
|
-
s.authors = ["
|
11
|
-
s.
|
12
|
-
s.
|
13
|
-
s.
|
14
|
-
|
6
|
+
s.version = (ENV['VERSION'] || '0.7.1').dup
|
7
|
+
s.authors = ["http_spew hackers"]
|
8
|
+
s.description = File.read('README').split("\n\n")[1]
|
9
|
+
s.email = %q{http_spew-public@yhbt.net}
|
10
|
+
s.extra_rdoc_files = IO.readlines('.document').map!(&:chomp!).keep_if do |f|
|
11
|
+
File.exist?(f)
|
12
|
+
end
|
15
13
|
s.files = manifest
|
16
|
-
s.homepage =
|
17
|
-
s.summary =
|
18
|
-
s.rdoc_options = rdoc_options
|
19
|
-
s.rubyforge_project = %q{rainbows}
|
14
|
+
s.homepage = 'https://yhbt.net/http_spew/'
|
15
|
+
s.summary = 'HTTP Spew - LAN-only HTTP spam^H^H^H^Hclient for Ruby'
|
20
16
|
s.test_files = Dir["test/test_*.rb"]
|
21
|
-
s.add_dependency(%q<kcar>, "~> 0.3")
|
22
|
-
s.
|
23
|
-
s.
|
17
|
+
s.add_dependency(%q<kcar>, [ "~> 0.3", ">= 0.3.1"])
|
18
|
+
s.required_ruby_version = '>= 2.3'
|
19
|
+
s.licenses = %w(GPL-2.0+)
|
24
20
|
end
|
@@ -3,17 +3,28 @@
|
|
3
3
|
# This is a OS-level pipe that overrides IO#read to provide
|
4
4
|
# IO#readpartial-like semantics while remaining Rack::Lint-compatible
|
5
5
|
# for EOF, meaning we return nil on EOF instead of raising EOFError.
|
6
|
-
class HTTP_Spew::ChunkyPipe <
|
6
|
+
class HTTP_Spew::ChunkyPipe < IO
|
7
7
|
|
8
8
|
# other threads may force an error to be raised in the +read+
|
9
9
|
# method
|
10
10
|
attr_accessor :error
|
11
11
|
|
12
|
+
class << self
|
13
|
+
alias new pipe
|
14
|
+
end
|
15
|
+
|
12
16
|
# Override IO#read to behave like IO#readpartial, but still return +nil+
|
13
17
|
# on EOF instead of raising EOFError.
|
14
|
-
def read(
|
18
|
+
def read(len = 16384, buf = '')
|
15
19
|
check_err!
|
16
|
-
|
20
|
+
case read_nonblock(len, buf, exception: false)
|
21
|
+
when nil
|
22
|
+
return check_err! || close
|
23
|
+
when :wait_readable
|
24
|
+
wait_readable # retry
|
25
|
+
else
|
26
|
+
return buf
|
27
|
+
end while true
|
17
28
|
end
|
18
29
|
|
19
30
|
def check_err!
|
@@ -41,11 +41,11 @@ module HTTP_Spew::ClassMethods
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def with_timeout(t)
|
44
|
-
t0 =
|
44
|
+
t0 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
45
45
|
yield
|
46
|
-
|
47
|
-
|
48
|
-
|
46
|
+
ensure
|
47
|
+
t[0] -= Process.clock_gettime(Process::CLOCK_MONOTONIC) - t0
|
48
|
+
t[0] = 0.0 if t[0] < 0
|
49
49
|
end
|
50
50
|
|
51
51
|
# Returns an array of requests that are complete, including those
|
@@ -53,14 +53,14 @@ module HTTP_Spew::ClassMethods
|
|
53
53
|
# If +need+ is fullfilled, it closes all incomplete requests.
|
54
54
|
def wait_mt(need, requests, timeout)
|
55
55
|
ready, failed = [], []
|
56
|
-
r, w =
|
56
|
+
r, w = IO.pipe
|
57
57
|
active = []
|
58
58
|
t = [ timeout ]
|
59
59
|
requests.each_with_index do |req, i|
|
60
60
|
active << Thread.new do
|
61
61
|
begin
|
62
62
|
rv = req.run(timeout)
|
63
|
-
w.write([ i ].pack("v"))
|
63
|
+
w.write([ i ].pack("v".freeze))
|
64
64
|
rv
|
65
65
|
rescue => err
|
66
66
|
err
|
@@ -68,8 +68,8 @@ module HTTP_Spew::ClassMethods
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
begin
|
71
|
-
with_timeout(t) { r.
|
72
|
-
req_idx = r.read(2).unpack("v")[0]
|
71
|
+
with_timeout(t) { r.wait_readable(t[0]) }
|
72
|
+
req_idx = r.read(2).unpack("v".freeze)[0]
|
73
73
|
thr = active[req_idx]
|
74
74
|
with_timeout(t) { thr.join(t[0]) }
|
75
75
|
rv = thr.value
|
@@ -81,9 +81,9 @@ module HTTP_Spew::ClassMethods
|
|
81
81
|
pending = requests - ready
|
82
82
|
error = HTTP_Spew::TimeoutError.new("request timed out")
|
83
83
|
ready.concat(error_all(pending, error))
|
84
|
-
|
85
|
-
|
86
|
-
|
84
|
+
ensure
|
85
|
+
w.close
|
86
|
+
r.close
|
87
87
|
end
|
88
88
|
|
89
89
|
def wait(need, requests, timeout)
|
@@ -110,7 +110,7 @@ module HTTP_Spew::ClassMethods
|
|
110
110
|
break if pollset.empty?
|
111
111
|
|
112
112
|
busy = pollset.keys
|
113
|
-
rv = with_timeout(t) {
|
113
|
+
rv = with_timeout(t) { do_poll(pollset, t[0]) } or break
|
114
114
|
end while t[0] > 0.0 && requests = rv.keys.concat(busy).uniq!
|
115
115
|
|
116
116
|
ready.concat(failed)
|
@@ -121,4 +121,32 @@ module HTTP_Spew::ClassMethods
|
|
121
121
|
end
|
122
122
|
ready
|
123
123
|
end
|
124
|
+
|
125
|
+
begin
|
126
|
+
require 'kgio'
|
127
|
+
def do_poll(pollset, sec) # :nodoc:
|
128
|
+
Kgio.poll(pollset, (sec * 1000).to_i)
|
129
|
+
end
|
130
|
+
rescue LoadError
|
131
|
+
# emulate Kgio.poll with IO.select
|
132
|
+
def do_poll(pollset, sec) # :nodoc:
|
133
|
+
rd = []
|
134
|
+
wr = []
|
135
|
+
pollset.each do |io, events|
|
136
|
+
case events
|
137
|
+
when :wait_readable
|
138
|
+
rd << io
|
139
|
+
when :wait_writable
|
140
|
+
wr << io
|
141
|
+
else
|
142
|
+
raise "BUG: unsupported event #{event.inspect} for #{io.inspect}"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
ready = IO.select(rd, wr, nil, sec) or return
|
146
|
+
pollset.clear
|
147
|
+
ready[0].each { |io| pollset[io] = 1 } # POLLIN
|
148
|
+
ready[1].each { |io| pollset[io] = 4 } # POLLOUT
|
149
|
+
pollset
|
150
|
+
end
|
151
|
+
end
|
124
152
|
end
|
@@ -7,17 +7,16 @@ class HTTP_Spew::ContentMD5
|
|
7
7
|
attr_reader :content_md5
|
8
8
|
attr_reader :bytes_digested
|
9
9
|
|
10
|
-
CRLF = "\r\n" # :nodoc:
|
11
|
-
|
12
10
|
def initialize(env, input = env["rack.input"])
|
13
11
|
if trailer = env["HTTP_TRAILER"]
|
14
12
|
unless trailer.split(/\s*,\s*/).grep(/\AContent-MD5\z/i)[0]
|
15
|
-
trailer << (trailer.empty? ? "Content-MD5"
|
13
|
+
trailer << (trailer.empty? ? "Content-MD5".freeze
|
14
|
+
: ",Content-MD5".freeze)
|
16
15
|
end
|
17
16
|
else
|
18
|
-
env["HTTP_TRAILER"] = "Content-MD5"
|
17
|
+
env["HTTP_TRAILER"] = "Content-MD5".freeze
|
19
18
|
end
|
20
|
-
env["HTTP_TRANSFER_ENCODING"] = "chunked"
|
19
|
+
env["HTTP_TRANSFER_ENCODING"] = "chunked".freeze
|
21
20
|
@to_io, wr = HTTP_Spew::ChunkyPipe.new
|
22
21
|
expect_md5 = env.delete("HTTP_CONTENT_MD5")
|
23
22
|
expect_len = env.delete("CONTENT_LENGTH")
|
@@ -41,8 +40,9 @@ class HTTP_Spew::ContentMD5
|
|
41
40
|
@bytes_digested += n
|
42
41
|
wr.write("#{n.to_s(16)}\r\n")
|
43
42
|
digest.update(buf)
|
44
|
-
wr.write(buf <<
|
43
|
+
wr.write(buf << "\r\n".freeze)
|
45
44
|
end while input.read(0x4000, buf)
|
45
|
+
buf.clear
|
46
46
|
end
|
47
47
|
if expect_len && expect_len.to_i != @bytes_digested
|
48
48
|
raise HTTP_Spew::LengthError,
|
data/lib/http_spew/headers.rb
CHANGED
@@ -1,18 +1,10 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
2
|
module HTTP_Spew::Headers
|
3
|
-
# :stopdoc:
|
4
|
-
REQUEST_METHOD = "REQUEST_METHOD"
|
5
|
-
REQUEST_URI = "REQUEST_URI"
|
6
|
-
CRLF = "\r\n"
|
7
|
-
QUERY_STRING = "QUERY_STRING"
|
8
|
-
PATH_INFO = "PATH_INFO"
|
9
|
-
CONTENT_TYPE = "CONTENT_TYPE" # specified by Rack to be !/^HTTP_/
|
10
|
-
# :startdoc:
|
11
3
|
|
12
4
|
# regenerates the request_uri from a Rack +env+
|
13
5
|
def request_uri(env)
|
14
|
-
qs = env[QUERY_STRING]
|
15
|
-
qs.size == 0 ? env[PATH_INFO] : "#{env[PATH_INFO]}?#{qs}"
|
6
|
+
qs = env['QUERY_STRING']
|
7
|
+
qs.size == 0 ? env['PATH_INFO'] : "#{env['PATH_INFO']}?#{qs}"
|
16
8
|
end
|
17
9
|
module_function :request_uri
|
18
10
|
|
@@ -27,26 +19,25 @@ module HTTP_Spew::Headers
|
|
27
19
|
#
|
28
20
|
# buf, input = env_to_headers(env, input)
|
29
21
|
def env_to_headers(env, input)
|
30
|
-
req = "#{env[REQUEST_METHOD]} " \
|
31
|
-
"#{env[REQUEST_URI] || request_uri(env)} HTTP/1.1\r\n" \
|
22
|
+
req = "#{env['REQUEST_METHOD']} " \
|
23
|
+
"#{env['REQUEST_URI'] || request_uri(env)} HTTP/1.1\r\n" \
|
32
24
|
"Connection: close\r\n"
|
33
|
-
uscore, dash = "_", "-"
|
34
25
|
env.each do |key,value|
|
35
26
|
%r{\AHTTP_(\w+)\z} =~ key or next
|
36
27
|
key = $1
|
37
28
|
%r{\A(?:VERSION|EXPECT|TRANSFER_ENCODING|CONNECTION|KEEP_ALIVE)\z}x =~
|
38
29
|
key and next
|
39
30
|
|
40
|
-
key.tr!(
|
31
|
+
key.tr!('_'.freeze, '-'.freeze)
|
41
32
|
req << "#{key}: #{value}\r\n"
|
42
33
|
end
|
43
34
|
if input
|
44
35
|
req << (input.respond_to?(:size) ?
|
45
36
|
"Content-Length: #{input.size}\r\n" :
|
46
|
-
"Transfer-Encoding: chunked\r\n")
|
47
|
-
ct = env[CONTENT_TYPE] and req << "Content-Type: #{ct}\r\n"
|
37
|
+
"Transfer-Encoding: chunked\r\n".freeze)
|
38
|
+
ct = env['CONTENT_TYPE'] and req << "Content-Type: #{ct}\r\n"
|
48
39
|
end
|
49
|
-
req <<
|
40
|
+
req << "\r\n".freeze
|
50
41
|
String === input ? (req << input) : [ req, input ]
|
51
42
|
end
|
52
43
|
module_function :env_to_headers
|