excon 0.0.21 → 0.0.22

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

Potentially problematic release.


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

@@ -27,7 +27,7 @@ You can also specify more complicated options to either style of call
27
27
 
28
28
  If you need to do something special with a response you can also pass a block that will be called with each chunk.
29
29
 
30
- Excon.get('http://geemus.com', :block => lambda {|chunk| p chunk })
30
+ Excon.get('http://geemus.com') {|chunk| p chunk }
31
31
 
32
32
  From there you should be able to make just about any request you might need.
33
33
 
data/Rakefile CHANGED
@@ -1,39 +1,147 @@
1
1
  require 'rubygems'
2
2
  require 'rake'
3
+ require 'date'
3
4
 
4
- begin
5
- require 'jeweler'
6
- Jeweler::Tasks.new do |gem|
7
- gem.name = "excon"
8
- gem.summary = %Q{EXtended http(s) CONnections}
9
- gem.description = %Q{speed, persistence, http(s)}
10
- gem.email = "wbeary@engineyard.com"
11
- gem.homepage = "http://github.com/geemus/excon"
12
- gem.authors = ["Wesley Beary"]
13
- # gem.add_development_dependency "shindo", ">= 0"
14
- # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
- end
16
- rescue LoadError
17
- puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
5
+ #############################################################################
6
+ #
7
+ # Helper functions
8
+ #
9
+ #############################################################################
10
+
11
+ def name
12
+ @name ||= Dir['*.gemspec'].first.split('.').first
13
+ end
14
+
15
+ def version
16
+ line = File.read("lib/#{name}.rb")[/^\s*VERSION\s*=\s*.*/]
17
+ line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
18
+ end
19
+
20
+ def date
21
+ Date.today.to_s
22
+ end
23
+
24
+ def rubyforge_project
25
+ name
26
+ end
27
+
28
+ def gemspec_file
29
+ "#{name}.gemspec"
18
30
  end
19
31
 
20
- require 'shindo/rake'
21
- Shindo::Rake.new
32
+ def gem_file
33
+ "#{name}-#{version}.gem"
34
+ end
35
+
36
+ def replace_header(head, header_name)
37
+ head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
38
+ end
22
39
 
23
- task :test => :check_dependencies
40
+ #############################################################################
41
+ #
42
+ # Standard tasks
43
+ #
44
+ #############################################################################
24
45
 
25
46
  task :default => :test
26
47
 
48
+ require 'rake/testtask'
49
+ Rake::TestTask.new(:test) do |test|
50
+ test.libs << 'lib' << 'test'
51
+ test.pattern = 'test/**/test_*.rb'
52
+ test.verbose = true
53
+ end
54
+
55
+ desc "Generate RCov test coverage and open in your browser"
56
+ task :coverage do
57
+ require 'rcov'
58
+ sh "rm -fr coverage"
59
+ sh "rcov test/test_*.rb"
60
+ sh "open coverage/index.html"
61
+ end
62
+
27
63
  require 'rake/rdoctask'
28
64
  Rake::RDocTask.new do |rdoc|
29
- if File.exist?('VERSION')
30
- version = File.read('VERSION')
31
- else
32
- version = ""
33
- end
34
-
35
65
  rdoc.rdoc_dir = 'rdoc'
36
- rdoc.title = "excon #{version}"
66
+ rdoc.title = "#{name} #{version}"
37
67
  rdoc.rdoc_files.include('README*')
38
68
  rdoc.rdoc_files.include('lib/**/*.rb')
39
69
  end
70
+
71
+ desc "Open an irb session preloaded with this library"
72
+ task :console do
73
+ sh "irb -rubygems -r ./lib/#{name}.rb"
74
+ end
75
+
76
+ #############################################################################
77
+ #
78
+ # Custom tasks (add your own tasks here)
79
+ #
80
+ #############################################################################
81
+
82
+
83
+
84
+ #############################################################################
85
+ #
86
+ # Packaging tasks
87
+ #
88
+ #############################################################################
89
+
90
+ task :release => :build do
91
+ unless `git branch` =~ /^\* master$/
92
+ puts "You must be on the master branch to release!"
93
+ exit!
94
+ end
95
+ sh "sudo gem install pkg/#{name}-#{version}.gem"
96
+ sh "git commit --allow-empty -a -m 'Release #{version}'"
97
+ sh "git tag v#{version}"
98
+ sh "git push origin master"
99
+ sh "git push origin v#{version}"
100
+ sh "gem push pkg/#{name}-#{version}.gem"
101
+ end
102
+
103
+ task :build => :gemspec do
104
+ sh "mkdir -p pkg"
105
+ sh "gem build #{gemspec_file}"
106
+ sh "mv #{gem_file} pkg"
107
+ end
108
+
109
+ task :gemspec => :validate do
110
+ # read spec file and split out manifest section
111
+ spec = File.read(gemspec_file)
112
+ head, manifest, tail = spec.split(" # = MANIFEST =\n")
113
+
114
+ # replace name version and date
115
+ replace_header(head, :name)
116
+ replace_header(head, :version)
117
+ replace_header(head, :date)
118
+ #comment this out if your rubyforge_project has a different name
119
+ replace_header(head, :rubyforge_project)
120
+
121
+ # determine file list from git ls-files
122
+ files = `git ls-files`.
123
+ split("\n").
124
+ sort.
125
+ reject { |file| file =~ /^\./ }.
126
+ reject { |file| file =~ /^(rdoc|pkg)/ }.
127
+ map { |file| " #{file}" }.
128
+ join("\n")
129
+
130
+ # piece file back together and write
131
+ manifest = " s.files = %w[\n#{files}\n ]\n"
132
+ spec = [head, manifest, tail].join(" # = MANIFEST =\n")
133
+ File.open(gemspec_file, 'w') { |io| io.write(spec) }
134
+ puts "Updated #{gemspec_file}"
135
+ end
136
+
137
+ task :validate do
138
+ libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}"]
139
+ unless libfiles.empty?
140
+ puts "Directory `lib` should only contain a `#{name}.rb` file and `#{name}` dir."
141
+ exit!
142
+ end
143
+ unless Dir['VERSION*'].empty?
144
+ puts "A `VERSION` file at root level violates Gem best practices."
145
+ exit!
146
+ end
147
+ end
@@ -1,5 +1,3 @@
1
- require 'eventmachine'
2
-
3
1
  require File.join(File.dirname(__FILE__), '..', 'lib/excon')
4
2
 
5
3
  require 'benchmark'
@@ -38,25 +36,4 @@ Benchmark.bmbm(25) do |bench|
38
36
  open('http://www.google.com/').read
39
37
  end
40
38
  end
41
- bench.report('em') do
42
- module DumbHttpClient
43
- @@responses = 0
44
- def post_init
45
- send_data "GET / HTTP/1.1\r\nHost: _\r\n\r\n"
46
- end
47
-
48
- def receive_data(*)
49
- @@responses += 1
50
- if @@responses == COUNT
51
- EM.stop
52
- end
53
- end
54
- end
55
-
56
- EM.run{
57
- COUNT.times do
58
- EM.connect 'www.google.com', 80, DumbHttpClient
59
- end
60
- }
61
- end
62
39
  end
@@ -1,23 +1,19 @@
1
- require 'benchmark'
2
-
3
- COUNT = 1_000_000
4
- data = "Content-Length: 100"
5
- Benchmark.bmbm(25) do |bench|
6
- bench.report('regex') do
7
- COUNT.times do
8
- header = data.match(/(.*):\s(.*)/)
9
- "#{header[1]}: #{header[2]}"
10
- end
11
- end
12
- bench.report('split') do
13
- COUNT.times do
14
- header = data.split(': ')
15
- "#{header[0]}: #{header[1]}"
16
- end
17
- end
18
- end
19
-
1
+ # require 'benchmark'
20
2
 
3
+ # COUNT = 1_000_000
4
+ # data = "Content-Length: 100"
5
+ # Benchmark.bmbm(25) do |bench|
6
+ # bench.report('regex') do
7
+ # COUNT.times do
8
+ # header = data.match(/(.*):\s(.*)/)
9
+ # end
10
+ # end
11
+ # bench.report('split') do
12
+ # COUNT.times do
13
+ # header = data.split(': ')
14
+ # end
15
+ # end
16
+ # end
21
17
 
22
18
  # Rehearsal ------------------------------------------------------------
23
19
  # regex 4.270000 0.010000 4.280000 ( 4.294186)
@@ -27,3 +23,25 @@ end
27
23
  # user system total real
28
24
  # regex 4.260000 0.010000 4.270000 ( 4.284764)
29
25
  # split 3.860000 0.010000 3.870000 ( 3.882795)
26
+
27
+ require 'rubygems'
28
+ require 'tach'
29
+
30
+ data = "Content-Length: 100"
31
+ Tach.meter(1_000_000) do
32
+ tach('regex') do
33
+ data.match(/(.*):\s(.*)/)
34
+ header = [$1, $2]
35
+ end
36
+ tach('split') do
37
+ header = data.split(': ')
38
+ end
39
+ end
40
+
41
+ # +-------+----------+----------+
42
+ # | tach | average | total |
43
+ # +-------+----------+----------+
44
+ # | regex | 4.680451 | 4.680451 |
45
+ # +-------+----------+----------+
46
+ # | split | 4.393218 | 4.393218 |
47
+ # +-------+----------+----------+
@@ -1,51 +1,51 @@
1
- require 'benchmark'
2
-
3
- COUNT = 1_000_000
4
- data = "Content-Length: 100\r\n"
5
- Benchmark.bmbm(25) do |bench|
6
- bench.report('chomp') do
7
- COUNT.times do
8
- data = "Content-Length: 100\r\n"
9
- data.chomp
10
- end
11
- end
12
- bench.report('chomp!') do
13
- COUNT.times do
14
- data = "Content-Length: 100\r\n"
15
- data.chomp!
16
- end
17
- end
18
- bench.report('chop') do
19
- COUNT.times do
20
- data = "Content-Length: 100\r\n"
21
- data.chop
22
- end
23
- end
24
- bench.report('chop!') do
25
- COUNT.times do
26
- data = "Content-Length: 100\r\n"
27
- data.chop!
28
- end
29
- end
30
- bench.report('strip') do
31
- COUNT.times do
32
- data = "Content-Length: 100\r\n"
33
- data.strip
34
- end
35
- end
36
- bench.report('strip!') do
37
- COUNT.times do
38
- data = "Content-Length: 100\r\n"
39
- data.strip!
40
- end
41
- end
42
- bench.report('index') do
43
- COUNT.times do
44
- data = "Content-Length: 100\r\n"
45
- data[0..-3]
46
- end
47
- end
48
- end
1
+ # require 'benchmark'
2
+ #
3
+ # COUNT = 1_000_000
4
+ # data = "Content-Length: 100\r\n"
5
+ # Benchmark.bmbm(25) do |bench|
6
+ # bench.report('chomp') do
7
+ # COUNT.times do
8
+ # data = "Content-Length: 100\r\n"
9
+ # data.chomp
10
+ # end
11
+ # end
12
+ # bench.report('chomp!') do
13
+ # COUNT.times do
14
+ # data = "Content-Length: 100\r\n"
15
+ # data.chomp!
16
+ # end
17
+ # end
18
+ # bench.report('chop') do
19
+ # COUNT.times do
20
+ # data = "Content-Length: 100\r\n"
21
+ # data.chop
22
+ # end
23
+ # end
24
+ # bench.report('chop!') do
25
+ # COUNT.times do
26
+ # data = "Content-Length: 100\r\n"
27
+ # data.chop!
28
+ # end
29
+ # end
30
+ # bench.report('strip') do
31
+ # COUNT.times do
32
+ # data = "Content-Length: 100\r\n"
33
+ # data.strip
34
+ # end
35
+ # end
36
+ # bench.report('strip!') do
37
+ # COUNT.times do
38
+ # data = "Content-Length: 100\r\n"
39
+ # data.strip!
40
+ # end
41
+ # end
42
+ # bench.report('index') do
43
+ # COUNT.times do
44
+ # data = "Content-Length: 100\r\n"
45
+ # data[0..-3]
46
+ # end
47
+ # end
48
+ # end
49
49
 
50
50
 
51
51
 
@@ -66,4 +66,50 @@ end
66
66
  # chop! 0.520000 0.000000 0.520000 ( 0.522950)
67
67
  # strip 0.640000 0.000000 0.640000 ( 0.646328)
68
68
  # strip! 0.520000 0.000000 0.520000 ( 0.532715)
69
- # index 0.740000 0.010000 0.750000 ( 0.771277)
69
+ # index 0.740000 0.010000 0.750000 ( 0.771277)
70
+
71
+ require 'rubygems'
72
+ require 'tach'
73
+
74
+ data = "Content-Length: 100\r\n"
75
+ Tach.meter(1_000_000) do
76
+ tach('chomp') do
77
+ data.dup.chomp
78
+ end
79
+ tach('chomp!') do
80
+ data.dup.chomp!
81
+ end
82
+ tach('chop') do
83
+ data.dup.chop
84
+ end
85
+ tach('chop!') do
86
+ data.dup.chop!
87
+ end
88
+ tach('strip') do
89
+ data.dup.strip
90
+ end
91
+ tach('strip!') do
92
+ data.dup.strip!
93
+ end
94
+ tach('index') do
95
+ data.dup[0..-3]
96
+ end
97
+ end
98
+
99
+ # +--------+----------+----------+
100
+ # | tach | average | total |
101
+ # +--------+----------+----------+
102
+ # | chomp | 1.444547 | 1.444547 |
103
+ # +--------+----------+----------+
104
+ # | chomp! | 1.276813 | 1.276813 |
105
+ # +--------+----------+----------+
106
+ # | chop | 1.422744 | 1.422744 |
107
+ # +--------+----------+----------+
108
+ # | chop! | 1.240941 | 1.240941 |
109
+ # +--------+----------+----------+
110
+ # | strip | 1.444776 | 1.444776 |
111
+ # +--------+----------+----------+
112
+ # | strip! | 1.266459 | 1.266459 |
113
+ # +--------+----------+----------+
114
+ # | index | 1.557975 | 1.557975 |
115
+ # +--------+----------+----------+
@@ -1,52 +1,81 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
- # -*- encoding: utf-8 -*-
5
-
1
+ ## This is the rakegem gemspec template. Make sure you read and understand
2
+ ## all of the comments. Some sections require modification, and others can
3
+ ## be deleted if you don't need them. Once you understand the contents of
4
+ ## this file, feel free to delete any comments that begin with two hash marks.
5
+ ## You can find comprehensive Gem::Specification documentation, at
6
+ ## http://docs.rubygems.org/read/chapter/20
6
7
  Gem::Specification.new do |s|
7
- s.name = %q{excon}
8
- s.version = "0.0.21"
9
-
8
+ s.specification_version = 2 if s.respond_to? :specification_version=
10
9
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Wesley Beary"]
12
- s.date = %q{2010-03-29}
13
- s.description = %q{speed, persistence, http(s)}
14
- s.email = %q{wbeary@engineyard.com}
15
- s.extra_rdoc_files = [
16
- "README.rdoc"
17
- ]
18
- s.files = [
19
- ".document",
20
- ".gitignore",
21
- "README.rdoc",
22
- "Rakefile",
23
- "VERSION",
24
- "benchmarks/excon_vs.rb",
25
- "benchmarks/headers_split_vs_match.rb",
26
- "benchmarks/strip_newline.rb",
27
- "excon.gemspec",
28
- "lib/excon.rb",
29
- "lib/excon/connection.rb",
30
- "lib/excon/errors.rb",
31
- "lib/excon/response.rb",
32
- "tests/config.ru",
33
- "tests/test_helper.rb",
34
- "tests/threaded_tests.rb"
35
- ]
36
- s.homepage = %q{http://github.com/geemus/excon}
10
+ s.rubygems_version = '1.3.5'
11
+
12
+ ## Leave these as is they will be modified for you by the rake gemspec task.
13
+ ## If your rubyforge_project name is different, then edit it and comment out
14
+ ## the sub! line in the Rakefile
15
+ s.name = 'excon'
16
+ s.version = '0.0.22'
17
+ s.date = '2010-05-09'
18
+ s.rubyforge_project = 'excon'
19
+
20
+ ## Make sure your summary is short. The description may be as long
21
+ ## as you like.
22
+ s.summary = "speed, persistence, http(s)"
23
+ s.description = "EXtended http(s) CONnections"
24
+
25
+ ## List the primary authors. If there are a bunch of authors, it's probably
26
+ ## better to set the email to an email list or something. If you don't have
27
+ ## a custom homepage, consider using your GitHub URL or the like.
28
+ s.authors = ["geemus (Wesley Beary)"]
29
+ s.email = 'geemus@gmail.com'
30
+ s.homepage = 'http://github.com/geemus/NAME'
31
+
32
+ ## This gets added to the $LOAD_PATH so that 'lib/NAME.rb' can be required as
33
+ ## require 'NAME.rb' or'/lib/NAME/file.rb' can be as require 'NAME/file.rb'
34
+ s.require_paths = %w[lib]
35
+
36
+ ## This sections is only necessary if you have C extensions.
37
+ # s.require_paths << 'ext'
38
+ # s.extensions = %w[ext/extconf.rb]
39
+
40
+ ## If your gem includes any executables, list them here.
41
+ # s.executables = ["name"]
42
+ # s.default_executable = 'name'
43
+
44
+ ## Specify any RDoc options here. You'll want to add your README and
45
+ ## LICENSE files to the extra_rdoc_files list.
37
46
  s.rdoc_options = ["--charset=UTF-8"]
38
- s.require_paths = ["lib"]
39
- s.rubygems_version = %q{1.3.6}
40
- s.summary = %q{EXtended http(s) CONnections}
41
-
42
- if s.respond_to? :specification_version then
43
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
44
- s.specification_version = 3
45
-
46
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
47
- else
48
- end
49
- else
50
- end
51
- end
47
+ s.extra_rdoc_files = %w[README.rdoc]
48
+
49
+ ## List your runtime dependencies here. Runtime dependencies are those
50
+ ## that are needed for an end user to actually USE your code.
51
+ # s.add_dependency('DEPNAME', [">= 1.1.0", "< 2.0.0"])
52
52
 
53
+ ## List your development dependencies here. Development dependencies are
54
+ ## those that are only needed during development
55
+ # s.add_development_dependency('DEVDEPNAME', [">= 1.1.0", "< 2.0.0"])
56
+
57
+ ## Leave this section as-is. It will be automatically generated from the
58
+ ## contents of your Git repository via the gemspec task. DO NOT REMOVE
59
+ ## THE MANIFEST COMMENTS, they are used as delimiters by the task.
60
+ # = MANIFEST =
61
+ s.files = %w[
62
+ README.rdoc
63
+ Rakefile
64
+ benchmarks/excon_vs.rb
65
+ benchmarks/headers_split_vs_match.rb
66
+ benchmarks/strip_newline.rb
67
+ excon.gemspec
68
+ lib/excon.rb
69
+ lib/excon/connection.rb
70
+ lib/excon/errors.rb
71
+ lib/excon/response.rb
72
+ tests/config.ru
73
+ tests/test_helper.rb
74
+ tests/threaded_tests.rb
75
+ ]
76
+ # = MANIFEST =
77
+
78
+ ## Test files will be grabbed from the file list. Make sure the path glob
79
+ ## matches what you actually use.
80
+ s.test_files = s.files.select { |path| path =~ /^[spec|tests]\/.*_[spec|tests]\.rb/ }
81
+ end
@@ -14,16 +14,20 @@ require 'excon/response'
14
14
 
15
15
  module Excon
16
16
 
17
+ unless const_defined?(:VERSION)
18
+ VERSION = '0.0.22'
19
+ end
20
+
17
21
  CHUNK_SIZE = 1048576 # 1 megabyte
18
22
 
19
- def self.new(url)
20
- Excon::Connection.new(url)
23
+ def self.new(url, params = {})
24
+ Excon::Connection.new(url, params)
21
25
  end
22
26
 
23
27
  %w{connect delete get head options post put trace}.each do |method|
24
28
  eval <<-DEF
25
- def self.#{method}(url, params = {})
26
- new(url).request(params.merge!(:method => '#{method.upcase}'))
29
+ def self.#{method}(url, params = {}, &block)
30
+ new(url).request(params.merge!(:method => '#{method.upcase}'), &block)
27
31
  end
28
32
  DEF
29
33
  end
@@ -1,29 +1,34 @@
1
1
  module Excon
2
2
  class Connection
3
3
 
4
- def initialize(url)
5
- @uri = URI.parse(url)
4
+ def initialize(url, params = {})
5
+ uri = URI.parse(url)
6
+ @connection = {
7
+ :headers => {},
8
+ :host => uri.host,
9
+ :path => uri.path,
10
+ :port => uri.port,
11
+ :query => uri.query,
12
+ :scheme => uri.scheme
13
+ }.merge!(params)
6
14
  reset_socket
7
15
  end
8
16
 
9
- def request(params)
17
+ def request(params, &block)
10
18
  begin
11
- params[:path] ||= @uri.path
19
+ params[:path] ||= @connection[:path]
12
20
  unless params[:path][0..0] == '/'
13
21
  params[:path] = "/#{params[:path]}"
14
22
  end
15
- if (params[:query] && !params[:query].empty?) || @uri.query
16
- params[:path] << "?#{params[:query]}"
23
+ request = "#{params[:method]} #{params[:path]}"
24
+ if (params[:query] && !params[:query].empty?) || @connection[:query]
25
+ request << "?#{params[:query]}"
17
26
  end
18
- request = "#{params[:method]} #{params[:path]} HTTP/1.1\r\n"
19
- params[:headers] ||= {}
20
- params[:headers]['Host'] = params[:host] || @uri.host
27
+ request << " HTTP/1.1\r\n"
28
+ params[:headers] ||= @connection[:headers]
29
+ params[:headers]['Host'] ||= params[:host] || @connection[:host]
21
30
  unless params[:headers]['Content-Length']
22
- if params[:body]
23
- params[:headers]['Content-Length'] = params[:body].length
24
- else
25
- params[:headers]['Content-Length'] = 0
26
- end
31
+ params[:headers]['Content-Length'] = (params[:body] && params[:body].length) || 0
27
32
  end
28
33
  for key, value in params[:headers]
29
34
  request << "#{key}: #{value}\r\n"
@@ -31,7 +36,7 @@ module Excon
31
36
  request << "\r\n"
32
37
  socket.write(request)
33
38
 
34
- if params[:body]
39
+ if params[:body] ||= @connection[:body]
35
40
  if params[:body].is_a?(String)
36
41
  socket.write(params[:body])
37
42
  else
@@ -41,47 +46,11 @@ module Excon
41
46
  end
42
47
  end
43
48
 
44
- response = Excon::Response.new
45
- response.status = socket.readline[9..11].to_i
46
- while true
47
- data = socket.readline.chop!
48
- unless data.empty?
49
- key, value = data.split(': ')
50
- response.headers[key] = value
51
- else
52
- break
53
- end
54
- end
55
-
56
- unless params[:method] == 'HEAD'
57
- block = if !params[:block] || (params[:expects] && ![*params[:expects]].include?(response.status))
58
- response.body = ''
59
- lambda { |chunk| response.body << chunk }
60
- else
61
- params[:block]
62
- end
63
-
64
- if response.headers['Connection'] == 'close'
65
- block.call(socket.read)
66
- reset_socket
67
- elsif response.headers['Content-Length']
68
- remaining = response.headers['Content-Length'].to_i
69
- while remaining > 0
70
- block.call(socket.read([CHUNK_SIZE, remaining].min))
71
- remaining -= CHUNK_SIZE
72
- end
73
- elsif response.headers['Transfer-Encoding'] == 'chunked'
74
- while true
75
- chunk_size = socket.readline.chop!.to_i(16)
76
- chunk = socket.read(chunk_size + 2).chop! # 2 == "/r/n".length
77
- if chunk_size > 0
78
- block.call(chunk)
79
- else
80
- break
81
- end
82
- end
83
- end
49
+ response = Excon::Response.parse(socket, params, &block)
50
+ if response.headers['Connection'] == 'close'
51
+ reset_socket
84
52
  end
53
+ response
85
54
  rescue => socket_error
86
55
  reset_socket
87
56
  raise(socket_error)
@@ -112,9 +81,9 @@ module Excon
112
81
  private
113
82
 
114
83
  def reset_socket
115
- new_socket = TCPSocket.open(@uri.host, @uri.port)
84
+ new_socket = TCPSocket.open(@connection[:host], @connection[:port])
116
85
 
117
- if @uri.scheme == 'https'
86
+ if @connection[:scheme] == 'https'
118
87
  @ssl_context = OpenSSL::SSL::SSLContext.new
119
88
  @ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
120
89
  new_socket = OpenSSL::SSL::SSLSocket.new(new_socket, @ssl_context)
@@ -123,15 +92,15 @@ module Excon
123
92
  end
124
93
 
125
94
  Thread.current[:_excon_sockets] ||= {}
126
- Thread.current[:_excon_sockets][@uri.to_s] = new_socket
95
+ Thread.current[:_excon_sockets][@connection.inspect] = new_socket
127
96
  end
128
97
 
129
98
  def socket
130
99
  Thread.current[:_excon_sockets] ||= {}
131
- if !Thread.current[:_excon_sockets][@uri.to_s] || Thread.current[:_excon_sockets][@uri.to_s].closed?
100
+ if !Thread.current[:_excon_sockets][@connection.inspect] || Thread.current[:_excon_sockets][@connection.inspect].closed?
132
101
  reset_socket
133
102
  end
134
- Thread.current[:_excon_sockets][@uri.to_s]
103
+ Thread.current[:_excon_sockets][@connection.inspect]
135
104
  end
136
105
 
137
106
  end
@@ -89,7 +89,7 @@ module Excon
89
89
  504 => [Excon::Errors::GatewayTimeout, 'Gateway Timeout']
90
90
  }
91
91
  error, message = @errors[response.status] || [Excon::Errors::Error, 'Unknown']
92
- error.new("Expected(#{request[:expects]}) <=> Actual(#{response.status} #{message})\n request => #{request.inspect}\n response => #{response.inspect}")
92
+ error.new("Expected(#{request[:expects].inspect}) <=> Actual(#{response.status} #{message})\n request => #{request.inspect}\n response => #{response.inspect}")
93
93
  end
94
94
 
95
95
  end
@@ -1,6 +1,59 @@
1
1
  module Excon
2
2
  class Response
3
3
 
4
+ def self.parse(socket, params = {}, &block)
5
+ if params[:block]
6
+ p "params[:block] is deprecated, please pass the block to the method"
7
+ end
8
+ if block_given?
9
+ params[:block] = block
10
+ end
11
+
12
+ response = new
13
+
14
+ response.status = socket.readline[9..11].to_i
15
+ while true
16
+ data = socket.readline.chop!
17
+ unless data.empty?
18
+ key, value = data.split(': ')
19
+ response.headers[key] = value
20
+ else
21
+ break
22
+ end
23
+ end
24
+
25
+ unless params[:method] == 'HEAD'
26
+ block = if !params[:block] || (params[:expects] && ![*params[:expects]].include?(response.status))
27
+ response.body = ''
28
+ lambda { |chunk| response.body << chunk }
29
+ else
30
+ params[:block]
31
+ end
32
+
33
+ if response.headers['Connection'] == 'close'
34
+ block.call(socket.read)
35
+ elsif response.headers['Content-Length']
36
+ remaining = response.headers['Content-Length'].to_i
37
+ while remaining > 0
38
+ block.call(socket.read([CHUNK_SIZE, remaining].min))
39
+ remaining -= CHUNK_SIZE
40
+ end
41
+ elsif response.headers['Transfer-Encoding'] == 'chunked'
42
+ while true
43
+ chunk_size = socket.readline.chop!.to_i(16)
44
+ chunk = socket.read(chunk_size + 2).chop! # 2 == "/r/n".length
45
+ if chunk_size > 0
46
+ block.call(chunk)
47
+ else
48
+ break
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ response
55
+ end
56
+
4
57
  attr_accessor :body, :headers, :status
5
58
 
6
59
  def initialize(attributes = {})
metadata CHANGED
@@ -5,21 +5,21 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 21
9
- version: 0.0.21
8
+ - 22
9
+ version: 0.0.22
10
10
  platform: ruby
11
11
  authors:
12
- - Wesley Beary
12
+ - geemus (Wesley Beary)
13
13
  autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-03-29 00:00:00 -07:00
17
+ date: 2010-05-09 00:00:00 -07:00
18
18
  default_executable:
19
19
  dependencies: []
20
20
 
21
- description: speed, persistence, http(s)
22
- email: wbeary@engineyard.com
21
+ description: EXtended http(s) CONnections
22
+ email: geemus@gmail.com
23
23
  executables: []
24
24
 
25
25
  extensions: []
@@ -27,11 +27,8 @@ extensions: []
27
27
  extra_rdoc_files:
28
28
  - README.rdoc
29
29
  files:
30
- - .document
31
- - .gitignore
32
30
  - README.rdoc
33
31
  - Rakefile
34
- - VERSION
35
32
  - benchmarks/excon_vs.rb
36
33
  - benchmarks/headers_split_vs_match.rb
37
34
  - benchmarks/strip_newline.rb
@@ -44,7 +41,7 @@ files:
44
41
  - tests/test_helper.rb
45
42
  - tests/threaded_tests.rb
46
43
  has_rdoc: true
47
- homepage: http://github.com/geemus/excon
44
+ homepage: http://github.com/geemus/NAME
48
45
  licenses: []
49
46
 
50
47
  post_install_message:
@@ -68,10 +65,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
68
65
  version: "0"
69
66
  requirements: []
70
67
 
71
- rubyforge_project:
68
+ rubyforge_project: excon
72
69
  rubygems_version: 1.3.6
73
70
  signing_key:
74
- specification_version: 3
75
- summary: EXtended http(s) CONnections
71
+ specification_version: 2
72
+ summary: speed, persistence, http(s)
76
73
  test_files: []
77
74
 
data/.document DELETED
@@ -1,5 +0,0 @@
1
- README.rdoc
2
- lib/**/*.rb
3
- bin/*
4
- features/**/*.feature
5
- LICENSE
data/.gitignore DELETED
@@ -1,5 +0,0 @@
1
- *.sw?
2
- .DS_Store
3
- coverage
4
- rdoc
5
- pkg
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.0.21