httpkit 0.6.0.pre.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/.gitignore +7 -0
  2. data/.rspec +3 -0
  3. data/.travis.yml +15 -0
  4. data/.yardopts +2 -0
  5. data/Gemfile +19 -0
  6. data/Gemfile.devtools +67 -0
  7. data/Procfile +1 -0
  8. data/README.md +66 -0
  9. data/Rakefile +5 -0
  10. data/UNLICENSE +24 -0
  11. data/config/devtools.yml +2 -0
  12. data/config/flay.yml +3 -0
  13. data/config/flog.yml +2 -0
  14. data/config/mutant.yml +3 -0
  15. data/config/reek.yml +114 -0
  16. data/config/rubocop.yml +56 -0
  17. data/config/yardstick.yml +2 -0
  18. data/examples/echo_server.rb +36 -0
  19. data/examples/getting_started.rb +34 -0
  20. data/httpkit.gemspec +27 -0
  21. data/lib/httpkit/body.rb +67 -0
  22. data/lib/httpkit/client/keep_alive.rb +10 -0
  23. data/lib/httpkit/client/timeouts.rb +14 -0
  24. data/lib/httpkit/client.rb +94 -0
  25. data/lib/httpkit/connection/eventmachine.rb +72 -0
  26. data/lib/httpkit/connection/status.rb +28 -0
  27. data/lib/httpkit/promise.rb +19 -0
  28. data/lib/httpkit/request.rb +19 -0
  29. data/lib/httpkit/response.rb +110 -0
  30. data/lib/httpkit/serializer/encoding.rb +43 -0
  31. data/lib/httpkit/serializer.rb +75 -0
  32. data/lib/httpkit/server/keep_alive.rb +58 -0
  33. data/lib/httpkit/server/timeouts.rb +13 -0
  34. data/lib/httpkit/server.rb +62 -0
  35. data/lib/httpkit/support/handler_manager.rb +25 -0
  36. data/lib/httpkit/support/message.rb +66 -0
  37. data/lib/httpkit/version.rb +5 -0
  38. data/lib/httpkit.rb +49 -0
  39. data/spec/integration/error_handling_spec.rb +76 -0
  40. data/spec/integration/keep_alive_spec.rb +101 -0
  41. data/spec/integration/smoke_spec.rb +21 -0
  42. data/spec/integration/streaming_spec.rb +57 -0
  43. data/spec/integration/timeouts_spec.rb +82 -0
  44. data/spec/shared/integration/server_client_pair.rb +29 -0
  45. data/spec/spec_helper.rb +45 -0
  46. data/spec/support/handler.rb +48 -0
  47. data/spec/support/helper.rb +70 -0
  48. data/spec/unit/client_spec.rb +230 -0
  49. data/spec/unit/connection/eventmachine_spec.rb +211 -0
  50. data/spec/unit/connection/status_spec.rb +83 -0
  51. data/spec/unit/httpkit_spec.rb +41 -0
  52. data/spec/unit/promise_spec.rb +56 -0
  53. data/spec/unit/request_spec.rb +35 -0
  54. data/spec/unit/response_spec.rb +108 -0
  55. data/spec/unit/server/keep_alive_spec.rb +69 -0
  56. data/spec/unit/server_spec.rb +128 -0
  57. data/spec/unit/support/handler_manager_spec.rb +21 -0
  58. data/spec/unit/support/message_spec.rb +115 -0
  59. metadata +190 -0
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ *.gem
2
+ .bundle/
3
+ coverage/
4
+ doc/
5
+ .yardoc/
6
+ measurements/
7
+ Gemfile.lock
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --order rand
2
+ --color
3
+ --format Fuubar
data/.travis.yml ADDED
@@ -0,0 +1,15 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - jruby
6
+ - rbx
7
+ - ruby-head
8
+ - jruby-head
9
+ matrix:
10
+ allow_failures:
11
+ - rvm: jruby
12
+ - rvm: ruby-head
13
+ - rvm: jruby-head
14
+ fast_finish: true
15
+ script: bundle exec rake -t ci:metrics spec:integration
data/.yardopts ADDED
@@ -0,0 +1,2 @@
1
+ - UNLICENSE
2
+ - examples/*
data/Gemfile ADDED
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
6
+
7
+ gem 'devtools', git: 'https://github.com/rom-rb/devtools.git'
8
+ gem 'fuubar', git: 'https://github.com/lgierth/fuubar.git',
9
+ ref: 'static-percentage'
10
+ gem 'awesome_print'
11
+
12
+ platform :rbx do
13
+ gem 'rubysl-fiber', '~> 2.0'
14
+ gem 'rubysl-weakref', '~> 2.0'
15
+ gem 'rubinius', '~> 2.0'
16
+ end
17
+
18
+ # Added by devtools
19
+ eval_gemfile 'Gemfile.devtools'
data/Gemfile.devtools ADDED
@@ -0,0 +1,67 @@
1
+ # encoding: utf-8
2
+
3
+ group :development do
4
+ gem 'rake', '~> 10.1.0'
5
+ gem 'rspec', '~> 2.14.1'
6
+ gem 'yard', '~> 0.8.7'
7
+
8
+ platform :rbx do
9
+ gem 'rubysl-singleton', '~> 2.0.0'
10
+ end
11
+ end
12
+
13
+ group :yard do
14
+ gem 'kramdown', '~> 1.2.0'
15
+ end
16
+
17
+ group :guard do
18
+ gem 'guard', '~> 2.2.4'
19
+ gem 'guard-bundler', '~> 2.0.0'
20
+ gem 'guard-rspec', '~> 4.0.4'
21
+ gem 'guard-rubocop', '~> 1.0.0'
22
+
23
+ # file system change event handling
24
+ gem 'listen', '~> 2.2.0'
25
+ gem 'rb-fchange', '~> 0.0.6', require: false
26
+ gem 'rb-fsevent', '~> 0.9.3', require: false
27
+ gem 'rb-inotify', '~> 0.9.0', require: false
28
+
29
+ # notification handling
30
+ gem 'libnotify', '~> 0.8.0', require: false
31
+ gem 'rb-notifu', '~> 0.0.4', require: false
32
+ gem 'terminal-notifier-guard', '~> 1.5.3', require: false
33
+ end
34
+
35
+ group :metrics do
36
+ gem 'coveralls', '~> 0.7.0'
37
+ gem 'flay', '~> 2.4.0'
38
+ gem 'flog', '~> 4.2.0'
39
+ gem 'reek', '~> 1.3.2'
40
+ gem 'rubocop', '~> 0.15.0'
41
+ gem 'simplecov', '~> 0.8.2'
42
+ gem 'yardstick', '~> 0.9.7', git: 'https://github.com/dkubb/yardstick.git'
43
+
44
+ platforms :ruby_19, :ruby_20 do
45
+ gem 'mutant', '~> 0.3.0.rc3', git: 'https://github.com/mbj/mutant.git'
46
+ gem 'unparser', '~> 0.1.5', git: 'https://github.com/mbj/unparser.git'
47
+ gem 'yard-spellcheck', '~> 0.1.5'
48
+ end
49
+
50
+ platform :rbx do
51
+ gem 'json', '~> 1.8.1'
52
+ gem 'racc', '~> 1.4.10'
53
+ gem 'rubysl-logger', '~> 2.0.0'
54
+ gem 'rubysl-open-uri', '~> 2.0.0'
55
+ gem 'rubysl-prettyprint', '~> 2.0.2'
56
+ end
57
+ end
58
+
59
+ group :benchmarks do
60
+ gem 'rbench', '~> 0.2.3'
61
+ end
62
+
63
+ platform :jruby do
64
+ group :jruby do
65
+ gem 'jruby-openssl', '~> 0.8.5'
66
+ end
67
+ end
data/Procfile ADDED
@@ -0,0 +1 @@
1
+ web: env PORT=$PORT ADDRESS=0.0.0.0 bundle exec ruby examples/echo_server.rb
data/README.md ADDED
@@ -0,0 +1,66 @@
1
+ # The HTTP toolkit for Ruby [![Build Status](https://travis-ci.org/lgierth/httpkit.png?branch=master)](https://travis-ci.org/lgierth/httpkit) [![Code Climate](https://codeclimate.com/github/lgierth/httpkit.png)](https://codeclimate.com/github/lgierth/httpkit) [![Coverage Status](https://coveralls.io/repos/lgierth/httpkit/badge.png?branch=master)](https://coveralls.io/r/lgierth/httpkit?branch=master)
2
+
3
+ HTTPkit is a Ruby toolkit for building HTTP clients and servers,
4
+ as well as compositions of them.
5
+
6
+ - \#1 feature: readable, high-quality, extendable code with 66.81% mutation coverage (wip)
7
+ - \#2 feature: sophisticated request and response streaming
8
+ - \#3 feature: compatible with Rack, Faraday, and Webmachine for Ruby (todo)
9
+ - \#4 feature: concurrenct or non-concurrent
10
+ - Non-concurrent using one-off EventMachine reactor (clients only)
11
+ - Evented using EventMachine
12
+ - Synchronously evented using EventMachine and Fibers
13
+ - Threaded using Celluloid (todo)
14
+
15
+ *Note:* The `master` branch contains the latest development effort. Look at the
16
+ `0.5.x` branch for stable, but very old releases. HTTPkit used to be called
17
+ Hatetepe.
18
+
19
+ ## Installation
20
+
21
+ Add this line to your application's Gemfile:
22
+
23
+ gem 'httpkit'
24
+
25
+ And then execute:
26
+
27
+ $ bundle
28
+
29
+ Or install it yourself as:
30
+
31
+ $ gem install httpkit
32
+
33
+ ## Usage
34
+
35
+ Code examples
36
+
37
+ - [Getting started ](http://rubydoc.info/github/lgierth/httpkit/master/file/examples/getting_started.rb)
38
+ - [HTTP echo server](http://rubydoc.info/github/lgierth/httpkit/master/file/examples/echo_server.rb)
39
+
40
+ API Reference
41
+
42
+ - [HTTPkit::Client ](http://rubydoc.info/github/lgierth/httpkit/master/HTTPkit/Client)
43
+ - [HTTPkit::Server ](http://rubydoc.info/github/lgierth/httpkit/master/HTTPkit/Server)
44
+ - [HTTPkit::Response ](http://rubydoc.info/github/lgierth/httpkit/master/HTTPkit/Request)
45
+ - [HTTPkit::Request ](http://rubydoc.info/github/lgierth/httpkit/master/HTTPkit/Response)
46
+ - [HTTPkit::Body ](http://rubydoc.info/github/lgierth/httpkit/master/HTTPkit/Body)
47
+ - [HTTPkit::Promise ](http://rubydoc.info/github/lgierth/httpkit/master/HTTPkit/Promise)
48
+ - [HTTPkit::Serializer](http://rubydoc.info/github/lgierth/httpkit/master/HTTPkit/Serializer)
49
+
50
+ ## To do
51
+
52
+ Here: https://trello.com/b/OoxEq1ze/httpkit
53
+
54
+ ## License
55
+
56
+ HTTPkit is free and unencumbered public domain software. For more
57
+ information, see [unlicense.org](http://unlicense.org/) or the accompanying
58
+ UNLICENSE file.
59
+
60
+ ## Contributing
61
+
62
+ 1. Fork it
63
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
64
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
65
+ 4. Push to the branch (`git push origin my-new-feature`)
66
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ task :default => :spec
2
+
3
+ # Added by devtools
4
+ require 'devtools'
5
+ Devtools.init_rake_tasks
data/UNLICENSE ADDED
@@ -0,0 +1,24 @@
1
+ This is free and unencumbered software released into the public domain.
2
+
3
+ Anyone is free to copy, modify, publish, use, compile, sell, or
4
+ distribute this software, either in source code form or as a compiled
5
+ binary, for any purpose, commercial or non-commercial, and by any
6
+ means.
7
+
8
+ In jurisdictions that recognize copyright laws, the author or authors
9
+ of this software dedicate any and all copyright interest in the
10
+ software to the public domain. We make this dedication for the benefit
11
+ of the public at large and to the detriment of our heirs and
12
+ successors. We intend this dedication to be an overt act of
13
+ relinquishment in perpetuity of all present and future rights to this
14
+ software under copyright law.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ For more information, please refer to <http://unlicense.org/>
@@ -0,0 +1,2 @@
1
+ ---
2
+ unit_test_timeout: 0.0
data/config/flay.yml ADDED
@@ -0,0 +1,3 @@
1
+ ---
2
+ threshold: 8
3
+ total_score: 181
data/config/flog.yml ADDED
@@ -0,0 +1,2 @@
1
+ ---
2
+ threshold: 10.0
data/config/mutant.yml ADDED
@@ -0,0 +1,3 @@
1
+ ---
2
+ name: httpkit
3
+ namespace: HTTPkit
data/config/reek.yml ADDED
@@ -0,0 +1,114 @@
1
+ ---
2
+ Attribute:
3
+ enabled: false
4
+ exclude: []
5
+ BooleanParameter:
6
+ enabled: true
7
+ exclude: []
8
+ ClassVariable:
9
+ enabled: true
10
+ exclude: []
11
+ ControlParameter:
12
+ enabled: true
13
+ exclude:
14
+ - "HTTPkit::Connection::EventMachine#close"
15
+ - "HTTPkit::Connection::EventMachine#unbind"
16
+ DataClump:
17
+ enabled: true
18
+ exclude: []
19
+ max_copies: 2
20
+ min_clump_size: 2
21
+ DuplicateMethodCall:
22
+ enabled: true
23
+ exclude: []
24
+ max_calls: 2
25
+ allow_calls: []
26
+ FeatureEnvy:
27
+ enabled: false
28
+ exclude: []
29
+ IrresponsibleModule:
30
+ enabled: false
31
+ exclude: []
32
+ LongParameterList:
33
+ enabled: true
34
+ exclude: []
35
+ max_params: 2
36
+ overrides:
37
+ initialize:
38
+ max_params: 4
39
+ setup:
40
+ max_params: 3
41
+ LongYieldList:
42
+ enabled: true
43
+ exclude: []
44
+ max_params: 2
45
+ NestedIterators:
46
+ enabled: true
47
+ exclude: []
48
+ max_allowed_nesting: 2
49
+ ignore_iterators: []
50
+ NilCheck:
51
+ enabled: true
52
+ exclude: []
53
+ RepeatedConditional:
54
+ enabled: true
55
+ exclude: []
56
+ max_ifs: 2
57
+ TooManyInstanceVariables:
58
+ enabled: true
59
+ exclude:
60
+ - HTTPkit::Connection::EventMachine
61
+ max_instance_variables: 4
62
+ TooManyMethods:
63
+ enabled: true
64
+ exclude: []
65
+ max_methods: 11
66
+ TooManyStatements:
67
+ enabled: true
68
+ exclude:
69
+ - each
70
+ max_statements: 5
71
+ UncommunicativeMethodName:
72
+ enabled: true
73
+ exclude: []
74
+ reject:
75
+ - !ruby/regexp /^[a-z]$/
76
+ - !ruby/regexp /[0-9]$/
77
+ - !ruby/regexp /[A-Z]/
78
+ accept: []
79
+ UncommunicativeModuleName:
80
+ enabled: true
81
+ exclude: []
82
+ reject:
83
+ - !ruby/regexp /^.$/
84
+ - !ruby/regexp /[0-9]$/
85
+ accept: []
86
+ UncommunicativeParameterName:
87
+ enabled: true
88
+ exclude: []
89
+ reject:
90
+ - !ruby/regexp /^.$/
91
+ - !ruby/regexp /[0-9]$/
92
+ - !ruby/regexp /[A-Z]/
93
+ accept:
94
+ - _
95
+ UncommunicativeVariableName:
96
+ enabled: true
97
+ exclude: []
98
+ reject:
99
+ - !ruby/regexp /^.$/
100
+ - !ruby/regexp /[0-9]$/
101
+ - !ruby/regexp /[A-Z]/
102
+ accept:
103
+ - k
104
+ - v
105
+ - a
106
+ - e
107
+ - _
108
+ UnusedParameters:
109
+ enabled: true
110
+ exclude: []
111
+ UtilityFunction:
112
+ enabled: false
113
+ exclude: []
114
+ max_helper_calls: 0
@@ -0,0 +1,56 @@
1
+ AllCops:
2
+ Includes:
3
+ - '**/*.rake'
4
+ - 'Gemfile'
5
+ - 'Gemfile.devtools'
6
+ Excludes:
7
+ - '**/vendor/**'
8
+ - '**/benchmarks/**'
9
+
10
+ # Avoid parameter lists longer than five parameters.
11
+ ParameterLists:
12
+ Max: 4
13
+ CountKeywordArgs: true
14
+
15
+ # Avoid more than `Max` levels of nesting.
16
+ BlockNesting:
17
+ Max: 3
18
+
19
+ # Align with the style guide.
20
+ CollectionMethods:
21
+ PreferredMethods:
22
+ collect: 'map'
23
+ inject: 'reduce'
24
+ find: 'detect'
25
+ find_all: 'select'
26
+
27
+ AccessModifierIndentation:
28
+ EnforcedStyle: indent
29
+
30
+ # Limit line length
31
+ LineLength:
32
+ Max: 79
33
+
34
+ # Disable documentation checking until a class needs to be documented once
35
+ Documentation:
36
+ Enabled: false
37
+
38
+ # Do not favor modifier if/unless usage when you have a single-line body
39
+ IfUnlessModifier:
40
+ Enabled: false
41
+
42
+ # Allow case equality operator (in limited use within the specs)
43
+ CaseEquality:
44
+ Enabled: false
45
+
46
+ # Constants do not always have to use SCREAMING_SNAKE_CASE
47
+ ConstantName:
48
+ Enabled: false
49
+
50
+ # Not all trivial readers/writers can be defined with attr_* methods
51
+ TrivialAccessors:
52
+ Enabled: false
53
+
54
+ SignalException:
55
+ # Valid values are: semantic, only_raise and only_fail
56
+ EnforcedStyle: only_raise
@@ -0,0 +1,2 @@
1
+ ---
2
+ threshold: 52.5
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+
3
+ require 'httpkit'
4
+
5
+ class EchoServer
6
+ def serve(request, served)
7
+ response = streaming_response
8
+ served.fulfill(response)
9
+
10
+ serialize(request, response)
11
+ request.closed { response.close }
12
+ end
13
+
14
+ private
15
+
16
+ def streaming_response
17
+ HTTPkit::Response.new(200, { 'Content-Type' => 'text/plain' },
18
+ HTTPkit::Body.new)
19
+ end
20
+
21
+ def serialize(request, response)
22
+ writer = response.body.closed.method(:progress)
23
+ serializer = HTTPkit::Serializer.new(request, writer)
24
+ serializer.serialize
25
+ end
26
+ end
27
+
28
+ HTTPkit.start do
29
+ HTTPkit::Server.start(address: ENV.fetch('ADDRESS', '127.0.0.1'),
30
+ port: ENV.fetch('PORT', 3000).to_i,
31
+ handlers: [HTTPkit::Server::KeepAlive.new,
32
+ EchoServer.new])
33
+
34
+ Signal.trap(:INT) { HTTPkit.stop }
35
+ Signal.trap(:TERM) { HTTPkit.stop }
36
+ end
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+
3
+ require 'httpkit'
4
+
5
+ class HelloServer
6
+ def serve(request, served)
7
+ p request.http_method # => :get
8
+ p request.uri # => "/"
9
+ p request.headers # => {"Host"=>"127.0.0.1:3000",
10
+ # "Content-Length"=>"0"}
11
+ p request.body.to_s # => ""
12
+
13
+ served.fulfill(response)
14
+ end
15
+
16
+ def response
17
+ HTTPkit::Response.new(200, { 'Content-Type' => 'text/plain' }, 'hello')
18
+ end
19
+ end
20
+
21
+ HTTPkit.run do
22
+ HTTPkit::Server.start(address: '127.0.0.1', port: 3000,
23
+ handlers: [HelloServer.new])
24
+
25
+ client = HTTPkit::Client.start(address: '127.0.0.1', port: 3000)
26
+
27
+ response = client.request(:get, '/')
28
+
29
+ p response.status # => 200
30
+ p response.status_name # => "OK"
31
+ p response.headers # => {"Content-Type"=>"text/plain",
32
+ # "Content-Length"=>"5"}
33
+ p response.body.to_s # => "hello"
34
+ end
data/httpkit.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # encoding: utf-8
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'httpkit/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "httpkit"
9
+ spec.version = HTTPkit::VERSION
10
+ spec.authors = ["Lars Gierth"]
11
+ spec.email = ["lars.gierth@gmail.com"]
12
+ spec.summary = %q{The HTTP toolkit for Ruby}
13
+ spec.description = %q{HTTPkit is a Ruby toolkit for building HTTP clients and servers, as well as compositions of them.}
14
+ spec.homepage = "https://github.com/lgierth/httpkit"
15
+ spec.license = "Public Domain"
16
+
17
+ spec.files = `git ls-files`.split($/)
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^spec/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_dependency "eventmachine"
23
+ spec.add_dependency "http_parser.rb"
24
+ spec.add_dependency "promise.rb", "~> 0.6"
25
+
26
+ spec.add_development_dependency "rspec"
27
+ end
@@ -0,0 +1,67 @@
1
+ # encoding: utf-8
2
+
3
+ module HTTPkit
4
+ class Body
5
+ def self.build(arg)
6
+ if arg.is_a?(Body)
7
+ arg
8
+ else
9
+ body = new(arg.to_s)
10
+ body.closed.fulfill
11
+ body
12
+ end
13
+ end
14
+
15
+ attr_reader :closed
16
+
17
+ # TODO: eliminate string param
18
+ def initialize(string = '')
19
+ @io = StringIO.new(string)
20
+
21
+ @closed = Promise.new
22
+ closed.on_progress { |str| @io.write(str) }
23
+ end
24
+
25
+ # don't optimize the sync call, we don't wanna search in @io.string
26
+ # because search time increases with its size.
27
+ def gets(*args)
28
+ closed.sync
29
+ @io.gets(*args)
30
+ end
31
+
32
+ def read(length = nil, buffer = nil)
33
+ closed.sync unless optimized_read?(length)
34
+ @io.read(length, buffer)
35
+ end
36
+
37
+ def rewind
38
+ closed.sync
39
+ @io.rewind
40
+ end
41
+
42
+ def each(&block)
43
+ yield_string(&block)
44
+ closed.on_progress(&block)
45
+ closed.sync
46
+ end
47
+
48
+ def to_s
49
+ closed.sync
50
+ @io.string
51
+ end
52
+
53
+ def string
54
+ @io.string
55
+ end
56
+
57
+ private
58
+
59
+ def optimized_read?(length)
60
+ length && length < (@io.length - pos)
61
+ end
62
+
63
+ def yield_string(&block)
64
+ block.call(@io.string) unless @io.string.empty?
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,10 @@
1
+ # encoding: utf-8
2
+
3
+ module HTTPkit
4
+ class Client::KeepAlive
5
+ def perform(request)
6
+ @previous, previous = request, @previous
7
+ previous.closed! if previous
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,14 @@
1
+ # encoding: utf-8
2
+
3
+ module HTTPkit
4
+ # @see EM.heartbeat_interval
5
+ class Client::Timeouts
6
+ def setup(config, _, connection)
7
+ @config = config
8
+ @connection = connection
9
+
10
+ @connection.comm_inactivity_timeout = @config[:timeout] ||= 2.0
11
+ @connection.pending_connect_timeout = @config[:connect_timeout] ||= 2.0
12
+ end
13
+ end
14
+ end