httpi 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.md +5 -0
- data/lib/httpi/cookie.rb +35 -0
- data/lib/httpi/cookie_store.rb +34 -0
- data/lib/httpi/request.rb +12 -0
- data/lib/httpi/response.rb +6 -0
- data/lib/httpi/version.rb +1 -1
- data/spec/httpi/cookie_spec.rb +36 -0
- data/spec/httpi/cookie_store_spec.rb +26 -0
- data/spec/httpi/request_spec.rb +23 -0
- data/spec/httpi/response_spec.rb +17 -0
- metadata +8 -4
data/CHANGELOG.md
CHANGED
data/lib/httpi/cookie.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
module HTTPI
|
2
|
+
|
3
|
+
# = HTTPI::Cookie
|
4
|
+
#
|
5
|
+
# Represents a single delicious cookie.
|
6
|
+
#
|
7
|
+
# == Examples
|
8
|
+
#
|
9
|
+
# cookie = HTTPI::Cookie.new("token=choc-choc-chip; Path=/; HttpOnly")
|
10
|
+
#
|
11
|
+
# cookie.name # "token"
|
12
|
+
# cookie.name_and_value # "token=choc-choc-chip"
|
13
|
+
class Cookie
|
14
|
+
|
15
|
+
# Returns a list of cookies from a Hash of +headers+.
|
16
|
+
def self.list_from_headers(headers)
|
17
|
+
Array(headers["Set-Cookie"]).map { |cookie| new(cookie) }
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(cookie)
|
21
|
+
@cookie = cookie
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns the name of the cookie.
|
25
|
+
def name
|
26
|
+
@cookie.split("=").first
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns the name and value of the cookie.
|
30
|
+
def name_and_value
|
31
|
+
@cookie.split(";").first
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module HTTPI
|
2
|
+
|
3
|
+
# = HTTPI::CookieStore
|
4
|
+
#
|
5
|
+
# Stores a unique list of cookies for future requests.
|
6
|
+
#
|
7
|
+
# == Examples
|
8
|
+
#
|
9
|
+
# # Add one or more cookies to the store
|
10
|
+
# cookie_store = HTTPI::CookieStore.new
|
11
|
+
# cookie_store.add HTTPI::Cookie.new("token=choc-choc-chip; Path=/; HttpOnly")
|
12
|
+
#
|
13
|
+
# # Fetch the names and values for the "Cookie" header
|
14
|
+
# cookie_store.fetch # => "token=choc-choc-chip"
|
15
|
+
class CookieStore
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@cookies = {}
|
19
|
+
end
|
20
|
+
|
21
|
+
# Adds one or more cookies to the store.
|
22
|
+
def add(*cookies)
|
23
|
+
cookies.each do |cookie|
|
24
|
+
@cookies[cookie.name] = cookie.name_and_value
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns the names and values for the "Cookie" header.
|
29
|
+
def fetch
|
30
|
+
@cookies.values.join(";") unless @cookies.empty?
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
data/lib/httpi/request.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "uri"
|
2
|
+
require "httpi/cookie_store"
|
2
3
|
require "httpi/auth/config"
|
3
4
|
require "rack/utils"
|
4
5
|
|
@@ -62,6 +63,12 @@ module HTTPI
|
|
62
63
|
headers["Accept-Encoding"] = "gzip,deflate"
|
63
64
|
end
|
64
65
|
|
66
|
+
# Sets the cookies from a given +http_response+.
|
67
|
+
def set_cookies(http_response)
|
68
|
+
cookie_store.add *http_response.cookies
|
69
|
+
headers["Cookie"] = cookie_store.fetch
|
70
|
+
end
|
71
|
+
|
65
72
|
attr_accessor :open_timeout, :read_timeout
|
66
73
|
attr_reader :body
|
67
74
|
|
@@ -87,6 +94,11 @@ module HTTPI
|
|
87
94
|
|
88
95
|
private
|
89
96
|
|
97
|
+
# Stores the cookies from past requests.
|
98
|
+
def cookie_store
|
99
|
+
@cookie_store ||= CookieStore.new
|
100
|
+
end
|
101
|
+
|
90
102
|
# Expects a +url+, validates its validity and returns a +URI+ object.
|
91
103
|
def normalize_url!(url)
|
92
104
|
raise ArgumentError, "Invalid URL: #{url}" unless url.to_s =~ /^http/
|
data/lib/httpi/response.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require "zlib"
|
2
2
|
require "stringio"
|
3
3
|
require "httpi/dime"
|
4
|
+
require "httpi/cookie"
|
4
5
|
require "rack/utils"
|
5
6
|
|
6
7
|
module HTTPI
|
@@ -32,6 +33,11 @@ module HTTPI
|
|
32
33
|
!!(headers["Content-Type"] =~ /^multipart/i)
|
33
34
|
end
|
34
35
|
|
36
|
+
# Returns a list of cookies from the response.
|
37
|
+
def cookies
|
38
|
+
@cookies ||= Cookie.list_from_headers(headers)
|
39
|
+
end
|
40
|
+
|
35
41
|
# Returns any DIME attachments.
|
36
42
|
def attachments
|
37
43
|
decode_body unless @body
|
data/lib/httpi/version.rb
CHANGED
@@ -0,0 +1,36 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "httpi"
|
3
|
+
|
4
|
+
describe HTTPI::Cookie do
|
5
|
+
|
6
|
+
let(:cookie) { HTTPI::Cookie.new("token=choc-choc-chip; Path=/; HttpOnly") }
|
7
|
+
|
8
|
+
describe ".list_from_headers" do
|
9
|
+
it "returns a list of cookies from a Hash of headers" do
|
10
|
+
headers = { "Set-Cookie" => "token=strawberry; Path=/; HttpOnly" }
|
11
|
+
cookies = HTTPI::Cookie.list_from_headers(headers)
|
12
|
+
|
13
|
+
cookies.should have(1).item
|
14
|
+
cookies.first.should be_a(HTTPI::Cookie)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "handles multiple cookies" do
|
18
|
+
headers = { "Set-Cookie" => ["user=chucknorris; Path=/; HttpOnly", "token=strawberry; Path=/; HttpOnly"] }
|
19
|
+
cookies = HTTPI::Cookie.list_from_headers(headers)
|
20
|
+
cookies.should have(2).items
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#name" do
|
25
|
+
it "returns the name of the cookie" do
|
26
|
+
cookie.name.should == "token"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#name_and_value" do
|
31
|
+
it "returns the name and value of the cookie" do
|
32
|
+
cookie.name_and_value.should == "token=choc-choc-chip"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "httpi"
|
3
|
+
|
4
|
+
describe HTTPI::CookieStore do
|
5
|
+
|
6
|
+
let(:user_cookie) { some_cookie(:user, "chucknorris") }
|
7
|
+
let(:token_cookie) { some_cookie(:token, "strawberry") }
|
8
|
+
|
9
|
+
it "stores a set of cookies" do
|
10
|
+
cookie_store = HTTPI::CookieStore.new
|
11
|
+
cookie_store.add(user_cookie, token_cookie)
|
12
|
+
cookie_store.fetch.should include("user=chucknorris", "token=strawberry")
|
13
|
+
|
14
|
+
# add a new token cookie with a different value
|
15
|
+
token_cookie = some_cookie(:token, "choc-choc-chip")
|
16
|
+
cookie_store.add(token_cookie)
|
17
|
+
|
18
|
+
cookie_store.fetch.should include("token=choc-choc-chip")
|
19
|
+
cookie_store.fetch.should_not include("token=strawberry")
|
20
|
+
end
|
21
|
+
|
22
|
+
def some_cookie(name, value)
|
23
|
+
HTTPI::Cookie.new("#{name}=#{value}; Path=/; HttpOnly")
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
data/spec/httpi/request_spec.rb
CHANGED
@@ -100,6 +100,29 @@ describe HTTPI::Request do
|
|
100
100
|
end
|
101
101
|
end
|
102
102
|
|
103
|
+
describe "#set_cookies" do
|
104
|
+
it "sets the cookie header for the next request" do
|
105
|
+
request.set_cookies response_with_cookie("some-cookie=choc-chip")
|
106
|
+
request.headers["Cookie"].should == "some-cookie=choc-chip"
|
107
|
+
end
|
108
|
+
|
109
|
+
it "sets additional cookies from subsequent requests" do
|
110
|
+
request.set_cookies response_with_cookie("some-cookie=choc-chip")
|
111
|
+
request.set_cookies response_with_cookie("second-cookie=oatmeal")
|
112
|
+
|
113
|
+
request.headers["Cookie"].should include("some-cookie=choc-chip", "second-cookie=oatmeal")
|
114
|
+
end
|
115
|
+
|
116
|
+
it "doesn't do anything if the response contains no cookies" do
|
117
|
+
request.set_cookies HTTPI::Response.new(200, {}, "")
|
118
|
+
request.headers["Cookie"].should be_nil
|
119
|
+
end
|
120
|
+
|
121
|
+
def response_with_cookie(cookie)
|
122
|
+
HTTPI::Response.new(200, { "Set-Cookie" => "#{cookie}; Path=/; HttpOnly" }, "")
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
103
126
|
describe "#body" do
|
104
127
|
it "lets you specify the HTTP request body using a String" do
|
105
128
|
request.body = "<some>xml</some>"
|
data/spec/httpi/response_spec.rb
CHANGED
@@ -34,6 +34,23 @@ describe HTTPI::Response do
|
|
34
34
|
response.should_not be_multipart
|
35
35
|
end
|
36
36
|
end
|
37
|
+
|
38
|
+
describe "#cookies" do
|
39
|
+
it "returns an empty list" do
|
40
|
+
response.cookies.should == []
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "with cookies" do
|
46
|
+
let(:response) { HTTPI::Response.new 200, { "Set-Cookie" => "some-cookie=choc-chip; Path=/; HttpOnly" }, "" }
|
47
|
+
|
48
|
+
describe "#cookies" do
|
49
|
+
it "returns a list of cookies" do
|
50
|
+
cookie = response.cookies.first
|
51
|
+
cookie.should be_a(HTTPI::Cookie)
|
52
|
+
end
|
53
|
+
end
|
37
54
|
end
|
38
55
|
|
39
56
|
context "empty" do
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: httpi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
+
- 1
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 1.0.0
|
10
|
+
version: 1.1.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Daniel Harrington
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2012-06-
|
19
|
+
date: 2012-06-28 00:00:00 Z
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
22
|
version_requirements: &id001 !ruby/object:Gem::Requirement
|
@@ -150,6 +150,8 @@ files:
|
|
150
150
|
- lib/httpi/adapter/net_http.rb
|
151
151
|
- lib/httpi/auth/config.rb
|
152
152
|
- lib/httpi/auth/ssl.rb
|
153
|
+
- lib/httpi/cookie.rb
|
154
|
+
- lib/httpi/cookie_store.rb
|
153
155
|
- lib/httpi/dime.rb
|
154
156
|
- lib/httpi/request.rb
|
155
157
|
- lib/httpi/response.rb
|
@@ -167,6 +169,8 @@ files:
|
|
167
169
|
- spec/httpi/adapter_spec.rb
|
168
170
|
- spec/httpi/auth/config_spec.rb
|
169
171
|
- spec/httpi/auth/ssl_spec.rb
|
172
|
+
- spec/httpi/cookie_spec.rb
|
173
|
+
- spec/httpi/cookie_store_spec.rb
|
170
174
|
- spec/httpi/httpi_spec.rb
|
171
175
|
- spec/httpi/request_spec.rb
|
172
176
|
- spec/httpi/response_spec.rb
|