httpi 0.6.1 → 0.7.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/README.md +3 -0
- data/lib/httpi/auth/ssl.rb +4 -1
- data/lib/httpi/dime.rb +56 -0
- data/lib/httpi/response.rb +27 -3
- data/lib/httpi/version.rb +1 -1
- data/spec/fixtures/attachment.gif +0 -0
- data/spec/fixtures/xml_dime.dime +0 -0
- data/spec/fixtures/xml_dime.xml +1 -0
- data/spec/httpi/response_spec.rb +35 -1
- data/spec/support/fixture.rb +8 -0
- metadata +9 -5
data/README.md
CHANGED
@@ -139,6 +139,7 @@ HTTPI::Auth::SSL
|
|
139
139
|
|
140
140
|
request = HTTPI::Request.new
|
141
141
|
request.auth.ssl.cert_key_file = "client_key.pem"
|
142
|
+
request.auth.ssl.cert_key_password = "C3rtP@ssw0rd"
|
142
143
|
request.auth.ssl.cert_file = "client_cert.pem"
|
143
144
|
request.auth.ssl.verify_mode = :none
|
144
145
|
|
@@ -168,6 +169,8 @@ It contains the response code, headers and body.
|
|
168
169
|
response.headers # => { "Content-Encoding" => "gzip" }
|
169
170
|
response.body # => "<!DOCTYPE HTML PUBLIC ...>"
|
170
171
|
|
172
|
+
The `response.body` handles gzipped and [DIME](http://en.wikipedia.org/wiki/Direct_Internet_Message_Encapsulation) encoded responses.
|
173
|
+
|
171
174
|
### TODO
|
172
175
|
|
173
176
|
* Return the original `HTTPI::Request` for debugging purposes
|
data/lib/httpi/auth/ssl.rb
CHANGED
@@ -20,6 +20,9 @@ module HTTPI
|
|
20
20
|
# Accessor for the cert key file to validate SSL certificates.
|
21
21
|
attr_accessor :cert_key_file
|
22
22
|
|
23
|
+
# Accessor for the cert key password to validate SSL certificates.
|
24
|
+
attr_accessor :cert_key_password
|
25
|
+
|
23
26
|
# Accessor for the cert file to validate SSL connections.
|
24
27
|
attr_accessor :cert_file
|
25
28
|
|
@@ -55,7 +58,7 @@ module HTTPI
|
|
55
58
|
|
56
59
|
# Returns an <tt>OpenSSL::PKey::RSA</tt> for the +cert_key_file+.
|
57
60
|
def cert_key
|
58
|
-
@cert_key ||= OpenSSL::PKey::RSA.new
|
61
|
+
@cert_key ||= OpenSSL::PKey::RSA.new(File.read(cert_key_file), cert_key_password)
|
59
62
|
end
|
60
63
|
|
61
64
|
# Sets the +OpenSSL+ certificate key.
|
data/lib/httpi/dime.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
module HTTPI
|
2
|
+
class DimeRecord < Struct.new('DimeRecord', :version, :first, :last, :chunked, :type_format, :options, :id, :type, :data)
|
3
|
+
end
|
4
|
+
|
5
|
+
class Dime < Array
|
6
|
+
BINARY = 1
|
7
|
+
XML = 2
|
8
|
+
|
9
|
+
def initialize(body)
|
10
|
+
bytes = body.unpack('C*')
|
11
|
+
|
12
|
+
while bytes.length > 0
|
13
|
+
record = DimeRecord.new
|
14
|
+
|
15
|
+
# Shift out bitfields for the first fields
|
16
|
+
byte = bytes.shift
|
17
|
+
record.version = (byte >> 3) & 31 # 5 bits DIME format version (always 1)
|
18
|
+
record.first = (byte >> 2) & 1 # 1 bit Set if this is the first part in the message
|
19
|
+
record.last = (byte >> 1) & 1 # 1 bit Set if this is the last part in the message
|
20
|
+
record.chunked = byte & 1 # 1 bit This file is broken into chunked parts
|
21
|
+
record.type_format = (bytes.shift >> 4) & 15 # 4 bits Type of file in the part (1 for binary data, 2 for XML)
|
22
|
+
# 4 bits Reserved (skipped in the above command)
|
23
|
+
|
24
|
+
# Fetch big-endian lengths
|
25
|
+
lengths = [] # we can't use a hash since the order will be screwed in Ruby 1.8
|
26
|
+
lengths << [:options, (bytes.shift << 8) | bytes.shift] # 2 bytes Length of the "options" field
|
27
|
+
lengths << [:id, (bytes.shift << 8) | bytes.shift] # 2 bytes Length of the "ID" or "name" field
|
28
|
+
lengths << [:type, (bytes.shift << 8) | bytes.shift] # 2 bytes Length of the "type" field
|
29
|
+
lengths << [:data, (bytes.shift << 24) | (bytes.shift << 16) | (bytes.shift << 8) | bytes.shift] # 4 bytes Size of the included file
|
30
|
+
|
31
|
+
# Read in padded data
|
32
|
+
lengths.each do |attribute_set|
|
33
|
+
attribute, length = attribute_set
|
34
|
+
content = bytes.slice!(0, length).pack('C*')
|
35
|
+
if attribute == :data && record.type_format == BINARY
|
36
|
+
content = StringIO.new(content)
|
37
|
+
end
|
38
|
+
|
39
|
+
record.send "#{attribute.to_s}=", content
|
40
|
+
|
41
|
+
bytes.slice!(0, 4 - (length & 3)) if (length & 3) != 0
|
42
|
+
end
|
43
|
+
|
44
|
+
self << record
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def xml_records
|
49
|
+
select { |r| r.type_format == XML }
|
50
|
+
end
|
51
|
+
|
52
|
+
def binary_records
|
53
|
+
select { |r| r.type_format == BINARY }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/httpi/response.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "zlib"
|
2
2
|
require "stringio"
|
3
|
+
require "httpi/dime"
|
3
4
|
|
4
5
|
module HTTPI
|
5
6
|
|
@@ -18,34 +19,57 @@ module HTTPI
|
|
18
19
|
self.raw_body = body
|
19
20
|
end
|
20
21
|
|
21
|
-
attr_accessor :code, :headers, :raw_body
|
22
|
+
attr_accessor :code, :headers, :raw_body, :attachments
|
22
23
|
|
23
24
|
# Returns whether the HTTP response is considered successful.
|
24
25
|
def error?
|
25
26
|
!SuccessfulResponseCodes.include? code.to_i
|
26
27
|
end
|
27
28
|
|
29
|
+
def attachments
|
30
|
+
decode_body unless @body
|
31
|
+
@attachments ||= []
|
32
|
+
end
|
33
|
+
|
28
34
|
# Returns the HTTP response body.
|
29
35
|
def body
|
30
|
-
@body
|
36
|
+
decode_body unless @body
|
37
|
+
@body
|
31
38
|
end
|
32
39
|
|
33
40
|
attr_writer :body
|
34
41
|
|
35
42
|
private
|
36
43
|
|
44
|
+
def decode_body
|
45
|
+
body = gzipped_response? ? decoded_gzip_body : raw_body
|
46
|
+
@body = dime_response? ? decoded_dime_body(body) : body
|
47
|
+
end
|
48
|
+
|
37
49
|
# Returns whether the response is gzipped.
|
38
50
|
def gzipped_response?
|
39
51
|
headers["Content-Encoding"] == "gzip" || raw_body[0..1] == "\x1f\x8b"
|
40
52
|
end
|
41
53
|
|
54
|
+
# Returns whether this is a DIME response.
|
55
|
+
def dime_response?
|
56
|
+
headers['Content-Type'] == 'application/dime'
|
57
|
+
end
|
58
|
+
|
42
59
|
# Returns the gzip decoded response body.
|
43
|
-
def
|
60
|
+
def decoded_gzip_body
|
44
61
|
gzip = Zlib::GzipReader.new StringIO.new(raw_body)
|
45
62
|
gzip.read
|
46
63
|
ensure
|
47
64
|
gzip.close
|
48
65
|
end
|
49
66
|
|
67
|
+
# Returns the DIME decoded response body.
|
68
|
+
def decoded_dime_body(body = nil)
|
69
|
+
dime = Dime.new(body || raw_body)
|
70
|
+
self.attachments = dime.binary_records
|
71
|
+
dime.xml_records.first.data
|
72
|
+
end
|
73
|
+
|
50
74
|
end
|
51
75
|
end
|
data/lib/httpi/version.rb
CHANGED
Binary file
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Body><getFileResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><getFileReturn href="#id0"/></getFileResponse><multiRef id="id0" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns1:FileVW" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="http://ws"><created xsi:type="xsd:dateTime">2010-10-27T22:00:00.000Z</created><id xsi:type="xsd:int">2181136</id><lastUpdated xsi:type="xsd:dateTime">2010-10-27T22:00:00.000Z</lastUpdated><metadata href="#id1"/><name xsi:type="xsd:string">attachment.gif</name><size xsi:type="xsd:long">80</size><type xsi:type="xsd:string">gif</type><version xsi:type="xsd:long">1</version></multiRef><multiRef id="id1" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns2:MetadataVW" xmlns:ns2="http://ws" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"><CR_Latest xsi:type="xsd:boolean">true</CR_Latest><MD5 xsi:type="xsd:string">0xC11FE5DB260A89160FFF4EC26630EEB8</MD5><PSize xsi:type="xsd:string" xsi:nil="true"/><category xsi:type="xsd:string">1</category><completionRate xsi:type="xsd:int">1</completionRate><date xsi:type="xsd:string" xsi:nil="true"/><docNo xsi:type="xsd:string"></docNo><filesId xsi:type="xsd:int">2181136</filesId><init xsi:type="xsd:string"></init><locked xsi:type="xsd:boolean">false</locked><mdate xsi:type="xsd:dateTime">2010-10-28T20:27:00.000Z</mdate><meta1 xsi:type="xsd:string" xsi:nil="true"/><meta10 xsi:type="xsd:string" xsi:nil="true"/><meta11 xsi:type="xsd:string" xsi:nil="true"/><meta12 xsi:type="xsd:string" xsi:nil="true"/><meta13 xsi:type="xsd:string" xsi:nil="true"/><meta14 xsi:type="xsd:string" xsi:nil="true"/><meta15 xsi:type="xsd:string" xsi:nil="true"/><meta16 xsi:type="xsd:string" xsi:nil="true"/><meta17 xsi:type="xsd:string" xsi:nil="true"/><meta18 xsi:type="xsd:string" xsi:nil="true"/><meta19 xsi:type="xsd:string" xsi:nil="true"/><meta2 xsi:type="xsd:string" xsi:nil="true"/><meta20 xsi:type="xsd:string" xsi:nil="true"/><meta3 xsi:type="xsd:string" xsi:nil="true"/><meta4 xsi:type="xsd:string" xsi:nil="true"/><meta5 xsi:type="xsd:string" xsi:nil="true"/><meta6 xsi:type="xsd:string" xsi:nil="true"/><meta7 xsi:type="xsd:string" xsi:nil="true"/><meta8 xsi:type="xsd:string" xsi:nil="true"/><meta9 xsi:type="xsd:string" xsi:nil="true"/><note xsi:type="xsd:string" xsi:nil="true"/><ref xsi:type="xsd:string"></ref><ref2 xsi:type="xsd:string" xsi:nil="true"/><ref3 xsi:type="xsd:string" xsi:nil="true"/><ref4 xsi:type="xsd:string" xsi:nil="true"/><revDate xsi:type="xsd:string"></revDate><revName xsi:type="xsd:string"></revName><scale xsi:type="xsd:string" xsi:nil="true"/><scaleUnit xsi:type="xsd:string" xsi:nil="true"/><size xsi:type="xsd:int">80</size><type xsi:type="xsd:string">Document</type><version xsi:type="xsd:int">1</version></multiRef></soapenv:Body></soapenv:Envelope>
|
data/spec/httpi/response_spec.rb
CHANGED
@@ -2,7 +2,7 @@ require "spec_helper"
|
|
2
2
|
require "httpi/response"
|
3
3
|
|
4
4
|
describe HTTPI::Response do
|
5
|
-
let(:response) { HTTPI::Response.new 200, { "Content-Encoding" => "gzip" }, Fixture.
|
5
|
+
let(:response) { HTTPI::Response.new 200, { "Content-Encoding" => "gzip" }, Fixture.xml }
|
6
6
|
|
7
7
|
describe "#code" do
|
8
8
|
it "should return the HTTP response code" do
|
@@ -15,6 +15,11 @@ describe HTTPI::Response do
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
+
end
|
19
|
+
|
20
|
+
describe HTTPI::Response, "gzip" do
|
21
|
+
let(:response) { HTTPI::Response.new 200, { "Content-Encoding" => "gzip" }, Fixture.gzip }
|
22
|
+
|
18
23
|
describe "#headers" do
|
19
24
|
it "should return the HTTP response headers" do
|
20
25
|
response.headers.should == { "Content-Encoding" => "gzip" }
|
@@ -34,3 +39,32 @@ describe HTTPI::Response do
|
|
34
39
|
end
|
35
40
|
|
36
41
|
end
|
42
|
+
|
43
|
+
describe HTTPI::Response, "DIME" do
|
44
|
+
let(:response) { HTTPI::Response.new 200, { "Content-Type" => "application/dime" }, Fixture.dime }
|
45
|
+
|
46
|
+
describe "#headers" do
|
47
|
+
it "should return the HTTP response headers" do
|
48
|
+
response.headers.should == { "Content-Type" => "application/dime" }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#body" do
|
53
|
+
it "should return the (dime decoded) HTTP response body" do
|
54
|
+
response.body.should == Fixture.xml_dime
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "#raw_body" do
|
59
|
+
it "should return the raw HTML response body" do
|
60
|
+
response.raw_body.should == Fixture.dime
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "#attachments" do
|
65
|
+
it "should return proper attachment when given a dime response" do
|
66
|
+
response.attachments.first.data == File.read(File.expand_path("../../fixtures/attachment.gif", __FILE__))
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
data/spec/support/fixture.rb
CHANGED
@@ -5,10 +5,18 @@ class Fixture
|
|
5
5
|
@xml ||= load :xml
|
6
6
|
end
|
7
7
|
|
8
|
+
def xml_dime
|
9
|
+
@xml_dime ||= load :xml_dime
|
10
|
+
end
|
11
|
+
|
8
12
|
def gzip
|
9
13
|
@gzip ||= load :xml, :gz
|
10
14
|
end
|
11
15
|
|
16
|
+
def dime
|
17
|
+
@dime ||= load :xml_dime, :dime
|
18
|
+
end
|
19
|
+
|
12
20
|
private
|
13
21
|
|
14
22
|
def load(fixture, type = :xml)
|
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: 3
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 7
|
9
|
+
- 0
|
10
|
+
version: 0.7.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: 2010-11-
|
19
|
+
date: 2010-11-10 00:00:00 +01:00
|
20
20
|
default_executable:
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
@@ -124,13 +124,17 @@ files:
|
|
124
124
|
- lib/httpi/adapter/net_http.rb
|
125
125
|
- lib/httpi/auth/config.rb
|
126
126
|
- lib/httpi/auth/ssl.rb
|
127
|
+
- lib/httpi/dime.rb
|
127
128
|
- lib/httpi/request.rb
|
128
129
|
- lib/httpi/response.rb
|
129
130
|
- lib/httpi/version.rb
|
131
|
+
- spec/fixtures/attachment.gif
|
130
132
|
- spec/fixtures/client_cert.pem
|
131
133
|
- spec/fixtures/client_key.pem
|
132
134
|
- spec/fixtures/xml.gz
|
133
135
|
- spec/fixtures/xml.xml
|
136
|
+
- spec/fixtures/xml_dime.dime
|
137
|
+
- spec/fixtures/xml_dime.xml
|
134
138
|
- spec/httpi/adapter/curb_spec.rb
|
135
139
|
- spec/httpi/adapter/httpclient_spec.rb
|
136
140
|
- spec/httpi/adapter/net_http_spec.rb
|