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 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
@@ -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 File.read(cert_key_file)
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
@@ -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 ||= gzipped_response? ? decoded_body : raw_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 decoded_body
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
@@ -1,5 +1,5 @@
1
1
  module HTTPI
2
2
 
3
- VERSION = "0.6.1"
3
+ VERSION = "0.7.0"
4
4
 
5
5
  end
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>
@@ -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.gzip }
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
@@ -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: 5
4
+ hash: 3
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 6
9
- - 1
10
- version: 0.6.1
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-01 00:00:00 +01:00
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