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 +4 -4
- data/CHANGES.md +65 -0
- data/Gemfile +1 -1
- data/http.gemspec +7 -1
- data/lib/http.rb +1 -1
- data/lib/http/backports.rb +2 -2
- data/lib/http/client.rb +39 -47
- data/lib/http/request.rb +2 -1
- data/lib/http/version.rb +1 -1
- data/spec/http/backports/uri_spec.rb +9 -0
- data/spec/http/client_spec.rb +30 -9
- metadata +8 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6c81e2f4f9a7626fd58b225bf69772a47bf361c6
|
4
|
+
data.tar.gz: 31f9bb1e4ceb3494898604e1724de240b8237e43
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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', '
|
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
|
-
|
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
data/lib/http/backports.rb
CHANGED
@@ -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,
|
23
|
-
opts
|
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
|
26
|
+
proxy = opts.proxy
|
27
|
+
body = make_request_body(opts, headers)
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
+
req = HTTP::Request.new(verb, uri, headers, proxy, body)
|
30
|
+
res = perform req, opts
|
29
31
|
|
30
|
-
|
31
|
-
|
32
|
-
|
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
|
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
|
-
|
131
|
+
true
|
128
132
|
rescue EOFError
|
129
|
-
|
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
data/lib/http/version.rb
CHANGED
data/spec/http/client_spec.rb
CHANGED
@@ -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
|
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
|
-
|
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
|
-
|
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
|
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-
|
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:
|
43
|
-
|
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:
|
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
|