http 0.6.0.pre → 0.6.0

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

Potentially problematic release.


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

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b647051e277907433baf4b118a8b63a3d04aa67b
4
- data.tar.gz: 30e721ae9be7d37ad8e9359ad0d52dce0f6a8d16
3
+ metadata.gz: 6c81e2f4f9a7626fd58b225bf69772a47bf361c6
4
+ data.tar.gz: 31f9bb1e4ceb3494898604e1724de240b8237e43
5
5
  SHA512:
6
- metadata.gz: 2531298e15fc793c052a03e524875151c91d8eb111fdb9c6886546009cf827dab8d51eb8158052cdaaa1edcb968a63c4be89350fc357cc1972a20c04693429c3
7
- data.tar.gz: ecf369955e78188f2d6eff9c159b55beb9d160a9ce36f6acb5472b5d1c9cd5b374b848582901861389da4ba0e0b8ead5d7f92b1d223ec1ed30212839f321aa3f
6
+ metadata.gz: 637b115774a74b54c7dcede1ab6c4fde01638f329c51dedc83b8ad2cb1129983a888b2aef2442e00a8f68bc36dba614710ec645c009ba3bb47551a8630069add
7
+ data.tar.gz: b9b86db8e595bc6bb09862bc9e2f8e529e8e2e2b0c0599214ea24f816e8a30cf948bc5f405d143501cdce5475cf1e2971cf376e46b50dc95a3943adebf00f207
data/CHANGES.md CHANGED
@@ -1,3 +1,68 @@
1
+ 0.6.0
2
+ -----
3
+
4
+ * Rename `HTTP::Request#method` to `HTTP::Request#verb` (@krainboltgreene)
5
+ * Add `HTTP::ResponseBody` class (@tarcieri)
6
+ * Change API of response on `HTTP::Client.request` and "friends" (`#get`, `#post`, etc) (@tarcieri)
7
+ * Add `HTTP::Response#readpartial` (@tarcieri)
8
+ * Add `HTTP::Headers` class (@ixti)
9
+ * Fix and improve following redirects (@ixti)
10
+ * Add `HTTP::Request#redirect` (@ixti)
11
+ * Add `HTTP::Response#content_type` (@ixti)
12
+ * Add `HTTP::Response#mime_type` (@ixti)
13
+ * Add `HTTP::Response#charset` (@ixti)
14
+ * Improve error message upon invalid URI scheme (@ixti)
15
+ * Consolidate errors under common `HTTP::Error` namespace (@ixti)
16
+ * Add easy way of adding Authorization header (@ixti)
17
+ * Fix proxy support (@hundredwatt)
18
+ * Fix and improve query params handing (@jwinter)
19
+ * Change API of custom MIME type parsers (@ixti)
20
+ * Remove `HTTP::Chainable#with_response` (@ixti)
21
+ * Remove `HTTP::Response::BodyDelegator` (@ixti)
22
+ * Remove `HTTP::Response#parsed_body` (@ixti)
23
+ * Bump up input buffer from 4K to 16K (@tarcieri)
24
+
25
+ ``` ruby
26
+ # Main API change you will mention is that `request` method and it's
27
+ # syntax sugar helpers like `get`, `post`, etc. now returns Response
28
+ # object instead of BodyDelegator:
29
+
30
+ response = HTTP.get "http://example.com"
31
+ raw_body = HTTP.get("http://example.com").to_s
32
+ parsed_body = HTTP.get("http://example.com/users.json").parse
33
+
34
+ # Second major change in API is work with request/response headers
35
+ # It is now delegated to `HTTP::Headers` class, so you can check it's
36
+ # documentation for details, here we will only outline main difference.
37
+ # Duckface (`[]=`) does not appends headers anymore
38
+
39
+ request[:content_type] = "text/plain"
40
+ request[:content_type] = "text/html"
41
+ request[:content_type] # => "text/html"
42
+
43
+ # In order to add multiple header values, you should pass array:
44
+
45
+ request[:cookie] = ["foo=bar", "woo=hoo"]
46
+ request[:cookie] # => ["foo=bar", "woo=hoo"]
47
+
48
+ # or call `#add` on headers:
49
+
50
+ request.headers.add :accept, "text/plain"
51
+ request.headers.add :accept, "text/html"
52
+ request[:accept] # => ["text/plain", "text/html"]
53
+
54
+ # Also, you can now read body in chunks (stream):
55
+
56
+ res = HTTP.get "http://example.com"
57
+ File.open "/tmp/dummy.bin", "wb" do |io|
58
+ while (chunk = res.readpartial)
59
+ io << chunk
60
+ end
61
+ end
62
+ ```
63
+
64
+ [Changes discussion](https://github.com/tarcieri/http/issues/116)
65
+
1
66
  0.5.0
2
67
  -----
3
68
  * Add query string support
data/Gemfile CHANGED
@@ -21,7 +21,7 @@ group :test do
21
21
  gem 'json', '>= 1.8.1', :platforms => [:jruby, :rbx, :ruby_18, :ruby_19]
22
22
  gem 'mime-types', '~> 1.25', :platforms => [:jruby, :ruby_18]
23
23
  gem 'rspec', '>= 2.14'
24
- gem 'rubocop', '>= 0.19', :platforms => [:ruby_19, :ruby_20, :ruby_21]
24
+ gem 'rubocop', '~> 0.19.0', :platforms => [:ruby_19, :ruby_20, :ruby_21]
25
25
  gem 'simplecov', :require => false
26
26
  gem 'yardstick'
27
27
  end
data/http.gemspec CHANGED
@@ -5,7 +5,13 @@ require 'http/version'
5
5
  Gem::Specification.new do |gem|
6
6
  gem.authors = %w[Tony Arcieri]
7
7
  gem.email = %w[tony.arcieri@gmail.com]
8
- gem.description = 'HTTP so awesome it will lure Catherine Zeta Jones into your unicorn petting zoo'
8
+
9
+ gem.description = <<-DESCRIPTION.strip.gsub(/\s+/, ' ')
10
+ An easy-to-use client library for making requests from Ruby.
11
+ It uses a simple method chaining system for building requests,
12
+ similar to Python's Requests.
13
+ DESCRIPTION
14
+
9
15
  gem.summary = 'HTTP should be easy'
10
16
  gem.homepage = 'https://github.com/tarcieri/http'
11
17
  gem.licenses = %w[MIT]
data/lib/http.rb CHANGED
@@ -9,7 +9,7 @@ require 'http/request/writer'
9
9
  require 'http/response'
10
10
  require 'http/response/body'
11
11
  require 'http/response/parser'
12
- require 'http/backports' if RUBY_VERSION < '1.9.0'
12
+ require 'http/backports'
13
13
 
14
14
  # HTTP should be easy
15
15
  module HTTP
@@ -1,2 +1,2 @@
1
- require 'http/backports/uri'
2
- require 'http/backports/base64'
1
+ require 'http/backports/uri' if RUBY_VERSION < '1.9.3'
2
+ require 'http/backports/base64' if RUBY_VERSION < '1.9.0'
data/lib/http/client.rb CHANGED
@@ -19,49 +19,27 @@ module HTTP
19
19
  end
20
20
 
21
21
  # Make an HTTP request
22
- def request(verb, uri, options = {})
23
- opts = @default_options.merge(options)
22
+ def request(verb, uri, opts = {})
23
+ opts = @default_options.merge(opts)
24
+ uri = make_request_uri(uri, opts)
24
25
  headers = opts.headers
25
- proxy = opts.proxy
26
+ proxy = opts.proxy
27
+ body = make_request_body(opts, headers)
26
28
 
27
- request_body = make_request_body(opts, headers)
28
- uri, opts = normalize_get_params(uri, opts) if verb == :get
29
+ req = HTTP::Request.new(verb, uri, headers, proxy, body)
30
+ res = perform req, opts
29
31
 
30
- uri = "#{uri}?#{URI.encode_www_form(opts.params)}" if opts.params && !opts.params.empty?
31
-
32
- request = HTTP::Request.new(verb, uri, headers, proxy, request_body)
33
- perform request, opts
34
- end
35
-
36
- # Perform the HTTP request (following redirects if needed)
37
- def perform(req, options)
38
- res = perform_without_following_redirects req, options
39
-
40
- if options.follow
41
- res = Redirector.new(options.follow).perform req, res do |request|
42
- perform_without_following_redirects request, options
32
+ if opts.follow
33
+ res = Redirector.new(opts.follow).perform req, res do |request|
34
+ perform request, opts
43
35
  end
44
36
  end
45
37
 
46
38
  res
47
39
  end
48
40
 
49
- # Read a chunk of the body
50
- def readpartial(size = BUFFER_SIZE)
51
- return unless @socket
52
-
53
- read_more size
54
- chunk = @parser.chunk
55
-
56
- finish_response if @parser.finished?
57
-
58
- chunk
59
- end
60
-
61
- private
62
-
63
41
  # Perform a single (no follow) HTTP request
64
- def perform_without_following_redirects(req, options)
42
+ def perform(req, options)
65
43
  # finish previous response if client was re-used
66
44
  # TODO: this is pretty wrong, as socket shoud be part of response
67
45
  # connection, so that re-use of client will not break multiple
@@ -90,6 +68,20 @@ module HTTP
90
68
  res
91
69
  end
92
70
 
71
+ # Read a chunk of the body
72
+ def readpartial(size = BUFFER_SIZE)
73
+ return unless @socket
74
+
75
+ read_more size
76
+ chunk = @parser.chunk
77
+
78
+ finish_response if @parser.finished?
79
+
80
+ chunk
81
+ end
82
+
83
+ private
84
+
93
85
  # Initialize TLS connection
94
86
  def start_tls(socket, options)
95
87
  # TODO: abstract away SSLContexts so we can use other TLS libraries
@@ -100,6 +92,18 @@ module HTTP
100
92
  socket
101
93
  end
102
94
 
95
+ # Merges query params if needed
96
+ def make_request_uri(uri, options)
97
+ uri = URI uri.to_s unless uri.is_a? URI
98
+
99
+ if options.params && !options.params.empty?
100
+ params = CGI.parse(uri.query.to_s).merge(options.params || {})
101
+ uri.query = URI.encode_www_form params
102
+ end
103
+
104
+ uri
105
+ end
106
+
103
107
  # Create the request body object to send
104
108
  def make_request_body(opts, headers)
105
109
  if opts.body
@@ -124,21 +128,9 @@ module HTTP
124
128
  # Feeds some more data into parser
125
129
  def read_more(size)
126
130
  @parser << @socket.readpartial(size) unless @parser.finished?
127
- return true
131
+ true
128
132
  rescue EOFError
129
- return false
130
- end
131
-
132
- # Moves uri get params into the opts.params hash
133
- # @return [Array<URI, Hash>]
134
- def normalize_get_params(uri, opts)
135
- uri = URI(uri) unless uri.is_a?(URI)
136
- if uri.query
137
- extracted_params_from_uri = Hash[URI.decode_www_form(uri.query)]
138
- opts = opts.with_params(extracted_params_from_uri.merge(opts.params || {}))
139
- uri.query = nil
140
- end
141
- [uri, opts]
133
+ false
142
134
  end
143
135
  end
144
136
  end
data/lib/http/request.rb CHANGED
@@ -1,8 +1,9 @@
1
+ require 'http/errors'
1
2
  require 'http/headers'
2
3
  require 'http/request/writer'
3
4
  require 'http/version'
4
- require 'uri'
5
5
  require 'base64'
6
+ require 'uri'
6
7
 
7
8
  module HTTP
8
9
  class Request
data/lib/http/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module HTTP
2
- VERSION = '0.6.0.pre'
2
+ VERSION = '0.6.0'
3
3
  end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe URI do
4
+ describe '.encode_www_form' do
5
+ it 'properly encodes arrays' do
6
+ expect(URI.encode_www_form :a => [:b, :c]).to eq 'a=b&a=c'
7
+ end
8
+ end
9
+ end
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe HTTP::Client do
4
4
  StubbedClient = Class.new(HTTP::Client) do
5
- def perform_without_following_redirects(request, options)
5
+ def perform(request, options)
6
6
  stubs.fetch(request.uri.to_s) { super(request, options) }
7
7
  end
8
8
 
@@ -70,27 +70,48 @@ describe HTTP::Client do
70
70
  end
71
71
 
72
72
  describe 'parsing params' do
73
+ let(:client) { HTTP::Client.new }
74
+ before { allow(client).to receive :perform }
75
+
73
76
  it 'accepts params within the provided URL' do
74
- client = HTTP::Client.new
75
- allow(client).to receive(:perform)
76
77
  expect(HTTP::Request).to receive(:new) do |_, uri|
77
- params = CGI.parse(URI(uri).query)
78
- expect(params).to eq('foo' => ['bar'])
78
+ expect(CGI.parse uri.query).to eq('foo' => %w[bar])
79
79
  end
80
80
 
81
81
  client.get('http://example.com/?foo=bar')
82
82
  end
83
83
 
84
84
  it 'combines GET params from the URI with the passed in params' do
85
- client = HTTP::Client.new
86
- allow(client).to receive(:perform)
87
85
  expect(HTTP::Request).to receive(:new) do |_, uri|
88
- params = CGI.parse(URI(uri).query)
89
- expect(params).to eq('foo' => ['bar'], 'baz' => ['quux'])
86
+ expect(CGI.parse uri.query).to eq('foo' => %w[bar], 'baz' => %w[quux])
90
87
  end
91
88
 
92
89
  client.get('http://example.com/?foo=bar', :params => {:baz => 'quux'})
93
90
  end
91
+
92
+ it 'merges duplicate values' do
93
+ expect(HTTP::Request).to receive(:new) do |_, uri|
94
+ expect(CGI.parse uri.query).to eq('a' => %w[1 2])
95
+ end
96
+
97
+ client.get('http://example.com/?a=1', :params => {:a => 2})
98
+ end
99
+
100
+ it 'does not modifies query part if no params were given' do
101
+ expect(HTTP::Request).to receive(:new) do |_, uri|
102
+ expect(uri.query).to eq 'deadbeef'
103
+ end
104
+
105
+ client.get('http://example.com/?deadbeef')
106
+ end
107
+
108
+ it 'does not corrupts index-less arrays' do
109
+ expect(HTTP::Request).to receive(:new) do |_, uri|
110
+ expect(CGI.parse uri.query).to eq 'a[]' => %w[b c], 'd' => %w[e]
111
+ end
112
+
113
+ client.get('http://example.com/?a[]=b&a[]=c', :params => {:d => 'e'})
114
+ end
94
115
  end
95
116
 
96
117
  describe 'passing json' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: http
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0.pre
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tony
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-03-29 00:00:00.000000000 Z
12
+ date: 2014-04-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: http_parser.rb
@@ -39,8 +39,8 @@ dependencies:
39
39
  - - "~>"
40
40
  - !ruby/object:Gem::Version
41
41
  version: '1.0'
42
- description: HTTP so awesome it will lure Catherine Zeta Jones into your unicorn petting
43
- zoo
42
+ description: An easy-to-use client library for making requests from Ruby. It uses
43
+ a simple method chaining system for building requests, similar to Python's Requests.
44
44
  email:
45
45
  - tony.arcieri@gmail.com
46
46
  executables: []
@@ -89,6 +89,7 @@ files:
89
89
  - spec/http/authorization_header/bearer_token_spec.rb
90
90
  - spec/http/authorization_header_spec.rb
91
91
  - spec/http/backports/base64_spec.rb
92
+ - spec/http/backports/uri_spec.rb
92
93
  - spec/http/client_spec.rb
93
94
  - spec/http/content_type_spec.rb
94
95
  - spec/http/headers/mixin_spec.rb
@@ -125,9 +126,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
125
126
  version: '0'
126
127
  required_rubygems_version: !ruby/object:Gem::Requirement
127
128
  requirements:
128
- - - ">"
129
+ - - ">="
129
130
  - !ruby/object:Gem::Version
130
- version: 1.3.1
131
+ version: '0'
131
132
  requirements: []
132
133
  rubyforge_project:
133
134
  rubygems_version: 2.2.0
@@ -139,6 +140,7 @@ test_files:
139
140
  - spec/http/authorization_header/bearer_token_spec.rb
140
141
  - spec/http/authorization_header_spec.rb
141
142
  - spec/http/backports/base64_spec.rb
143
+ - spec/http/backports/uri_spec.rb
142
144
  - spec/http/client_spec.rb
143
145
  - spec/http/content_type_spec.rb
144
146
  - spec/http/headers/mixin_spec.rb