net-http-spdy 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,11 @@
1
+ rvm:
2
+ - 1.9.3
3
+ - ruby-head
4
+
5
+ script: rake test
6
+
7
+ gemfile:
8
+ - Gemfile
9
+
10
+ notifications:
11
+ email: authornari+travis@gmail.com
data/Gemfile CHANGED
@@ -3,5 +3,6 @@ source "http://rubygems.org"
3
3
  gemspec
4
4
 
5
5
  group :test do
6
- gem 'test-unit', '~> 2.5.3'
6
+ gem 'test-unit', '~> 2.5.4'
7
+ gem 'eventmachine', '~> 1.0.0'
7
8
  end
@@ -12,7 +12,8 @@ A SPDY HTTP client implementation with extended Net:HTTP.
12
12
 
13
13
  == FEATURES/PROBLEMS:
14
14
 
15
- * Supports SSL/TLS in Ruby 2.0.0 or later
15
+ * Support SPDYv2
16
+ * Support SSL/TLS in Ruby 2.0.0 or later
16
17
 
17
18
  == COMPARING:
18
19
 
@@ -10,14 +10,12 @@ flag_uris = %w(
10
10
  end
11
11
  fetch_threads = []
12
12
  uri = URI('https://www.modspdy.com/world-flags/')
13
- http = Net::HTTP::SPDY.new(uri.host, uri.port)
14
- http.use_ssl = true
15
- http.start
16
- flag_uris.each do |uri|
17
- req = Net::HTTP::Get.new(uri)
18
- fetch_threads << Thread.start do
19
- http.request(req)
13
+ Net::HTTP::SPDY.start(uri.host, uri.port, use_ssl: true) do |http|
14
+ flag_uris.each do |uri|
15
+ req = Net::HTTP::Get.new(uri)
16
+ fetch_threads << Thread.start do
17
+ http.request(req)
18
+ end
20
19
  end
20
+ fetch_threads.each(&:join)
21
21
  end
22
- fetch_threads.each(&:join)
23
- http.finish
@@ -4,6 +4,49 @@ $: << File.join(File.dirname(__FILE__), "../../../vender/spdy/lib/")
4
4
  require 'spdy'
5
5
  require 'openssl'
6
6
 
7
+ # A SPDY HTTP Client with Net::HTTP
8
+ #
9
+ # Net::HTTP::SPDY has created with extending Net::HTTP.
10
+ # See Net::HTTP, if you want to know major usages.
11
+ #
12
+ # Different points from Net::HTTP to Net::HTTP::SPDY are here.
13
+ #
14
+ # == A TCP socket per multi-streams
15
+ #
16
+ # A TCP Socket conneted with Net::HTTP::SPDY will not close usually
17
+ # until you call Net::HTTP#finish.
18
+ # And, you can use multi-thread to send HTTP requests continuously.
19
+ #
20
+ # Example:
21
+ #
22
+ # require 'net/http/spdy'
23
+ #
24
+ # flag_uris = %w(
25
+ # images_sm/ad_flag.png images_sm/ae_flag.png
26
+ # images_sm/af_flag.png images_sm/ag_flag.png
27
+ # images_sm/ai_flag.png images_sm/am_flag.png
28
+ # images_sm/ao_flag.png images_sm/ar_flag.png
29
+ # images_sm/as_flag.png images_sm/at_flag.png).map do |path|
30
+ # URI('https://www.modspdy.com/world-flags/' + path)
31
+ # end
32
+ # fetch_threads = []
33
+ # uri = URI('https://www.modspdy.com/world-flags/')
34
+ # Net::HTTP::SPDY.start(uri.host, uri.port, use_ssl: true) do |http|
35
+ # flag_uris.each do |uri|
36
+ # req = Net::HTTP::Get.new(uri)
37
+ # fetch_threads << Thread.start do
38
+ # http.request(req)
39
+ # end
40
+ # end
41
+ # fetch_threads.each(&:join)
42
+ # end
43
+ #
44
+ # == Server push
45
+ #
46
+ # You can check to exist HTTP responses pushed by a server by
47
+ # Net::HTTPResponse#has_associatd_response? and you can take
48
+ # it by Net::HTTPResponse#associated_responses .
49
+ #
7
50
  class Net::HTTP::SPDY < Net::HTTP
8
51
  def initialize(address, port = nil)
9
52
  super
@@ -17,21 +60,22 @@ class Net::HTTP::SPDY < Net::HTTP
17
60
  end
18
61
 
19
62
  if RUBY_VERSION >= "2.0.0"
20
- SSL_IVNAMES << :@npn_protocols
21
- SSL_ATTRIBUTES << :npn_protocols
22
63
  SSL_IVNAMES << :@npn_select_cb
23
64
  SSL_ATTRIBUTES << :npn_select_cb
24
65
  end
25
66
 
67
+ undef :close_on_empty_response= if defined?(self.close_on_empty_response=true)
68
+
69
+ private
70
+
26
71
  def connect
72
+ if RUBY_VERSION < "2.0.0" && use_ssl?
73
+ raise ArgumentError, "Supports SSL in Ruby 2.0.0 or later only"
74
+ end
27
75
  super
28
76
  @stream_session = StreamSession.new(@socket)
29
77
  end
30
78
 
31
- undef :close_on_empty_response= if defined?(self.close_on_empty_response=true)
32
-
33
- private
34
-
35
79
  def transport_request(req)
36
80
  begin_transport req
37
81
  req.uri = URI((use_ssl? ? "https://" : "http://") + addr_port + req.path)
@@ -55,7 +99,10 @@ class Net::HTTP::SPDY < Net::HTTP
55
99
  begin
56
100
  r = Net::HTTPResponse.read_new(s)
57
101
  end while r.kind_of?(Net::HTTPContinue)
58
- yield r if block_given?
102
+ r.reading_body(s, true) {
103
+ yield r if block_given?
104
+ }
105
+ r.uri = s.uri
59
106
  res.associated_responses << r
60
107
  end
61
108
  end
@@ -15,7 +15,7 @@ class Net::HTTPGenericRequest
15
15
  if is_spdy?(sock)
16
16
  stream = sock
17
17
  write_header stream, ver, path
18
- wait_for_continue stream, ver if stream.sock.continue_timeout
18
+ wait_for_continue stream, ver if stream.continue_timeout
19
19
  IO.copy_stream(f, stream)
20
20
  else
21
21
  send_request_with_body_stream_wo_spdy
@@ -1,15 +1,23 @@
1
1
  class Net::HTTPResponse
2
- if RUBY_VERSION <= "2.0.0"
3
- attr_accessor :uri
2
+ if RUBY_VERSION < '2.0.0'
3
+ attr_reader :uri
4
+
5
+ def uri= uri # :nodoc:
6
+ @uri = uri.dup if uri
7
+ end
4
8
  end
5
9
 
6
10
  attr_reader :associated_responses
7
11
 
8
- def has_associatd_response?
12
+ ##
13
+ # Returns true when itself has a associated_response
14
+ def has_associated_response?
9
15
  @associated_responses ||= []
10
- not @response.empty?
16
+ not @associated_responses.empty?
11
17
  end
12
18
 
19
+ ##
20
+ # Returns associated responses
13
21
  def associated_responses
14
22
  @associated_responses ||= []
15
23
  return @associated_responses
@@ -3,9 +3,9 @@ require 'forwardable'
3
3
  class Net::HTTP::SPDY::Stream
4
4
  extend Forwardable
5
5
 
6
- attr_accessor :buf, :eof, :connected
7
- attr_reader :sock, :uri, :assocs, :new_assoc, :id
8
- def_delegators :@sock, :io, :closed?, :close
6
+ attr_accessor :buf, :eof, :connected, :new_assoc
7
+ attr_reader :sock, :uri, :assocs, :id
8
+ def_delegators :@sock, :io, :closed?, :close, :continue_timeout
9
9
 
10
10
  def initialize(id, session, sock, uri)
11
11
  @id = id
@@ -73,8 +73,8 @@ class Net::HTTP::SPDY::Stream
73
73
  }
74
74
  h['host'] = request.delete("host").first
75
75
 
76
- %w(Connection Host Keep-Alive Proxy-Connection Transfer-Encoding).each do |h|
77
- raise ArgumentError, "#{h} cannot send with SPDY" if not request[h].nil?
76
+ %w(Connection Host Keep-Alive Proxy-Connection Transfer-Encoding).each do |i|
77
+ raise ArgumentError, "Can't send #{i} with SPDY" if not request[i].nil?
78
78
  end
79
79
 
80
80
  sr = SPDY::Protocol::Control::SynStream.new(zlib_session: @session.parser.zlib_session)
@@ -98,6 +98,14 @@ class Net::HTTP::SPDY::Stream
98
98
  end
99
99
  end
100
100
 
101
+ def write_protocol_error
102
+ d = SPDY::Protocol::Control::RstStream.new
103
+ d.create(stream_id: @id, status_code: 1)
104
+ @session.monitor.synchronize do
105
+ @sock.write d.to_binary_s
106
+ end
107
+ end
108
+
101
109
  def close_write
102
110
  d = SPDY::Protocol::Data::Frame.new
103
111
  d.create(stream_id: @id, flags: 1)
@@ -112,23 +120,23 @@ class Net::HTTP::SPDY::Stream
112
120
  def read_frame(ignore_eof)
113
121
  while buf.empty?
114
122
  raise EOFError if eof? && !ignore_eof
115
- begin
116
- @session.monitor.synchronize do
123
+ @session.monitor.synchronize do
124
+ begin
117
125
  return if not buf.empty?
118
126
  s = @sock.io.read_nonblock(BUFSIZE)
119
127
  @session.parse(s)
120
- end
121
- rescue IO::WaitReadable
122
- if IO.select([@sock.io], nil, nil, @sock.read_timeout)
123
- retry
124
- else
125
- raise Net::ReadTimeout
126
- end
127
- rescue IO::WaitWritable
128
- if IO.select(nil, [@sock.io], nil, @sock.read_timeout)
129
- retry
130
- else
131
- raise Net::ReadTimeout
128
+ rescue IO::WaitReadable
129
+ if IO.select([@sock.io], nil, nil, @sock.read_timeout)
130
+ retry
131
+ else
132
+ raise Net::ReadTimeout
133
+ end
134
+ rescue IO::WaitWritable
135
+ if IO.select(nil, [@sock.io], nil, @sock.read_timeout)
136
+ retry
137
+ else
138
+ raise Net::ReadTimeout
139
+ end
132
140
  end
133
141
  end
134
142
  end
@@ -50,7 +50,7 @@ class Net::HTTP::SPDY
50
50
  @sock.debug_output.puts "on_open: id=<#{id}>,assoc_id=<#{assoc_id}>" if @sock.debug_output
51
51
  if assoc_id
52
52
  s = @streams.fetch(id)
53
- s.new_assoc = @assoc_id
53
+ s.new_assoc = assoc_id
54
54
  end
55
55
  end
56
56
  parser.on_headers do |id, headers|
@@ -59,15 +59,19 @@ class Net::HTTP::SPDY
59
59
  if s.new_assoc
60
60
  # TODO: check invalid header and send PROTOCOL_ERROR
61
61
  uri = URI(headers.delete('url'))
62
- assoc = push(assoc_id, uri, true)
62
+ assoc = push(s.new_assoc, uri, true)
63
63
  s.new_assoc = nil
64
64
  s.assocs << assoc
65
+ s = assoc
65
66
  else
66
67
  s = @streams.fetch(id)
67
68
  end
68
69
 
69
- # TODO: check invalid header
70
70
  h = ["#{headers['version']} #{headers['status']}"]
71
+ if headers['version'].nil? or headers['status'].nil?
72
+ s.write_protocol_error
73
+ raise StreamError, "Receives a SYN_REPLY without a status or without a version header"
74
+ end
71
75
  code, msg = headers.delete('status').split(" ")
72
76
  r = ::Net::HTTPResponse.new(headers.delete('version'), code, msg)
73
77
  r.each_capitalized{|k,v| h << "#{k}: #{v}" }
@@ -1,5 +1,5 @@
1
1
  require 'net/http'
2
2
 
3
3
  class Net::HTTP::SPDY < Net::HTTP
4
- VERSION = '0.0.2'
4
+ VERSION = '0.0.3'
5
5
  end
@@ -0,0 +1,104 @@
1
+ module TestNetHTTPSPDY
2
+ extend Forwardable
3
+
4
+ HANDLERS = %w(on_open on_ping on_headers on_settings
5
+ on_body on_message_complete on_reset)
6
+
7
+ def setup
8
+ @parser = SPDY::Parser.new
9
+ spawn_server
10
+ end
11
+
12
+ def teardown
13
+ EM.stop_event_loop
14
+ while @server_thread.alive?
15
+ sleep 0.1
16
+ end
17
+ end
18
+
19
+ def new
20
+ http = Net::HTTP::SPDY.new(config('host'), config('port'))
21
+ http.set_debug_output logfile()
22
+ http
23
+ end
24
+
25
+ def config(key)
26
+ @config ||= self.class::CONFIG
27
+ @config[key]
28
+ end
29
+
30
+ def logfile
31
+ $DEBUG ? $stderr : NullWriter.new
32
+ end
33
+
34
+ def start(&block)
35
+ new.start(&block)
36
+ end
37
+
38
+ def_delegators "SPDYHandler", *HANDLERS
39
+ def_delegators :@parser, :zlib_session
40
+
41
+ private
42
+ def unused_port
43
+ s = TCPServer.open(0)
44
+ port = s.addr[1]
45
+ s.close
46
+ port
47
+ end
48
+
49
+ def spawn_server
50
+ @config = {'host' => '127.0.0.1', 'port' => unused_port}
51
+ SPDYHandler.parser = @parser
52
+ @server_thread = Thread.start do
53
+ EM.run do
54
+ EM.start_server(config('host'), config('port'), SPDYHandler)
55
+ end
56
+ end
57
+ @server_thread.abort_on_exception = true
58
+ n_try_max = 5
59
+ begin
60
+ TCPSocket.open(config('host'), config('port')).close
61
+ rescue Errno::ECONNREFUSED
62
+ sleep 0.2
63
+ n_try_max -= 1
64
+ raise 'cannot spawn server; give up' if n_try_max < 0
65
+ retry
66
+ end
67
+ end
68
+
69
+ class SPDYHandler < EM::Connection
70
+ def self.parser=(parser)
71
+ @@parser = parser
72
+ end
73
+
74
+ HANDLERS.each do |h|
75
+ self.class_eval <<-METHOD
76
+ @@#{h} = nil
77
+ def self.#{h}(&block)
78
+ @@#{h} = block
79
+ end
80
+ METHOD
81
+ end
82
+
83
+ def post_init
84
+ HANDLERS.each do |h|
85
+ if self.class.class_variable_get("@@#{h}")
86
+ @@parser.send(h) do |*args|
87
+ self.class.class_variable_get("@@#{h}").call(self, *args)
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ def receive_data(data)
94
+ @@parser << data if not data.empty?
95
+ end
96
+ end
97
+
98
+ class NullWriter
99
+ def <<(s) end
100
+ def puts(*args) end
101
+ def print(*args) end
102
+ def printf(*args) end
103
+ end
104
+ end
@@ -9,6 +9,7 @@ Bundler.require(:default, :test)
9
9
  require "test/unit"
10
10
 
11
11
  require "net/http/spdy"
12
+ require 'helper'
12
13
 
13
14
  test_file = "./test/test_*.rb"
14
15
  Dir.glob(test_file) do |file|
@@ -1,48 +1,50 @@
1
- class TestAccessToWeb < Test::Unit::TestCase
2
- def test_get_google
3
- uri = URI('https://www.google.com/')
4
- http = Net::HTTP::SPDY.new(uri.host, uri.port)
5
- http.use_ssl = true
6
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
7
- http.start do |http|
8
- req = Net::HTTP::Get.new(uri)
9
- res = http.request(req)
10
- assert_include ["200", "302"], res.code
1
+ if RUBY_VERSION >= "2.0.0"
2
+ class TestAccessToWeb < Test::Unit::TestCase
3
+ def test_get_google
4
+ uri = URI('https://www.google.com/')
5
+ http = Net::HTTP::SPDY.new(uri.host, uri.port)
6
+ http.use_ssl = true
7
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
8
+ http.start do |http|
9
+ req = Net::HTTP::Get.new(uri)
10
+ res = http.request(req)
11
+ assert_include ["200", "302"], res.code
12
+ end
11
13
  end
12
- end
13
-
14
- def test_get_google_simple
15
- uri = URI('https://www.google.com/')
16
- Net::HTTP::SPDY.start(uri.host, uri.port, use_ssl: true) do |http|
17
- res = http.get("/")
18
- assert_include ["200", "302"], res.code
14
+
15
+ def test_get_google_simple
16
+ uri = URI('https://www.google.com/')
17
+ Net::HTTP::SPDY.start(uri.host, uri.port, use_ssl: true) do |http|
18
+ res = http.get("/")
19
+ assert_include ["200", "302"], res.code
20
+ end
19
21
  end
20
- end
21
-
22
- def test_get_world_flags_parallel
23
- flag_uris = %w(
24
- images_sm/ad_flag.png images_sm/ae_flag.png
25
- images_sm/af_flag.png images_sm/ag_flag.png
26
- images_sm/ai_flag.png images_sm/am_flag.png
27
- images_sm/ao_flag.png images_sm/ar_flag.png
28
- images_sm/as_flag.png images_sm/at_flag.png).map do |path|
29
- URI('https://www.modspdy.com/world-flags/' + path)
30
- end
31
- fetch_threads = []
32
- uri = URI('https://www.modspdy.com/world-flags/')
33
- http = Net::HTTP::SPDY.new(uri.host, uri.port)
34
- http.use_ssl = true
35
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
36
- #http.set_debug_output $stderr
37
- http.start
38
- flag_uris.each do |uri|
39
- req = Net::HTTP::Get.new(uri)
40
- #fetch_threads << Thread.start do
41
- res = http.request(req)
42
- assert_equal "200", res.code
43
- #end
22
+
23
+ def test_get_world_flags_parallel
24
+ flag_uris = %w(
25
+ images_sm/ad_flag.png images_sm/ae_flag.png
26
+ images_sm/af_flag.png images_sm/ag_flag.png
27
+ images_sm/ai_flag.png images_sm/am_flag.png
28
+ images_sm/ao_flag.png images_sm/ar_flag.png
29
+ images_sm/as_flag.png images_sm/at_flag.png).map do |path|
30
+ URI('https://www.modspdy.com/world-flags/' + path)
31
+ end
32
+ fetch_threads = []
33
+ uri = URI('https://www.modspdy.com/world-flags/')
34
+ http = Net::HTTP::SPDY.new(uri.host, uri.port)
35
+ http.use_ssl = true
36
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
37
+ #http.set_debug_output $stderr
38
+ http.start
39
+ flag_uris.each do |uri|
40
+ req = Net::HTTP::Get.new(uri)
41
+ #fetch_threads << Thread.start do
42
+ res = http.request(req)
43
+ assert_equal "200", res.code
44
+ #end
45
+ end
46
+ fetch_threads.each(&:join)
47
+ http.finish
44
48
  end
45
- fetch_threads.each(&:join)
46
- http.finish
47
49
  end
48
50
  end
@@ -0,0 +1,108 @@
1
+ class TestSpdy < Test::Unit::TestCase
2
+ include TestNetHTTPSPDY
3
+
4
+ def test_get
5
+ on_headers do |sv, stream_id, headers|
6
+ sr = SPDY::Protocol::Control::SynReply.new(zlib_session: zlib_session)
7
+ h = {'Content-Type' => 'text/plain', 'status' => '200', 'version' => 'HTTP/1.1'}
8
+ sr.create(stream_id: stream_id, headers: h)
9
+ sv.send_data sr.to_binary_s
10
+
11
+ d = SPDY::Protocol::Data::Frame.new
12
+ d.create(stream_id: stream_id, data: "This is SPDY.", flags: 1)
13
+ sv.send_data d.to_binary_s
14
+
15
+ assert_equal "http", headers['scheme']
16
+ assert_equal "GET", headers['method']
17
+ assert_equal "/", headers['url']
18
+ assert_equal "HTTP/1.1", headers['version']
19
+ end
20
+ start do |http|
21
+ res = http.request_get("/")
22
+ assert_equal '200', res.code
23
+ assert_equal 'This is SPDY.', res.body
24
+ end
25
+ end
26
+
27
+ def test_server_push
28
+ on_headers do |sv, stream_id, headers|
29
+ sr = SPDY::Protocol::Control::SynReply.new(zlib_session: zlib_session)
30
+ h = {'Content-Type' => 'text/plain', 'status' => '200', 'version' => 'HTTP/1.1'}
31
+ sr.create(stream_id: stream_id, headers: h)
32
+ sv.send_data sr.to_binary_s
33
+
34
+ # server push start
35
+ sr = SPDY::Protocol::Control::SynStream.new(zlib_session: zlib_session)
36
+ h = {'Content-Type' => 'text/plain', 'status' => '200', 'version' => 'HTTP/1.1', 'url' => "http://127.0.0.1/test.txt"}
37
+ sr.create(
38
+ stream_id: stream_id, headers: h,
39
+ associated_to_stream_id: stream_id+1, flags: 2)
40
+ sv.send_data sr.to_binary_s
41
+
42
+ d = SPDY::Protocol::Data::Frame.new
43
+ d.create(stream_id: stream_id+1, data: "PUSH OK", flags: 1)
44
+ sv.send_data d.to_binary_s
45
+ # finish
46
+
47
+ d = SPDY::Protocol::Data::Frame.new
48
+ d.create(stream_id: stream_id, data: "OK", flags: 1)
49
+ sv.send_data d.to_binary_s
50
+ end
51
+ start do |http|
52
+ res = http.request_get("/")
53
+ assert_equal '200', res.code
54
+ assert_equal 'OK', res.body
55
+ assert_equal true, res.has_associated_response?
56
+ assoc = res.associated_responses.first
57
+ assert_equal '200', assoc.code
58
+ assert_equal 'PUSH OK', assoc.body
59
+ assert_equal 'http://127.0.0.1/test.txt', assoc.uri.to_s
60
+ end
61
+ end
62
+
63
+ def test_get_without_version
64
+ on_headers do |sv, stream_id, headers|
65
+ sr = SPDY::Protocol::Control::SynReply.new(zlib_session: zlib_session)
66
+ h = {"status" => '200'}
67
+ sr.create(stream_id: stream_id, headers: h, flags: 1)
68
+ sv.send_data sr.to_binary_s
69
+ end
70
+ on_reset do |stream_id, status_code|
71
+ assert_equal 1, status_code
72
+ end
73
+ assert_raise Net::HTTP::SPDY::StreamError do
74
+ start do |http|
75
+ http.request_get("/")
76
+ end
77
+ end
78
+ end
79
+
80
+ def test_post
81
+ post_data = ""
82
+ on_headers do |sv, stream_id, headers|
83
+ assert_equal "http", headers['scheme']
84
+ assert_equal "POST", headers['method']
85
+ assert_equal "/", headers['url']
86
+ assert_equal "HTTP/1.1", headers['version']
87
+ end
88
+ on_body do |sv, stream_id, data|
89
+ if data == 'data'
90
+ sr = SPDY::Protocol::Control::SynReply.new(zlib_session: zlib_session)
91
+ h = {'Content-Type' => 'text/plain', 'status' => '200', 'version' => 'HTTP/1.1'}
92
+ sr.create(stream_id: stream_id, headers: h)
93
+ sv.send_data sr.to_binary_s
94
+
95
+ d = SPDY::Protocol::Data::Frame.new
96
+ d.create(stream_id: stream_id, data: "OK", flags: 1)
97
+ sv.send_data d.to_binary_s
98
+ end
99
+ end
100
+
101
+ start do |http|
102
+ http.request_post("/", 'data') do |res|
103
+ assert_equal '200', res.code
104
+ assert_equal 'OK', res.body
105
+ end
106
+ end
107
+ end
108
+ end
@@ -95,7 +95,7 @@ module SPDY
95
95
  pckt = Control::Settings.new({:zlib_session => @zlib_session})
96
96
  pckt.read(@buffer)
97
97
 
98
- @on_settings.call(pckt.stream_id, pckt.status_code) if @on_settings
98
+ @on_settings.call(pckt.flags, pckt.headers) if @on_settings
99
99
 
100
100
  when 6 then # PING
101
101
  pckt = Control::Ping.new({:zlib_session => @zlib_session})
@@ -83,6 +83,7 @@ module SPDY
83
83
 
84
84
  def create(opts = {})
85
85
  build({:type => 1, :len => 10}.merge(opts))
86
+ self.associated_to_stream_id = opts.fetch(:associated_to_stream_id, 0)
86
87
  end
87
88
  end
88
89
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: net-http-spdy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-20 00:00:00.000000000 Z
12
+ date: 2013-01-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bindata
@@ -51,6 +51,7 @@ extensions: []
51
51
  extra_rdoc_files: []
52
52
  files:
53
53
  - ".gitignore"
54
+ - ".travis.yml"
54
55
  - Gemfile
55
56
  - README.rdoc
56
57
  - Rakefile
@@ -63,8 +64,10 @@ files:
63
64
  - lib/net/http/spdy/stream_session.rb
64
65
  - lib/net/http/spdy/version.rb
65
66
  - net-http-spdy.gemspec
67
+ - test/helper.rb
66
68
  - test/run-test.rb
67
69
  - test/test_access_to_web.rb
70
+ - test/test_spdy.rb
68
71
  - vender/spdy/README.md
69
72
  - vender/spdy/lib/spdy.rb
70
73
  - vender/spdy/lib/spdy/compat.rb
@@ -97,5 +100,7 @@ signing_key:
97
100
  specification_version: 3
98
101
  summary: A SPDY HTTP client implementation with extended Net:HTTP
99
102
  test_files:
103
+ - test/helper.rb
100
104
  - test/run-test.rb
101
105
  - test/test_access_to_web.rb
106
+ - test/test_spdy.rb