httpi-ntlm 0.9.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/.autotest +5 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +8 -0
  5. data/CHANGELOG.md +69 -0
  6. data/Gemfile +9 -0
  7. data/LICENSE +20 -0
  8. data/README.md +223 -0
  9. data/Rakefile +18 -0
  10. data/autotest/discover.rb +1 -0
  11. data/httpi-ntlm.gemspec +27 -0
  12. data/lib/httpi-ntlm.rb +1 -0
  13. data/lib/httpi.rb +198 -0
  14. data/lib/httpi/adapter.rb +67 -0
  15. data/lib/httpi/adapter/curb.rb +125 -0
  16. data/lib/httpi/adapter/httpclient.rb +98 -0
  17. data/lib/httpi/adapter/net_http.rb +117 -0
  18. data/lib/httpi/auth/config.rb +81 -0
  19. data/lib/httpi/auth/ssl.rb +91 -0
  20. data/lib/httpi/dime.rb +56 -0
  21. data/lib/httpi/request.rb +90 -0
  22. data/lib/httpi/response.rb +85 -0
  23. data/lib/httpi/version.rb +5 -0
  24. data/spec/fixtures/attachment.gif +0 -0
  25. data/spec/fixtures/client_cert.pem +16 -0
  26. data/spec/fixtures/client_key.pem +15 -0
  27. data/spec/fixtures/xml.gz +0 -0
  28. data/spec/fixtures/xml.xml +10 -0
  29. data/spec/fixtures/xml_dime.dime +0 -0
  30. data/spec/fixtures/xml_dime.xml +1 -0
  31. data/spec/httpi/adapter/curb_spec.rb +232 -0
  32. data/spec/httpi/adapter/httpclient_spec.rb +164 -0
  33. data/spec/httpi/adapter/net_http_spec.rb +142 -0
  34. data/spec/httpi/adapter_spec.rb +55 -0
  35. data/spec/httpi/auth/config_spec.rb +117 -0
  36. data/spec/httpi/auth/ssl_spec.rb +128 -0
  37. data/spec/httpi/httpi_spec.rb +284 -0
  38. data/spec/httpi/request_spec.rb +135 -0
  39. data/spec/httpi/response_spec.rb +125 -0
  40. data/spec/integration/request_spec.rb +95 -0
  41. data/spec/integration/server.rb +39 -0
  42. data/spec/spec_helper.rb +12 -0
  43. data/spec/support/fixture.rb +27 -0
  44. data/spec/support/matchers.rb +19 -0
  45. metadata +200 -0
@@ -0,0 +1,67 @@
1
+ require "httpi/adapter/httpclient"
2
+ require "httpi/adapter/curb"
3
+ require "httpi/adapter/net_http"
4
+
5
+ module HTTPI
6
+
7
+ # = HTTPI::Adapter
8
+ #
9
+ # Manages the adapter classes. Currently supports:
10
+ #
11
+ # * httpclient
12
+ # * curb
13
+ # * net/http
14
+ module Adapter
15
+
16
+ ADAPTERS = {
17
+ :httpclient => { :class => HTTPClient, :dependencies => ["httpclient"] },
18
+ :curb => { :class => Curb, :dependencies => ["curb"] },
19
+ :net_http => { :class => NetHTTP, :dependencies => ["net/https", "net/ntlm_http"] }
20
+ }
21
+
22
+ LOAD_ORDER = [:httpclient, :curb, :net_http]
23
+
24
+ class << self
25
+
26
+ def use=(adapter)
27
+ return @adapter = nil if adapter.nil?
28
+
29
+ validate_adapter! adapter
30
+ load_dependencies adapter
31
+ @adapter = adapter
32
+ end
33
+
34
+ def use
35
+ @adapter ||= default_adapter
36
+ end
37
+
38
+ def load(adapter)
39
+ adapter = adapter ? validate_adapter!(adapter) : use
40
+ [adapter, ADAPTERS[adapter][:class]]
41
+ end
42
+
43
+ private
44
+
45
+ def validate_adapter!(adapter)
46
+ raise ArgumentError, "Invalid HTTPI adapter: #{adapter}" unless ADAPTERS[adapter]
47
+ adapter
48
+ end
49
+
50
+ def default_adapter
51
+ LOAD_ORDER.each do |adapter|
52
+ begin
53
+ load_dependencies adapter
54
+ return adapter
55
+ rescue LoadError
56
+ next
57
+ end
58
+ end
59
+ end
60
+
61
+ def load_dependencies(adapter)
62
+ ADAPTERS[adapter][:dependencies].each { |dependency| require dependency }
63
+ end
64
+
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,125 @@
1
+ require "httpi/response"
2
+
3
+ module HTTPI
4
+ module Adapter
5
+
6
+ # = HTTPI::Adapter::Curb
7
+ #
8
+ # Adapter for the Curb client.
9
+ # http://rubygems.org/gems/curb
10
+ class Curb
11
+
12
+ def initialize(request = nil)
13
+ end
14
+
15
+ # Returns a memoized <tt>Curl::Easy</tt> instance.
16
+ def client
17
+ @client ||= Curl::Easy.new
18
+ end
19
+
20
+ # Executes an HTTP GET request.
21
+ # @see HTTPI.get
22
+ def get(request)
23
+ do_request(request) { |client| client.http_get }
24
+ end
25
+
26
+ # Executes an HTTP POST request.
27
+ # @see HTTPI.post
28
+ def post(request)
29
+ do_request(request) { |client| client.http_post request.body }
30
+ end
31
+
32
+ # Executes an HTTP HEAD request.
33
+ # @see HTTPI.head
34
+ def head(request)
35
+ do_request(request) { |client| client.http_head }
36
+ end
37
+
38
+ # Executes an HTTP PUT request.
39
+ # @see HTTPI.put
40
+ def put(request)
41
+ do_request(request) { |client| client.http_put request.body }
42
+ end
43
+
44
+ # Executes an HTTP DELETE request.
45
+ # @see HTTPI.delete
46
+ def delete(request)
47
+ do_request(request) { |client| client.http_delete }
48
+ end
49
+
50
+ private
51
+
52
+ def do_request(request)
53
+ setup_client request
54
+ yield client
55
+ respond_with client
56
+ end
57
+
58
+ def setup_client(request)
59
+ basic_setup request
60
+ setup_http_auth request if request.auth.http?
61
+ setup_ssl_auth request.auth.ssl if request.auth.ssl?
62
+ setup_ntlm_auth request if request.auth.ntlm?
63
+ end
64
+
65
+ def basic_setup(request)
66
+ client.url = request.url.to_s
67
+ client.proxy_url = request.proxy.to_s if request.proxy
68
+ client.timeout = request.read_timeout if request.read_timeout
69
+ client.connect_timeout = request.open_timeout if request.open_timeout
70
+ client.headers = request.headers.to_hash
71
+ client.verbose = false
72
+ end
73
+
74
+ def setup_http_auth(request)
75
+ client.http_auth_types = request.auth.type
76
+ client.username, client.password = *request.auth.credentials
77
+ end
78
+
79
+ def setup_ssl_auth(ssl)
80
+ client.cert_key = ssl.cert_key_file
81
+ client.cert = ssl.cert_file
82
+ client.cacert = ssl.ca_cert_file if ssl.ca_cert_file
83
+ client.certtype = ssl.cert_type.to_s.upcase
84
+ client.ssl_verify_peer = ssl.verify_mode == :peer
85
+ end
86
+
87
+ def setup_ntlm_auth(request)
88
+ client.username, client.password = *request.auth.credentials
89
+ client.http_auth_types = request.auth.type
90
+ end
91
+
92
+ def respond_with(client)
93
+ status, headers = parse_header_string(client.header_str)
94
+ Response.new client.response_code, headers, client.body_str
95
+ end
96
+
97
+ # Borrowed from Webmock's Curb adapter:
98
+ # http://github.com/bblimke/webmock/blob/master/lib/webmock/http_lib_adapters/curb.rb
99
+ def parse_header_string(header_string)
100
+ status, headers = nil, {}
101
+ return [status, headers] unless header_string
102
+
103
+ header_string.split(/\r\n/).each do |header|
104
+ if header =~ %r|^HTTP/1.[01] \d\d\d (.*)|
105
+ status = $1
106
+ else
107
+ parts = header.split(':', 2)
108
+ unless parts.empty?
109
+ parts[1].strip! unless parts[1].nil?
110
+ if headers.has_key?(parts[0])
111
+ headers[parts[0]] = [headers[parts[0]]] unless headers[parts[0]].kind_of? Array
112
+ headers[parts[0]] << parts[1]
113
+ else
114
+ headers[parts[0]] = parts[1]
115
+ end
116
+ end
117
+ end
118
+ end
119
+
120
+ [status, headers]
121
+ end
122
+
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,98 @@
1
+ require "httpi/response"
2
+
3
+ module HTTPI
4
+ module Adapter
5
+
6
+ # = HTTPI::Adapter::HTTPClient
7
+ #
8
+ # Adapter for the HTTPClient client.
9
+ # http://rubygems.org/gems/httpclient
10
+ class HTTPClient
11
+
12
+ def initialize(request = nil)
13
+ end
14
+
15
+ # Returns a memoized <tt>HTTPClient</tt> instance.
16
+ def client
17
+ @client ||= ::HTTPClient.new
18
+ end
19
+
20
+ # Executes an HTTP GET request.
21
+ # @see HTTPI.get
22
+ def get(request)
23
+ do_request request do |url, headers|
24
+ client.get url, nil, headers
25
+ end
26
+ end
27
+
28
+ # Executes an HTTP POST request.
29
+ # @see HTTPI.post
30
+ def post(request)
31
+ do_request request do |url, headers, body|
32
+ client.post url, body, headers
33
+ end
34
+ end
35
+
36
+ # Executes an HTTP HEAD request.
37
+ # @see HTTPI.head
38
+ def head(request)
39
+ do_request request do |url, headers|
40
+ client.head url, nil, headers
41
+ end
42
+ end
43
+
44
+ # Executes an HTTP PUT request.
45
+ # @see HTTPI.put
46
+ def put(request)
47
+ do_request request do |url, headers, body|
48
+ client.put url, body, headers
49
+ end
50
+ end
51
+
52
+ # Executes an HTTP DELETE request.
53
+ # @see HTTPI.delete
54
+ def delete(request)
55
+ do_request request do |url, headers|
56
+ client.delete url, headers
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ def do_request(request)
63
+ setup_client request
64
+ respond_with yield(request.url, request.headers, request.body)
65
+ end
66
+
67
+ def setup_client(request)
68
+ basic_setup request
69
+ setup_auth request if request.auth.http? || request.auth.ntlm?
70
+ setup_ssl_auth request.auth.ssl if request.auth.ssl?
71
+ end
72
+
73
+ def basic_setup(request)
74
+ client.proxy = request.proxy if request.proxy
75
+ client.connect_timeout = request.open_timeout if request.open_timeout
76
+ client.receive_timeout = request.read_timeout if request.read_timeout
77
+ end
78
+
79
+ def setup_auth(request)
80
+ client.set_auth request.url, *request.auth.credentials
81
+ end
82
+
83
+ def setup_ssl_auth(ssl)
84
+ unless ssl.verify_mode == :none
85
+ client.ssl_config.client_cert = ssl.cert
86
+ client.ssl_config.client_key = ssl.cert_key
87
+ client.ssl_config.client_ca = ssl.ca_cert if ssl.ca_cert_file
88
+ end
89
+ client.ssl_config.verify_mode = ssl.openssl_verify_mode
90
+ end
91
+
92
+ def respond_with(response)
93
+ Response.new response.code, Hash[*response.header.all.flatten], response.content
94
+ end
95
+
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,117 @@
1
+ require "uri"
2
+ require "httpi/response"
3
+
4
+ module HTTPI
5
+ module Adapter
6
+
7
+ # = HTTPI::Adapter::NetHTTP
8
+ #
9
+ # Adapter for the Net::HTTP client.
10
+ # http://ruby-doc.org/stdlib/libdoc/net/http/rdoc/
11
+ class NetHTTP
12
+
13
+ def initialize(request)
14
+ self.client = new_client request
15
+ end
16
+
17
+ attr_reader :client
18
+
19
+ # Executes an HTTP GET request.
20
+ # @see HTTPI.get
21
+ def get(request)
22
+ do_request :get, request do |http, get|
23
+ http.request get
24
+ end
25
+ end
26
+
27
+ # Executes an HTTP POST request.
28
+ # @see HTTPI.post
29
+ def post(request)
30
+ do_request :post, request do |http, post|
31
+ post.body = request.body
32
+ http.request post
33
+ end
34
+ end
35
+
36
+ # Executes an HTTP HEAD request.
37
+ # @see HTTPI.head
38
+ def head(request)
39
+ do_request :head, request do |http, head|
40
+ http.request head
41
+ end
42
+ end
43
+
44
+ # Executes an HTTP PUT request.
45
+ # @see HTTPI.put
46
+ def put(request)
47
+ do_request :put, request do |http, put|
48
+ put.body = request.body
49
+ http.request put
50
+ end
51
+ end
52
+
53
+ # Executes an HTTP DELETE request.
54
+ # @see HTTPI.delete
55
+ def delete(request)
56
+ do_request :delete, request do |http, delete|
57
+ http.request delete
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ attr_writer :client
64
+
65
+ def new_client(request)
66
+ proxy = request.proxy || URI("")
67
+ Net::HTTP::Proxy(proxy.host, proxy.port).new request.url.host, request.url.port
68
+ end
69
+
70
+ def do_request(type, request)
71
+ setup_client request
72
+ setup_ssl_auth request.auth.ssl if request.auth.ssl?
73
+
74
+ respond_with(client.start do |http|
75
+ yield http, request_client(type, request)
76
+ end)
77
+ end
78
+
79
+ def setup_client(request)
80
+ client.use_ssl = request.ssl?
81
+ client.open_timeout = request.open_timeout if request.open_timeout
82
+ client.read_timeout = request.read_timeout if request.read_timeout
83
+ end
84
+
85
+ def setup_ssl_auth(ssl)
86
+ client.key = ssl.cert_key
87
+ client.cert = ssl.cert
88
+ client.ca_file = ssl.ca_cert_file if ssl.ca_cert_file
89
+ client.verify_mode = ssl.openssl_verify_mode
90
+ end
91
+
92
+ def request_client(type, request)
93
+ request_class = case type
94
+ when :get then Net::HTTP::Get
95
+ when :post then Net::HTTP::Post
96
+ when :head then Net::HTTP::Head
97
+ when :put then Net::HTTP::Put
98
+ when :delete then Net::HTTP::Delete
99
+ end
100
+
101
+ request_client = request_class.new request.url.request_uri, request.headers
102
+
103
+ request_client.basic_auth *request.auth.credentials if request.auth.basic?
104
+ request_client.ntlm_auth *request.auth.credentials if request.auth.ntlm?
105
+
106
+ request_client
107
+ end
108
+
109
+ def respond_with(response)
110
+ headers = response.to_hash
111
+ headers.each { |key, value| headers[key] = value[0] }
112
+ Response.new response.code, headers, response.body
113
+ end
114
+
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,81 @@
1
+ require "httpi/auth/ssl"
2
+
3
+ module HTTPI
4
+ module Auth
5
+
6
+ # = HTTPI::Auth::Config
7
+ #
8
+ # Manages HTTP and SSL auth configuration. Currently supports HTTP basic/digest
9
+ # and SSL client authentication.
10
+ class Config
11
+
12
+ # Supported authentication types.
13
+ TYPES = [:basic, :digest, :ssl, :ntlm]
14
+
15
+ # Accessor for the HTTP basic auth credentials.
16
+ def basic(*args)
17
+ return @basic if args.empty?
18
+
19
+ self.type = :basic
20
+ @basic = args.flatten.compact
21
+ end
22
+
23
+ # Returns whether to use HTTP basic auth.
24
+ def basic?
25
+ type == :basic
26
+ end
27
+
28
+ # Accessor for the HTTP digest auth credentials.
29
+ def digest(*args)
30
+ return @digest if args.empty?
31
+
32
+ self.type = :digest
33
+ @digest = args.flatten.compact
34
+ end
35
+
36
+ # Returns whether to use HTTP digest auth.
37
+ def digest?
38
+ type == :digest
39
+ end
40
+
41
+ # Returns whether to use HTTP basic or dihest auth.
42
+ def http?
43
+ type == :basic || type == :digest
44
+ end
45
+
46
+ # Accessor for the NTLM auth credentials.
47
+ def ntlm(*args)
48
+ return @ntlm if args.empty?
49
+
50
+ self.type = :ntlm
51
+ @ntlm = args.flatten.compact
52
+ end
53
+
54
+ # Returns whether to use NTLM auth.
55
+ def ntlm?
56
+ type == :ntlm
57
+ end
58
+
59
+ # Returns the <tt>HTTPI::Auth::SSL</tt> object.
60
+ def ssl
61
+ @ssl ||= SSL.new
62
+ end
63
+
64
+ # Returns whether to use SSL client auth.
65
+ def ssl?
66
+ ssl.present?
67
+ end
68
+
69
+ # Shortcut method for returning the credentials for the authentication specified.
70
+ # Returns +nil+ unless any authentication credentials were specified.
71
+ def credentials
72
+ return unless type
73
+ send type
74
+ end
75
+
76
+ # Accessor for the authentication type in use.
77
+ attr_accessor :type
78
+
79
+ end
80
+ end
81
+ end