microget 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: de1316815435cc4a99b3d2a7c6f13b0e43015d87
4
- data.tar.gz: 13e92c78deb579b3fd98ff7ccc48bf6c659595b0
3
+ metadata.gz: 10904aa7598a374362dd5086d3b033a8f5a296a1
4
+ data.tar.gz: f61403282080b0722189d571436a8c6dfa89189a
5
5
  SHA512:
6
- metadata.gz: 220d1cada56fdded21fc72b5970505b93bb92f582ffda2eeca4a2f99e583ed1e2abbf02074f73182632ad560f15a4f6ebf00998f8ee97749da2f160089c50d15
7
- data.tar.gz: 8d09e070e936bf79bdb53ec97af71b31eaeba3f3b41dfa4cffa2267fb77a5efe9146412d35edd52cceb4db5b509b5c0194f1e1e8984c217de2556b225b027d59
6
+ metadata.gz: 141b9588147336dc6656f8c49ab6c3c438ea551baaec13cfd2edab42509406ba4ca60fd6aaf37e8b0f37722c220daf4d7b6a04b4bae567a1bba70bf19caec793
7
+ data.tar.gz: 8a2b5cd9b07e850f23ed17f5990a20054193c9effcee6ec66983c6758f615dc5b9c96d6534aa165f7d9a9cfc1dd52816c816160a4177406a19c7c73e2ae2c895
data/Gemfile CHANGED
@@ -8,7 +8,7 @@ source "http://rubygems.org"
8
8
  group :development do
9
9
  gem 'puma'
10
10
  gem 'yard'
11
- gem "rspec", "~> 3.3.0"
11
+ gem "rspec", "~> 3.2.0", "< 3.3"
12
12
  gem "rdoc", "~> 3.12"
13
13
  gem "bundler", "~> 1.0"
14
14
  gem "jeweler", "~> 2.0.1"
data/lib/microget.rb CHANGED
@@ -3,7 +3,9 @@ require 'socket'
3
3
 
4
4
  # An no-nonsense, pedal-to-the-metal unbuffered HTTP streaming client for doing GETs of large bodies, fast.
5
5
  module Microget
6
- VERSION = '1.0.0'
6
+ autoload :ServerRunner, File.dirname(__FILE__) + '/microget/server_runner'
7
+
8
+ VERSION = '1.1.0'
7
9
 
8
10
  extend self
9
11
 
@@ -26,6 +28,8 @@ module Microget
26
28
  raise ('Only plain HTTP is supported (%s)' % uri) unless uri.scheme == 'http'
27
29
  raise "Unknown host" unless uri.host
28
30
 
31
+ # Some reading on what might be usable here:
32
+ # http://www.mikeperham.com/2009/03/15/socket-timeouts-in-ruby/
29
33
  socket = TCPSocket.open(uri.host, uri.port || 80)
30
34
  socket.write("GET #{uri.request_uri} HTTP/1.1\r\n")
31
35
 
@@ -65,24 +69,25 @@ module Microget
65
69
  def perform_get(uri, request_headers: {}, chunk_size: 1024 * 1024 * 5)
66
70
  status_code, header_hash, socket = get_status_headers_and_body_socket(uri, request_headers: request_headers)
67
71
  body_bytes_received = 0
72
+
73
+ # Yield the status and headers once with an empty response
74
+ # so that the client can bail out of the request even before the body
75
+ # starts to arrive
76
+ return body_bytes_received unless yield(status_code, header_hash, '')
77
+
68
78
  # ...and then just read the body, without any buffering, using a non-blocking read
69
79
  while !socket.eof?
70
80
  begin
71
81
  data = socket.read_nonblock(chunk_size)
72
82
  body_bytes_received += data.bytesize
73
- return unless yield(status_code, header_hash, data)
83
+ continue_reading = yield(status_code, header_hash, data)
84
+ return body_bytes_received unless continue_reading
74
85
  rescue IO::WaitReadable
75
86
  IO.select([socket], [], SOCKET_TIMEOUT)
76
87
  retry
77
88
  end
78
89
  end
79
90
 
80
- # Yield the status and headers once with an empty response
81
- # so that the client gets at least something.
82
- if body_bytes_received.zero?
83
- yield(status_code, header_hash, '')
84
- end
85
-
86
91
  body_bytes_received
87
92
  ensure
88
93
  socket.close if socket && !socket.closed?
@@ -0,0 +1,60 @@
1
+ require 'net/http'
2
+
3
+ # A simplistic runner for external web servers within a separate process.
4
+ class Microget::ServerRunner < Struct.new(:name, :command, :port, :rackup_file_path)
5
+ SHOULD_CONNECT_WITHIN = 2
6
+
7
+ def command
8
+ super % [port, rackup_file_path]
9
+ end
10
+
11
+ def start!
12
+ # Boot Puma in a forked process
13
+ @pid = fork do
14
+ $stderr.puts "Spinning up with #{command.inspect}"
15
+
16
+ # Do not pollute the test suite output with the Puma logs,
17
+ # save the stuff to logfiles instead
18
+ $stdout.reopen(File.open('server_runner_%s_stdout.log' % name, 'a'))
19
+ $stderr.reopen(File.open('server_runner_%s_stderr.log' % name, 'a'))
20
+
21
+ # Since we have to do with timing tolerances, having the output drip in ASAP is useful
22
+ $stdout.sync = true
23
+ $stderr.sync = true
24
+ exec(command)
25
+ end
26
+
27
+ Thread.abort_on_exception = true
28
+
29
+ t = Time.now
30
+ # Wait for Puma to be online, poll the alive URL until it stops responding
31
+ loop do
32
+ sleep 0.5
33
+ begin
34
+ alive_check_url = "http://0.0.0.0:%d/" % port
35
+ response = Net::HTTP.get_response(URI(alive_check_url))
36
+ @running = true
37
+ break
38
+ rescue Errno::ECONNREFUSED
39
+ if (Time.now - t) > SHOULD_CONNECT_WITHIN # Timeout when starting
40
+ raise "Could not get the server started in 2 seconds, something might be misconfigured"
41
+ end
42
+ end
43
+ end
44
+
45
+ trap("TERM") { stop! }
46
+ end
47
+
48
+ def running?
49
+ !!@running
50
+ end
51
+
52
+ def stop!
53
+ return unless @pid
54
+
55
+ # Tell the webserver to quit, twice (we do not care if there are running responses)
56
+ %W( TERM TERM KILL ).each {|sig| Process.kill(sig, @pid); sleep 0.5 }
57
+ @pid = nil
58
+ @running = false
59
+ end
60
+ end
data/microget.gemspec ADDED
@@ -0,0 +1,72 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+ # stub: microget 1.1.0 ruby lib
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "microget"
9
+ s.version = "1.1.0"
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib"]
13
+ s.authors = ["Julik Tarkhanov"]
14
+ s.date = "2015-11-04"
15
+ s.description = "Pedal-to-the-metal HTTP client for GET requests"
16
+ s.email = "me@julik.nl"
17
+ s.extra_rdoc_files = [
18
+ "LICENSE.txt",
19
+ "README.md"
20
+ ]
21
+ s.files = [
22
+ ".document",
23
+ ".rspec",
24
+ ".yardopts",
25
+ "Gemfile",
26
+ "LICENSE.txt",
27
+ "README.md",
28
+ "Rakefile",
29
+ "lib/microget.rb",
30
+ "lib/microget/server_runner.rb",
31
+ "microget.gemspec",
32
+ "spec/helper.rb",
33
+ "spec/microget_spec.rb",
34
+ "spec/microget_with_real_server_spec.rb",
35
+ "spec/streaming_app.ru"
36
+ ]
37
+ s.homepage = "http://github.com/julik/microget"
38
+ s.licenses = ["MIT"]
39
+ s.rubygems_version = "2.2.2"
40
+ s.summary = "Designed for slow and/or large response bodies"
41
+
42
+ if s.respond_to? :specification_version then
43
+ s.specification_version = 4
44
+
45
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
46
+ s.add_development_dependency(%q<puma>, [">= 0"])
47
+ s.add_development_dependency(%q<yard>, [">= 0"])
48
+ s.add_development_dependency(%q<rspec>, ["< 3.3", "~> 3.2.0"])
49
+ s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
50
+ s.add_development_dependency(%q<bundler>, ["~> 1.0"])
51
+ s.add_development_dependency(%q<jeweler>, ["~> 2.0.1"])
52
+ s.add_development_dependency(%q<simplecov>, [">= 0"])
53
+ else
54
+ s.add_dependency(%q<puma>, [">= 0"])
55
+ s.add_dependency(%q<yard>, [">= 0"])
56
+ s.add_dependency(%q<rspec>, ["< 3.3", "~> 3.2.0"])
57
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
58
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
59
+ s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
60
+ s.add_dependency(%q<simplecov>, [">= 0"])
61
+ end
62
+ else
63
+ s.add_dependency(%q<puma>, [">= 0"])
64
+ s.add_dependency(%q<yard>, [">= 0"])
65
+ s.add_dependency(%q<rspec>, ["< 3.3", "~> 3.2.0"])
66
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
67
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
68
+ s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
69
+ s.add_dependency(%q<simplecov>, [">= 0"])
70
+ end
71
+ end
72
+
data/spec/helper.rb CHANGED
@@ -3,4 +3,3 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
3
 
4
4
  require 'rspec'
5
5
  require 'microget'
6
- require_relative 'server_runner'
@@ -3,9 +3,8 @@ require_relative 'helper'
3
3
  describe "Microget running against a real server" do
4
4
  before :all do
5
5
  rack_app = File.expand_path(File.join(__dir__, 'streaming_app.ru'))
6
- @server = ServerRunner.new("bundle exec puma --port %d %s", 9393, rack_app)
6
+ @server = Microget::ServerRunner.new(:puma, "bundle exec puma --port %d %s", 9393, rack_app)
7
7
  @server.start!
8
- sleep 0.5 until @server.running?
9
8
  end
10
9
 
11
10
  after :all do
@@ -49,6 +48,9 @@ describe "Microget running against a real server" do
49
48
  t = Time.now
50
49
  end
51
50
 
51
+ first_chunk_and_delta = time_deltas_and_chunks.shift
52
+ expect(first_chunk_and_delta[1]).to be_empty # First chunk is empty to allow header/status checks
53
+
52
54
  time_deltas_and_chunks.each do |(delta, chunk_contents)|
53
55
  expect(chunk_contents).to include('Message number ')
54
56
  expect(delta).to be_within(0.2).of(1.0) # The server "drips" down one message every second, approximately
@@ -61,6 +61,10 @@ map '/with-content-length' do
61
61
  run StreamerWithLength
62
62
  end
63
63
 
64
+ map '/' do
65
+ run ->(env) { [200, {}, ['Yes']]}
66
+ end
67
+
64
68
  map '/alive' do
65
69
  run ->(env) { [200, {}, ['Yes']]}
66
70
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: microget
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julik Tarkhanov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-01 00:00:00.000000000 Z
11
+ date: 2015-11-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: puma
@@ -42,16 +42,22 @@ dependencies:
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
+ - - "<"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.3'
45
48
  - - "~>"
46
49
  - !ruby/object:Gem::Version
47
- version: 3.3.0
50
+ version: 3.2.0
48
51
  type: :development
49
52
  prerelease: false
50
53
  version_requirements: !ruby/object:Gem::Requirement
51
54
  requirements:
55
+ - - "<"
56
+ - !ruby/object:Gem::Version
57
+ version: '3.3'
52
58
  - - "~>"
53
59
  - !ruby/object:Gem::Version
54
- version: 3.3.0
60
+ version: 3.2.0
55
61
  - !ruby/object:Gem::Dependency
56
62
  name: rdoc
57
63
  requirement: !ruby/object:Gem::Requirement
@@ -124,11 +130,11 @@ files:
124
130
  - README.md
125
131
  - Rakefile
126
132
  - lib/microget.rb
133
+ - lib/microget/server_runner.rb
134
+ - microget.gemspec
127
135
  - spec/helper.rb
128
136
  - spec/microget_spec.rb
129
137
  - spec/microget_with_real_server_spec.rb
130
- - spec/server_runner.rb
131
- - spec/spec_helper.rb
132
138
  - spec/streaming_app.ru
133
139
  homepage: http://github.com/julik/microget
134
140
  licenses:
@@ -1,57 +0,0 @@
1
- require 'net/http'
2
-
3
- class ServerRunner < Struct.new(:command, :port, :rackup_file_path)
4
- def command
5
- super % [port, rackup_file_path]
6
- end
7
-
8
- def start!
9
- # Boot Puma in a forked process
10
- @pid = fork do
11
- $stderr.puts "Spinning up with #{command.inspect}"
12
- # Do not pollute the RSpec output with the Puma logs,
13
- # save the stuff to logfiles instead
14
- # $stdout.reopen(File.open('server_runner_stdout.log' % name, 'a'))
15
- # $stderr.reopen(File.open('server_runner_stderr.log' % name, 'a'))
16
-
17
- # Since we have to do with timing tolerances, having the output drip in ASAP is useful
18
- $stdout.sync = true
19
- $stderr.sync = true
20
- exec(command)
21
- end
22
-
23
- Thread.abort_on_exception = true
24
-
25
- Thread.new do
26
- t = Time.now
27
- # Wait for Puma to be online, poll the alive URL until it stops responding
28
- loop do
29
- sleep 0.5
30
- begin
31
- alive_check_url = "http://0.0.0.0:%d/alive" % port
32
- response = Net::HTTP.get_response(URI(alive_check_url))
33
- @running = true
34
- break
35
- rescue Errno::ECONNREFUSED
36
- if Time.now - t > 2 # Timeout when starting
37
- raise "Could not get the server started in 2 seconds, something might be misconfigured"
38
- end
39
- end
40
- end
41
- end
42
-
43
- trap("TERM") { stop! }
44
- end
45
-
46
- def running?
47
- !!@running
48
- end
49
-
50
- def stop!
51
- return unless @pid
52
-
53
- # Tell the webserver to quit, twice (we do not care if there are running responses)
54
- %W( TERM TERM KILL ).each {|sig| Process.kill(sig, @pid); sleep 0.5 }
55
- @pid = nil
56
- end
57
- end
data/spec/spec_helper.rb DELETED
@@ -1,6 +0,0 @@
1
- require 'simplecov'
2
-
3
-
4
- RSpec.configure do |config|
5
-
6
- end