reel 0.4.0 → 0.5.0.pre

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of reel might be problematic. Click here for more details.

Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +5 -2
  3. data/Gemfile +6 -0
  4. data/README.md +26 -16
  5. data/benchmarks/hello_reel.rb +1 -1
  6. data/benchmarks/reel_pool.rb +27 -0
  7. data/examples/hello_world.rb +2 -2
  8. data/examples/{ssl_hello_world.rb → https_hello_world.rb} +1 -1
  9. data/examples/roundtrip.rb +1 -1
  10. data/examples/server_sent_events.rb +22 -18
  11. data/examples/spy_hello_world.rb +22 -0
  12. data/examples/websockets.rb +3 -3
  13. data/lib/reel.rb +6 -9
  14. data/lib/reel/connection.rb +40 -42
  15. data/lib/reel/mixins.rb +3 -1
  16. data/lib/reel/request.rb +40 -9
  17. data/lib/reel/request/body.rb +65 -0
  18. data/lib/reel/request/info.rb +21 -0
  19. data/lib/reel/{request_parser.rb → request/parser.rb} +2 -2
  20. data/lib/reel/request/state_machine.rb +26 -0
  21. data/lib/reel/response.rb +4 -11
  22. data/lib/reel/response/writer.rb +59 -0
  23. data/lib/reel/server.rb +30 -6
  24. data/lib/reel/server/http.rb +20 -0
  25. data/lib/reel/server/https.rb +63 -0
  26. data/lib/reel/spy.rb +71 -0
  27. data/lib/reel/stream.rb +2 -2
  28. data/lib/reel/version.rb +2 -2
  29. data/lib/reel/websocket.rb +1 -1
  30. data/reel.gemspec +3 -3
  31. data/spec/fixtures/ca.crt +27 -0
  32. data/spec/fixtures/ca.key +27 -0
  33. data/spec/fixtures/client.crt +81 -20
  34. data/spec/fixtures/client.unsigned.crt +22 -0
  35. data/spec/fixtures/server.crt +80 -20
  36. data/spec/reel/connection_spec.rb +50 -11
  37. data/spec/reel/{server_spec.rb → http_server_spec.rb} +1 -1
  38. data/spec/reel/https_server_spec.rb +119 -0
  39. data/spec/reel/{response_writer_spec.rb → response/writer_spec.rb} +10 -2
  40. data/spec/reel/websocket_spec.rb +2 -2
  41. data/spec/spec_helper.rb +3 -34
  42. data/spec/support/example_request.rb +34 -0
  43. metadata +56 -43
  44. data/examples/chunked.rb +0 -25
  45. data/lib/reel/request_body.rb +0 -56
  46. data/lib/reel/request_info.rb +0 -19
  47. data/lib/reel/response_writer.rb +0 -76
  48. data/lib/reel/ssl_server.rb +0 -41
  49. data/spec/reel/ssl_server_spec.rb +0 -54
data/lib/reel/spy.rb ADDED
@@ -0,0 +1,71 @@
1
+ require 'forwardable'
2
+
3
+ module Reel
4
+ # Prints out all traffic to a Reel server. Useful for debugging
5
+ class Spy
6
+ extend Forwardable
7
+
8
+ def_delegators :@socket, :closed?
9
+
10
+ def initialize(socket, logger = STDOUT)
11
+ @socket, @logger = socket, logger
12
+ @proto, @port, _, @ip = @socket.peeraddr
13
+ connected
14
+ end
15
+
16
+ # Log a connection to this server
17
+ def connected
18
+ log :connect, "+++ #{@ip}:#{@port} (#{@proto}) connected\n"
19
+ end
20
+
21
+ # Read from the client
22
+ def readpartial(maxlen, outbuf = "")
23
+ data = @socket.readpartial(maxlen, outbuf)
24
+ log :read, data
25
+ data
26
+ end
27
+
28
+ # Write data to the client
29
+ def write(string)
30
+ log :write, string
31
+ @socket << string
32
+ end
33
+ alias << write
34
+
35
+ # Close the socket
36
+ def close
37
+ @socket.close
38
+ log :close, "--- #{@ip}:#{@port} (#{@proto}) disconnected\n"
39
+ end
40
+
41
+ # Log the given event
42
+ def log(type, str)
43
+ case type
44
+ when :connect
45
+ @logger << Colors.green(str)
46
+ when :close
47
+ @logger << Colors.red(str)
48
+ when :read
49
+ @logger << Colors.gold(str)
50
+ when :write
51
+ @logger << Colors.white(str)
52
+ else
53
+ raise "unknown event type: #{type.inspect}"
54
+ end
55
+ end
56
+
57
+ module Colors
58
+ module_function
59
+
60
+ def escape(n); "\033[#{n}m"; end
61
+ def reset; escape 0; end
62
+ def color(n); escape "1;#{n}"; end
63
+ def colorize(n, str); "#{color(n)}#{str}#{reset}"; end
64
+
65
+ def green(str); colorize(32, str); end
66
+ def red(str); colorize(31, str); end
67
+ def white(str); colorize(39, str); end
68
+ def gold(str); colorize(33, str); end
69
+ end
70
+ end
71
+ end
data/lib/reel/stream.rb CHANGED
@@ -12,7 +12,7 @@ module Reel
12
12
  def write(data)
13
13
  @socket << data
14
14
  data
15
- rescue Errno::EPIPE
15
+ rescue IOError, Errno::ECONNRESET, Errno::EPIPE
16
16
  raise SocketError, "error writing to socket"
17
17
  end
18
18
  alias :<< :write
@@ -102,7 +102,7 @@ module Reel
102
102
  raise TypeError, "can't render #{@body.class} as a response body"
103
103
  end
104
104
 
105
- @headers = canonicalize_headers(headers)
105
+ @headers = HTTP::Headers.coerce(headers)
106
106
  @version = http_version
107
107
  end
108
108
 
data/lib/reel/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Reel
2
- VERSION = "0.4.0"
3
- CODENAME = "Garbo"
2
+ VERSION = "0.5.0.pre"
3
+ CODENAME = "Bette"
4
4
  end
@@ -79,7 +79,7 @@ module Reel
79
79
  def write(msg)
80
80
  @socket << ::WebSocket::Message.new(msg).to_data
81
81
  msg
82
- rescue Errno::EPIPE
82
+ rescue IOError, Errno::ECONNRESET, Errno::EPIPE
83
83
  cancel_timer!
84
84
  raise SocketError, "error writing to socket"
85
85
  rescue
data/reel.gemspec CHANGED
@@ -18,9 +18,9 @@ Gem::Specification.new do |gem|
18
18
  gem.add_runtime_dependency 'celluloid', '>= 0.15.1'
19
19
  gem.add_runtime_dependency 'celluloid-io', '>= 0.15.0'
20
20
  gem.add_runtime_dependency 'http', '>= 0.5.0'
21
- gem.add_runtime_dependency 'http_parser.rb', '>= 0.6.0.beta.2'
22
- gem.add_runtime_dependency 'websocket_parser', '>= 0.1.4'
21
+ gem.add_runtime_dependency 'http_parser.rb', '>= 0.6.0'
22
+ gem.add_runtime_dependency 'websocket_parser', '>= 0.1.6'
23
23
 
24
24
  gem.add_development_dependency 'rake'
25
- gem.add_development_dependency 'rspec'
25
+ gem.add_development_dependency 'rspec', '>= 2.11.0'
26
26
  end
@@ -0,0 +1,27 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIEgDCCA2igAwIBAgIJAPs+Pcx3Ws69MA0GCSqGSIb3DQEBBQUAMIGGMQswCQYD
3
+ VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5j
4
+ aXNjbzESMBAGA1UEChMJQ2VsbHVsb2lkMRcwFQYDVQQDEw5jYS5leGFtcGxlLmNv
5
+ bTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBsZS5jb20wHhcNMTMxMTA3MjMwMjMz
6
+ WhcNNDEwMzI0MjMwMjMzWjCBhjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlm
7
+ b3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xEjAQBgNVBAoTCUNlbGx1bG9p
8
+ ZDEXMBUGA1UEAxMOY2EuZXhhbXBsZS5jb20xHTAbBgkqhkiG9w0BCQEWDmNhQGV4
9
+ YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA48syWpTE
10
+ uZexHJJKTgfdTA/eXkUEh6QM/NcclLARJVT5YWlfQigOAkSowBTIBlsxiMPPUITY
11
+ kBEbWNz6mlVYehQlxISG6gc1b90S+aj+hWPX9oWvQUrUboQZZtgxZf817MElxP5G
12
+ JAtNKlGGj6gKYyM/4ir8TXRJ9SHta4xeVrrqm7/pdh5uaE3cBAJv0usRK/uQxh1N
13
+ woGAq6iCpwImnjx6SNrs1MoJo/F2nmdEcODaCLTVTY08hp/v+cVPCONMEvuJRUnu
14
+ O7ytR6ym1/3MufHg3Xv6OwnfXqh/czZ6tD+ncH5bAHnmZOvT2OA8y68yxTnIshcT
15
+ wE7x+RBDRMCBhwIDAQABo4HuMIHrMB0GA1UdDgQWBBSqhnwm0V/WWAQcB9xXM7W6
16
+ s2gtrDCBuwYDVR0jBIGzMIGwgBSqhnwm0V/WWAQcB9xXM7W6s2gtrKGBjKSBiTCB
17
+ hjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNh
18
+ biBGcmFuY2lzY28xEjAQBgNVBAoTCUNlbGx1bG9pZDEXMBUGA1UEAxMOY2EuZXhh
19
+ bXBsZS5jb20xHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tggkA+z49zHda
20
+ zr0wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEA0MMwHKw76n3Y+ybJ
21
+ WkOf9Qpu2/FDsQ0aMc5a/Z0cvrEx6xqcNDRmov+ikNClaClgfXG4gb+xWor8Y4fD
22
+ jpyaLL5X3G7ThseDjH6575UT1KjJ0team4XCx6zpLoKzLDW2sM1tAnNAXMGEnZ1R
23
+ HsJQdHuVTVekwuLcnrfnrfm395CLfMaOUaJw4ZsJmKyoHM03/80LNme+bjVJ+vh+
24
+ 1vE2t2c86WprrNQIryseqwz08DAuSPjezuIsSd5sARuOw3ggC3xhEkVJDJY2lIMh
25
+ gxi384M84LBbGjvQdKbdxkWcvfD5hgEva9I8I2yXVyRoQrUWHnVRlL87PUmkRvLT
26
+ HC7SFg==
27
+ -----END CERTIFICATE-----
@@ -0,0 +1,27 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIIEpAIBAAKCAQEA48syWpTEuZexHJJKTgfdTA/eXkUEh6QM/NcclLARJVT5YWlf
3
+ QigOAkSowBTIBlsxiMPPUITYkBEbWNz6mlVYehQlxISG6gc1b90S+aj+hWPX9oWv
4
+ QUrUboQZZtgxZf817MElxP5GJAtNKlGGj6gKYyM/4ir8TXRJ9SHta4xeVrrqm7/p
5
+ dh5uaE3cBAJv0usRK/uQxh1NwoGAq6iCpwImnjx6SNrs1MoJo/F2nmdEcODaCLTV
6
+ TY08hp/v+cVPCONMEvuJRUnuO7ytR6ym1/3MufHg3Xv6OwnfXqh/czZ6tD+ncH5b
7
+ AHnmZOvT2OA8y68yxTnIshcTwE7x+RBDRMCBhwIDAQABAoIBAHQ038434JfxW6gA
8
+ tSlTd8Bqw/0BZosv1HRT5L+xhj2uOL5J/A+K0YK0tgWvVE9xzDZB9gvUiYoNQA84
9
+ RBvheA5nItE67nyLCuazOA/m91jjE3QuxLYhT3fFqhO+LI0lAcRy0CrLsMqIfWge
10
+ SPAWQJ5MiDV/ylBVB7mnAjCAXkwNfi3LYuoBa5tX9HmN7kDFpqN0KyFav/3Bsij5
11
+ JUwxAHjWbSH61TLjA4WpvyKTARW3uhInjwj+CMRszfyH//h7lwFba5YbebXjfdFP
12
+ PsOS8lc/puqrjf7ZS/lPcL8xTElrcDr5oMtOBEoU+y2W+Gz5tpNQHCRIpq71CwEv
13
+ /VdicoECgYEA/CyGXfVv3GULb4BQbKJqIKa17uv9nVDxc3VUoelhN40WshKOt4zd
14
+ 03x0or1f/LymEijj2K/rKt6T1kbKIrw1FFG7HiFdX1AUBkP4q1gDBoGohSsOdcRQ
15
+ pFIdz9ViOn5F5+iJrRT3yDhJAL0kG/YSfqwsaafQqPzpgY9Ig3uIb0cCgYEA5z/5
16
+ 4tBKT6ps0ppLyK8NqpRtSK5ZWiy+N4kbNKEgaXOkRxZUXJBlRGoMe/E+wDLHsDza
17
+ X3jwkFUCXXRM2PihwYWdZjCWo6ktorZzNd0fceAXkgeCi+FigfTweqe2zjq1s8BU
18
+ FrNGo/06lC2JWKHVbke5hcBeyjRVPp/8Jnzm+8ECgYAG8/dUeeL2sbaKAYC2Lhg9
19
+ BDu59bnNb6DorRCDUlsC3BoHGOnkd7baEPFqV0xhPJZbo9L8c4VJbk+nNdZ29LeF
20
+ 8ub04rifWybiMVeW6dtTf5m06kYAy0Pp8/WseFa4BClLRqcdJZnbZGnm4lAvkS5b
21
+ XcXvt9fSAP8zOk8miO5vGwKBgQDbBuxumKwZwqip3Ly0yqDeFRFhSsmUsFZGEZV0
22
+ BrzFRGOvdQXYWmegIfXLGtc9gZtDYI/Q56KqgenojDQROYUz35MSbCjxwFZaDAcZ
23
+ WGPlHsQUawqJ5KLBxjZTZjCuKktZgmviyFC7GCj4mhzBlx6pAkRE28ysJl8rHqrb
24
+ 5Wd9wQKBgQCX6cLNz8HzBzJDBcZN/0ipqdSSNj4GCVaZCD2S+2uqAvwEud/0slRo
25
+ 1Pgi9o9BXSq6TGnXX6zcoWWXbMnlC2Oq61FFI+Q0+DnHxwwhasrULKTmeHzLN84s
26
+ QMUVu3CbaokYg2VBKPiyW2sLE3KOBViO1cQFBFvcPIMwoB9BzeG6ig==
27
+ -----END RSA PRIVATE KEY-----
@@ -1,22 +1,83 @@
1
+ Certificate:
2
+ Data:
3
+ Version: 3 (0x2)
4
+ Serial Number: 1 (0x1)
5
+ Signature Algorithm: sha1WithRSAEncryption
6
+ Issuer: C=US, ST=California, L=San Francisco, O=Celluloid, CN=ca.example.com/emailAddress=ca@example.com
7
+ Validity
8
+ Not Before: Nov 7 23:23:12 2013 GMT
9
+ Not After : Nov 7 23:23:12 2014 GMT
10
+ Subject: C=US, ST=California, O=Celluloid, CN=client.example.com/emailAddress=client@example.com
11
+ Subject Public Key Info:
12
+ Public Key Algorithm: rsaEncryption
13
+ RSA Public Key: (2048 bit)
14
+ Modulus (2048 bit):
15
+ 00:d5:eb:3c:e9:90:02:17:e0:58:a3:9f:2b:57:f3:
16
+ 81:a0:1d:bf:21:61:d3:49:02:7f:bd:83:9e:d7:1a:
17
+ ba:ad:00:7e:81:94:ba:00:34:59:78:9f:ff:b2:9c:
18
+ 44:30:06:a9:6b:36:77:ec:b4:fa:df:ee:c3:de:cf:
19
+ 2b:67:b5:25:72:b9:f4:84:f8:b1:94:18:12:40:fe:
20
+ 3c:a3:40:23:1c:11:ef:3e:e1:b7:ce:0b:66:61:0a:
21
+ 9b:e7:23:67:4a:34:ac:2c:98:cf:83:c9:6b:3f:3d:
22
+ 59:7b:5c:40:19:17:63:f8:89:0f:1e:18:b5:45:8e:
23
+ 98:7e:28:0f:c3:ef:d7:07:90:87:86:b7:81:44:03:
24
+ 8c:49:5a:a2:9f:f8:a8:df:b7:1a:35:70:1a:8b:c7:
25
+ 67:54:8a:e7:11:2f:bb:6f:6b:78:a7:80:0a:98:4a:
26
+ cf:e2:f3:68:ca:2c:69:63:ed:f7:51:33:2b:4e:c7:
27
+ ce:cd:86:cd:f9:45:6a:6e:eb:a9:7b:86:fa:5e:b7:
28
+ 1d:ed:db:05:36:a1:b2:8e:cc:a8:52:e3:27:1a:67:
29
+ 60:29:b4:40:cd:5c:a6:81:4d:0e:65:7a:34:91:c4:
30
+ 50:42:a5:84:2d:aa:69:1d:d1:b3:06:fd:3e:59:7d:
31
+ 70:b8:e5:ac:63:f5:ad:ab:8f:c0:0a:65:cb:7e:98:
32
+ b0:b3
33
+ Exponent: 65537 (0x10001)
34
+ X509v3 extensions:
35
+ X509v3 Basic Constraints:
36
+ CA:FALSE
37
+ Netscape Comment:
38
+ OpenSSL Generated Certificate
39
+ X509v3 Subject Key Identifier:
40
+ 74:EA:7C:F5:79:ED:5A:ED:B3:95:13:1C:5A:1A:C8:2E:63:12:EF:5D
41
+ X509v3 Authority Key Identifier:
42
+ keyid:AA:86:7C:26:D1:5F:D6:58:04:1C:07:DC:57:33:B5:BA:B3:68:2D:AC
43
+
44
+ Signature Algorithm: sha1WithRSAEncryption
45
+ 38:9d:aa:2c:40:cf:a2:79:0e:17:a1:4b:07:0e:8f:c9:8b:5f:
46
+ 8c:d4:34:14:00:e0:df:7d:9a:a4:d2:ec:b2:3f:ca:a4:e5:31:
47
+ 03:17:74:3e:03:56:69:3d:d0:c4:fc:e9:11:62:63:3d:02:24:
48
+ 37:f0:50:bf:c1:4e:a8:6f:e3:7d:24:16:9e:2d:cf:93:f3:c2:
49
+ ba:4a:76:f4:09:d9:44:44:80:19:5a:16:f5:b4:8c:13:bf:0a:
50
+ 19:e9:2b:6f:e0:eb:d6:8a:f3:b3:1d:ba:46:51:7c:44:df:11:
51
+ af:59:a1:2b:d4:58:6d:a8:28:47:26:7a:af:84:30:0f:a0:91:
52
+ 0b:94:f0:2a:a5:9e:2b:19:af:0c:16:34:fd:49:0c:ee:8d:31:
53
+ 00:9f:b8:00:dc:9b:9f:38:b0:c0:c1:37:37:96:9a:18:07:b0:
54
+ c6:50:ff:28:3b:f7:84:8e:d5:b3:df:97:4f:91:c0:91:a4:af:
55
+ f8:a0:ef:83:0c:37:1b:2c:aa:57:66:1c:cf:89:28:5e:b9:33:
56
+ ab:87:35:78:e7:10:64:90:22:35:e8:02:cf:61:71:52:5a:84:
57
+ 3a:1e:8a:71:cb:c2:63:32:c4:e8:d6:1b:ff:d5:18:18:50:b7:
58
+ c6:8c:c2:32:eb:7e:5e:44:b0:e2:03:5d:30:07:6b:ae:09:83:
59
+ a3:26:f1:78
1
60
  -----BEGIN CERTIFICATE-----
2
- MIIDmjCCAoICCQDwZ8yE/0n4PjANBgkqhkiG9w0BAQUFADCBjjELMAkGA1UEBhMC
3
- VVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28x
4
- EjAQBgNVBAoTCUNlbGx1bG9pZDEbMBkGA1UEAxMSY2xpZW50LmV4YW1wbGUuY29t
5
- MSEwHwYJKoZIhvcNAQkBFhJjbGllbnRAZXhhbXBsZS5jb20wHhcNMTIxMTI1MTkx
6
- NjI2WhcNMjIxMTIzMTkxNjI2WjCBjjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNh
7
- bGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xEjAQBgNVBAoTCUNlbGx1
8
- bG9pZDEbMBkGA1UEAxMSY2xpZW50LmV4YW1wbGUuY29tMSEwHwYJKoZIhvcNAQkB
9
- FhJjbGllbnRAZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
10
- AoIBAQDV6zzpkAIX4FijnytX84GgHb8hYdNJAn+9g57XGrqtAH6BlLoANFl4n/+y
11
- nEQwBqlrNnfstPrf7sPezytntSVyufSE+LGUGBJA/jyjQCMcEe8+4bfOC2ZhCpvn
12
- I2dKNKwsmM+DyWs/PVl7XEAZF2P4iQ8eGLVFjph+KA/D79cHkIeGt4FEA4xJWqKf
13
- +Kjftxo1cBqLx2dUiucRL7tva3ingAqYSs/i82jKLGlj7fdRMytOx87Nhs35RWpu
14
- 66l7hvpetx3t2wU2obKOzKhS4ycaZ2AptEDNXKaBTQ5lejSRxFBCpYQtqmkd0bMG
15
- /T5ZfXC45axj9a2rj8AKZct+mLCzAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAHzr
16
- b4VTktAi+8baGRJCXupt0Ari8ffoWhsYerELFLQF7K2sluxOqCsGEEF21e99fZxP
17
- lisLi0DIQ7cNlOGjRJ3xaydE74Fsry3xBNKoR8I7OMr9VFsrC54tc0x7NQ7bRHy6
18
- kCjSwKN4I2KWJjQ8yf8mIalmUKOmb/hirzna8io4CiDeJGZ1XNAQ9dl1RHRW442G
19
- GTu2ofAtU8TlzilZyclMY/lN7whw7sKP+pPr6fpAOJZsR64IzbBcWHHjJhx70XOx
20
- jnd5FB1oXnuupgPqEKmatSCytrue8GTkanB8VZ6+Zd/4XgTkie3UtCZW8R+NL/Lo
21
- us/+Ks3WIDyYdPSPnbE=
61
+ MIID8zCCAtugAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhjELMAkGA1UEBhMCVVMx
62
+ EzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xEjAQ
63
+ BgNVBAoTCUNlbGx1bG9pZDEXMBUGA1UEAxMOY2EuZXhhbXBsZS5jb20xHTAbBgkq
64
+ hkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tMB4XDTEzMTEwNzIzMjMxMloXDTE0MTEw
65
+ NzIzMjMxMlowdjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQ
66
+ BgNVBAoTCUNlbGx1bG9pZDEbMBkGA1UEAxMSY2xpZW50LmV4YW1wbGUuY29tMSEw
67
+ HwYJKoZIhvcNAQkBFhJjbGllbnRAZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEB
68
+ AQUAA4IBDwAwggEKAoIBAQDV6zzpkAIX4FijnytX84GgHb8hYdNJAn+9g57XGrqt
69
+ AH6BlLoANFl4n/+ynEQwBqlrNnfstPrf7sPezytntSVyufSE+LGUGBJA/jyjQCMc
70
+ Ee8+4bfOC2ZhCpvnI2dKNKwsmM+DyWs/PVl7XEAZF2P4iQ8eGLVFjph+KA/D79cH
71
+ kIeGt4FEA4xJWqKf+Kjftxo1cBqLx2dUiucRL7tva3ingAqYSs/i82jKLGlj7fdR
72
+ MytOx87Nhs35RWpu66l7hvpetx3t2wU2obKOzKhS4ycaZ2AptEDNXKaBTQ5lejSR
73
+ xFBCpYQtqmkd0bMG/T5ZfXC45axj9a2rj8AKZct+mLCzAgMBAAGjezB5MAkGA1Ud
74
+ EwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmlj
75
+ YXRlMB0GA1UdDgQWBBR06nz1ee1a7bOVExxaGsguYxLvXTAfBgNVHSMEGDAWgBSq
76
+ hnwm0V/WWAQcB9xXM7W6s2gtrDANBgkqhkiG9w0BAQUFAAOCAQEAOJ2qLEDPonkO
77
+ F6FLBw6PyYtfjNQ0FADg332apNLssj/KpOUxAxd0PgNWaT3QxPzpEWJjPQIkN/BQ
78
+ v8FOqG/jfSQWni3Pk/PCukp29AnZRESAGVoW9bSME78KGekrb+Dr1orzsx26RlF8
79
+ RN8Rr1mhK9RYbagoRyZ6r4QwD6CRC5TwKqWeKxmvDBY0/UkM7o0xAJ+4ANybnziw
80
+ wME3N5aaGAewxlD/KDv3hI7Vs9+XT5HAkaSv+KDvgww3GyyqV2Ycz4koXrkzq4c1
81
+ eOcQZJAiNegCz2FxUlqEOh6KccvCYzLE6NYb/9UYGFC3xozCMut+XkSw4gNdMAdr
82
+ rgmDoybxeA==
22
83
  -----END CERTIFICATE-----
@@ -0,0 +1,22 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDmjCCAoICCQDwZ8yE/0n4PjANBgkqhkiG9w0BAQUFADCBjjELMAkGA1UEBhMC
3
+ VVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28x
4
+ EjAQBgNVBAoTCUNlbGx1bG9pZDEbMBkGA1UEAxMSY2xpZW50LmV4YW1wbGUuY29t
5
+ MSEwHwYJKoZIhvcNAQkBFhJjbGllbnRAZXhhbXBsZS5jb20wHhcNMTIxMTI1MTkx
6
+ NjI2WhcNMjIxMTIzMTkxNjI2WjCBjjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNh
7
+ bGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xEjAQBgNVBAoTCUNlbGx1
8
+ bG9pZDEbMBkGA1UEAxMSY2xpZW50LmV4YW1wbGUuY29tMSEwHwYJKoZIhvcNAQkB
9
+ FhJjbGllbnRAZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
10
+ AoIBAQDV6zzpkAIX4FijnytX84GgHb8hYdNJAn+9g57XGrqtAH6BlLoANFl4n/+y
11
+ nEQwBqlrNnfstPrf7sPezytntSVyufSE+LGUGBJA/jyjQCMcEe8+4bfOC2ZhCpvn
12
+ I2dKNKwsmM+DyWs/PVl7XEAZF2P4iQ8eGLVFjph+KA/D79cHkIeGt4FEA4xJWqKf
13
+ +Kjftxo1cBqLx2dUiucRL7tva3ingAqYSs/i82jKLGlj7fdRMytOx87Nhs35RWpu
14
+ 66l7hvpetx3t2wU2obKOzKhS4ycaZ2AptEDNXKaBTQ5lejSRxFBCpYQtqmkd0bMG
15
+ /T5ZfXC45axj9a2rj8AKZct+mLCzAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAHzr
16
+ b4VTktAi+8baGRJCXupt0Ari8ffoWhsYerELFLQF7K2sluxOqCsGEEF21e99fZxP
17
+ lisLi0DIQ7cNlOGjRJ3xaydE74Fsry3xBNKoR8I7OMr9VFsrC54tc0x7NQ7bRHy6
18
+ kCjSwKN4I2KWJjQ8yf8mIalmUKOmb/hirzna8io4CiDeJGZ1XNAQ9dl1RHRW442G
19
+ GTu2ofAtU8TlzilZyclMY/lN7whw7sKP+pPr6fpAOJZsR64IzbBcWHHjJhx70XOx
20
+ jnd5FB1oXnuupgPqEKmatSCytrue8GTkanB8VZ6+Zd/4XgTkie3UtCZW8R+NL/Lo
21
+ us/+Ks3WIDyYdPSPnbE=
22
+ -----END CERTIFICATE-----
@@ -1,22 +1,82 @@
1
+ Certificate:
2
+ Data:
3
+ Version: 3 (0x2)
4
+ Serial Number: 3 (0x3)
5
+ Signature Algorithm: sha1WithRSAEncryption
6
+ Issuer: C=US, ST=California, L=San Francisco, O=Celluloid, CN=ca.example.com/emailAddress=ca@example.com
7
+ Validity
8
+ Not Before: Nov 7 23:33:55 2013 GMT
9
+ Not After : Nov 7 23:33:55 2014 GMT
10
+ Subject: C=US, ST=California, O=Celluloid, CN=127.0.0.1/emailAddress=server@example.com
11
+ Subject Public Key Info:
12
+ Public Key Algorithm: rsaEncryption
13
+ RSA Public Key: (2048 bit)
14
+ Modulus (2048 bit):
15
+ 00:a9:2e:cd:d7:83:4d:11:b6:81:b8:f9:22:9a:68:
16
+ d7:f0:e8:3b:de:f5:dd:0a:92:0d:02:35:f5:3c:02:
17
+ cc:4e:81:32:14:d5:0b:bc:b3:e6:f3:2a:4a:9e:eb:
18
+ a3:5f:09:ae:93:f1:53:e9:93:d5:5b:22:51:76:38:
19
+ d7:60:63:8a:3c:9a:e5:75:ab:e9:92:ea:3d:87:0c:
20
+ 0b:56:3e:20:e3:3f:ef:58:3b:01:9f:fc:34:f7:2e:
21
+ 14:9b:83:c9:3e:6a:52:f6:72:a7:bb:07:55:cd:52:
22
+ c3:45:12:f4:3e:c9:02:e5:8f:d3:16:29:be:e7:6d:
23
+ 80:cc:f1:aa:9d:bf:8e:8a:1a:80:e3:f6:ff:6b:7e:
24
+ 6e:10:88:ac:08:07:ab:bf:2a:84:06:db:66:05:ee:
25
+ c4:f8:3b:8e:23:53:fb:b6:d3:17:26:de:b5:75:12:
26
+ 58:34:80:2f:d4:3f:f6:2a:9e:e3:0f:09:96:1c:2b:
27
+ f6:7d:bd:81:ad:0c:9e:86:f0:e6:03:70:f6:52:64:
28
+ 17:64:aa:57:df:85:80:6c:b1:28:f7:47:bb:13:0a:
29
+ aa:21:e2:6b:34:f2:e9:1c:1b:27:1b:bd:43:be:71:
30
+ 6a:cf:2a:79:b2:4a:c1:9a:09:8b:46:92:9e:d0:b0:
31
+ 7d:5e:73:b4:06:03:4d:61:64:bd:b2:2f:c0:ae:24:
32
+ c5:1b
33
+ Exponent: 65537 (0x10001)
34
+ X509v3 extensions:
35
+ X509v3 Basic Constraints:
36
+ CA:FALSE
37
+ Netscape Comment:
38
+ OpenSSL Generated Certificate
39
+ X509v3 Subject Key Identifier:
40
+ B3:4D:7D:A4:A3:AC:8D:B7:7A:F6:EC:6E:25:60:CE:64:D2:2E:AC:AC
41
+ X509v3 Authority Key Identifier:
42
+ keyid:AA:86:7C:26:D1:5F:D6:58:04:1C:07:DC:57:33:B5:BA:B3:68:2D:AC
43
+
44
+ Signature Algorithm: sha1WithRSAEncryption
45
+ 2b:fa:71:6f:e8:27:af:93:b8:2c:15:53:9d:00:15:25:0d:db:
46
+ 33:ac:83:a7:a6:10:b0:d3:ca:7c:57:ae:d9:ca:4f:92:92:fe:
47
+ bd:3e:7d:59:af:33:59:1e:01:31:7c:01:7f:43:66:f3:96:84:
48
+ d6:20:e2:6d:69:61:eb:28:e9:b4:0c:9d:59:76:04:44:a1:0e:
49
+ 76:7e:b5:d8:a8:30:7c:2a:82:63:ee:dc:34:56:26:e7:08:65:
50
+ 7b:0e:31:33:f9:06:4a:51:4e:1a:e5:1a:5e:51:3c:d0:00:b2:
51
+ 6a:6d:3c:c3:80:77:34:1a:0d:51:20:fc:5b:0b:e3:68:a0:3e:
52
+ 72:10:b2:f7:7e:5d:a3:40:96:46:fe:e6:24:59:57:30:ab:6e:
53
+ 00:e4:eb:92:87:23:8e:17:d7:03:bf:59:04:82:52:05:76:fb:
54
+ d3:da:a2:a0:05:41:97:71:6d:29:04:ad:1a:f3:49:38:dc:8b:
55
+ cb:34:fe:5b:b4:0b:c4:18:e5:52:a7:20:d6:2d:6a:b0:cd:6f:
56
+ 17:87:8a:4f:6b:8f:43:50:ab:7b:2c:db:a3:be:09:24:a9:64:
57
+ 6e:c4:13:16:e9:83:bf:a3:45:a9:f1:27:85:ce:f7:70:0c:37:
58
+ 2f:25:8a:1e:b0:76:70:69:83:d2:ec:69:aa:ee:86:7e:4c:c9:
59
+ 71:d7:5c:37
1
60
  -----BEGIN CERTIFICATE-----
2
- MIIDmjCCAoICCQD+dJ16wNIKnzANBgkqhkiG9w0BAQUFADCBjjELMAkGA1UEBhMC
3
- VVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28x
4
- EjAQBgNVBAoTCUNlbGx1bG9pZDEbMBkGA1UEAxMSc2VydmVyLmV4YW1wbGUuY29t
5
- MSEwHwYJKoZIhvcNAQkBFhJzZXJ2ZXJAZXhhbXBsZS5jb20wHhcNMTIxMTI1MTkx
6
- NjAwWhcNMjIxMTIzMTkxNjAwWjCBjjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNh
7
- bGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xEjAQBgNVBAoTCUNlbGx1
8
- bG9pZDEbMBkGA1UEAxMSc2VydmVyLmV4YW1wbGUuY29tMSEwHwYJKoZIhvcNAQkB
9
- FhJzZXJ2ZXJAZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
10
- AoIBAQCpLs3Xg00RtoG4+SKaaNfw6Dve9d0Kkg0CNfU8AsxOgTIU1Qu8s+bzKkqe
11
- 66NfCa6T8VPpk9VbIlF2ONdgY4o8muV1q+mS6j2HDAtWPiDjP+9YOwGf/DT3LhSb
12
- g8k+alL2cqe7B1XNUsNFEvQ+yQLlj9MWKb7nbYDM8aqdv46KGoDj9v9rfm4QiKwI
13
- B6u/KoQG22YF7sT4O44jU/u20xcm3rV1Elg0gC/UP/YqnuMPCZYcK/Z9vYGtDJ6G
14
- 8OYDcPZSZBdkqlffhYBssSj3R7sTCqoh4ms08ukcGycbvUO+cWrPKnmySsGaCYtG
15
- kp7QsH1ec7QGA01hZL2yL8CuJMUbAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBABE4
16
- gYVSdC87NhpA49k0vcLLU7v7mU3a3no/vu1CIqQxzx8/xh26Qi3aGb1s9MgHpF2Z
17
- NiB1irXER2tyz/F3qCi8OCo7eNsndmDjj4GnkBjEPTtqRxH9imRWw4bJyqwqFHcu
18
- 1kczCZa+2VFQFEL4ErGycPFKM59ppTcJ0IxbK7PCGzO75TRQoAl52+3Aob+oejPP
19
- qFbiqNlV1T3EKa5yLdvOC5sLrEcfm3iMxmOtNVzp9OBhjXfm8Q1zgYs4VyJXzLMK
20
- wf956w2YEbpTAAzNc53zly/Jhr4MnFsa9Mn1oYp9Rfjzw/qJtXw+a3PtEKrO4XNe
21
- TsKHsAkj8XvUrhliiNQ=
61
+ MIID6jCCAtKgAwIBAgIBAzANBgkqhkiG9w0BAQUFADCBhjELMAkGA1UEBhMCVVMx
62
+ EzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xEjAQ
63
+ BgNVBAoTCUNlbGx1bG9pZDEXMBUGA1UEAxMOY2EuZXhhbXBsZS5jb20xHTAbBgkq
64
+ hkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tMB4XDTEzMTEwNzIzMzM1NVoXDTE0MTEw
65
+ NzIzMzM1NVowbTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQ
66
+ BgNVBAoTCUNlbGx1bG9pZDESMBAGA1UEAxMJMTI3LjAuMC4xMSEwHwYJKoZIhvcN
67
+ AQkBFhJzZXJ2ZXJAZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
68
+ ggEKAoIBAQCpLs3Xg00RtoG4+SKaaNfw6Dve9d0Kkg0CNfU8AsxOgTIU1Qu8s+bz
69
+ Kkqe66NfCa6T8VPpk9VbIlF2ONdgY4o8muV1q+mS6j2HDAtWPiDjP+9YOwGf/DT3
70
+ LhSbg8k+alL2cqe7B1XNUsNFEvQ+yQLlj9MWKb7nbYDM8aqdv46KGoDj9v9rfm4Q
71
+ iKwIB6u/KoQG22YF7sT4O44jU/u20xcm3rV1Elg0gC/UP/YqnuMPCZYcK/Z9vYGt
72
+ DJ6G8OYDcPZSZBdkqlffhYBssSj3R7sTCqoh4ms08ukcGycbvUO+cWrPKnmySsGa
73
+ CYtGkp7QsH1ec7QGA01hZL2yL8CuJMUbAgMBAAGjezB5MAkGA1UdEwQCMAAwLAYJ
74
+ YIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1Ud
75
+ DgQWBBSzTX2ko6yNt3r27G4lYM5k0i6srDAfBgNVHSMEGDAWgBSqhnwm0V/WWAQc
76
+ B9xXM7W6s2gtrDANBgkqhkiG9w0BAQUFAAOCAQEAK/pxb+gnr5O4LBVTnQAVJQ3b
77
+ M6yDp6YQsNPKfFeu2cpPkpL+vT59Wa8zWR4BMXwBf0Nm85aE1iDibWlh6yjptAyd
78
+ WXYERKEOdn612KgwfCqCY+7cNFYm5whlew4xM/kGSlFOGuUaXlE80ACyam08w4B3
79
+ NBoNUSD8WwvjaKA+chCy935do0CWRv7mJFlXMKtuAOTrkocjjhfXA79ZBIJSBXb7
80
+ 09qioAVBl3FtKQStGvNJONyLyzT+W7QLxBjlUqcg1i1qsM1vF4eKT2uPQ1Creyzb
81
+ o74JJKlkbsQTFumDv6NFqfEnhc73cAw3LyWKHrB2cGmD0uxpqu6GfkzJcddcNw==
22
82
  -----END CERTIFICATE-----
@@ -73,12 +73,8 @@ describe Reel::Connection do
73
73
  end
74
74
  end
75
75
 
76
- it "streams responses when transfer-encoding is chunked" do
77
- with_socket_pair do |client, peer|
78
- connection = Reel::Connection.new(peer)
79
- client << ExampleRequest.new.to_s
80
- request = connection.request
81
-
76
+ context "streams responses when transfer-encoding is chunked" do
77
+ def test_chunked_response(request, client)
82
78
  # Sending transfer_encoding chunked without a body enables streaming mode
83
79
  request.respond :ok, :transfer_encoding => :chunked
84
80
 
@@ -86,13 +82,13 @@ describe Reel::Connection do
86
82
  request << "Hello"
87
83
  request << "World"
88
84
  request.finish_response # Write trailer and reset connection to header mode
89
- connection.close
90
85
 
91
86
  response = ""
92
87
 
93
88
  begin
94
89
  while chunk = client.readpartial(4096)
95
90
  response << chunk
91
+ break if response =~ /0\r\n\r\n$/
96
92
  end
97
93
  rescue EOFError
98
94
  end
@@ -101,19 +97,62 @@ describe Reel::Connection do
101
97
  fixture = "5#{crlf}Hello#{crlf}5#{crlf}World#{crlf}0#{crlf*2}"
102
98
  response[(response.length - fixture.length)..-1].should eq fixture
103
99
  end
104
- end
100
+
101
+ it "with keep-alive" do
102
+ with_socket_pair do |client, peer|
103
+ connection = Reel::Connection.new(peer)
104
+ client << ExampleRequest.new.to_s
105
+ request = connection.request
106
+
107
+ test_chunked_response(request, client)
108
+ connection.close
109
+ end
110
+ end
111
+
112
+ it "without keep-alive" do
113
+ with_socket_pair do |client, peer|
114
+ connection = Reel::Connection.new(peer)
115
+ client << ExampleRequest.new.tap{ |r|
116
+ r['Connection'] = 'close'
117
+ }.to_s
118
+ request = connection.request
119
+
120
+ test_chunked_response(request, client)
121
+ connection.close
122
+ end
123
+ end
124
+
125
+ it "with pipelined requests" do
126
+ with_socket_pair do |client, peer|
127
+ connection = Reel::Connection.new(peer)
128
+
129
+ 2.times do
130
+ client << ExampleRequest.new.to_s
131
+ end
132
+ client << ExampleRequest.new.tap { |r|
133
+ r['Connection'] = 'close'
134
+ }.to_s
105
135
 
136
+ 3.times do
137
+ request = connection.request
138
+ test_chunked_response(request, client)
139
+ end
140
+ connection.close
141
+ end
142
+ end
143
+ end
144
+
106
145
  it "reset the request after a response is sent" do
107
146
  with_socket_pair do |client, peer|
108
147
  connection = Reel::Connection.new(peer)
109
148
  example_request = ExampleRequest.new(:get, "/", "1.1", {'Connection' => 'close'})
110
149
  client << example_request
111
150
 
112
- connection.request.should_not be_false
151
+ connection.request.should_not be_nil
113
152
 
114
153
  connection.respond :ok, "Response sent"
115
154
 
116
- connection.request.should be_false
155
+ connection.request.should be_nil
117
156
  end
118
157
  end
119
158
 
@@ -127,7 +166,7 @@ describe Reel::Connection do
127
166
 
128
167
  expect do
129
168
  2.times { request = connection.request }
130
- end.to raise_error(Reel::Connection::StateError)
169
+ end.to raise_error(Reel::StateError)
131
170
  end
132
171
  end
133
172