[#8136] Confused exception handling in Continuation Context — "Robert Dober" <robert.dober@...>

Hi all

13 messages 2006/07/06

[#8248] One-Click Installer: MinGW? or VC2005? — "Curt Hibbs" <ml.chibbs@...>

I just posted this to ruby-talk. But I would also like to discuss this

33 messages 2006/07/18
[#8264] Re: One-Click Installer: MinGW? or VC2005? — Charlie Savage <cfis@...> 2006/07/19

From my experience using both tool chains on Windows (for the ruby-prof

[#8266] Re: One-Click Installer: MinGW? or VC2005? — "Curt Hibbs" <ml.chibbs@...> 2006/07/19

Tim, I'm going to top reply since your post was so long. I'm interested in

[#8267] Re: One-Click Installer: MinGW? or VC2005? — Charlie Savage <cfis@...> 2006/07/19

> Tim, I'm going to top reply since your post was so long. I'm interested in

[#8271] my sandboxing extension!! — why the lucky stiff <ruby-core@...>

I have (what feels like) very exciting news. I finally sat down to code up my

17 messages 2006/07/19

[#8430] Re: doc patch: weakref. — "Berger, Daniel" <Daniel.Berger@...>

> -----Original Message-----

19 messages 2006/07/28
[#8434] Re: doc patch: weakref. — Yukihiro Matsumoto <matz@...> 2006/07/29

Hi,

[#8436] Re: doc patch: weakref. — Daniel Berger <djberg96@...> 2006/07/29

Yukihiro Matsumoto wrote:

[#8437] Re: doc patch: weakref. — Mauricio Fernandez <mfp@...> 2006/07/29

On Sat, Jul 29, 2006 at 07:37:24PM +0900, Daniel Berger wrote:

[#8441] Inconsistency in scoping during module_eval? — "Charles O Nutter" <headius@...>

I have the following code:

18 messages 2006/07/30
[#8442] Re: Inconsistency in scoping during module_eval? — nobu@... 2006/07/30

Hi,

[#8443] Re: Inconsistency in scoping during module_eval? — "Charles O Nutter" <headius@...> 2006/07/30

Why does this:

[#8445] Re: Inconsistency in scoping during module_eval? — Yukihiro Matsumoto <matz@...> 2006/07/30

Hi,

[#8454] Re: Inconsistency in scoping during module_eval? — "Charles O Nutter" <headius@...> 2006/07/31

So to clarify...

[PATCH] - Win32 NTLM/Negotiate Authentication Support for Net::HTTP

From: "Justin Bailey" <jgbailey@...>
Date: 2006-07-20 22:23:57 UTC
List: ruby-core #8327
These two files represent a patch which allows Net::HTTP to authenticate
with a proxy server demanding NTLM/Negotiate authentication on Windows. It
will authenticate as the current user. The authentication is transparent.
Note that open-uri automaticaly gets support for this to.

I hope the format of this patch works. I downloaded the 1_8_5_preview1
sources and took diffs against them. Two diffs are attached because two
separate directories are modified.

lib.patch.txt  adds one file to the lib/net/http directory and modifies
http.rb there.

test.patch.txt adds three files to test/lib/net/http and represents unit
tests for the patch. You must have a proxy server which uses NTLM/Negotiate
authentication handy unfortunately.

Please let me know if I can provide more information.

Justin

p.s. This library is also available on rubyforge as a gem -
http://rubyforge.org/projects/rubysspi/

Attachments (2)

lib.patch.txt (13.6 KB, text/x-diff)
diff -Nu c:\ruby\lib\ruby\1.8\net/http.rb c:\ruby\lib\ruby\1.8\net.1.8.5.preview1/http.rb
--- c:\ruby\lib\ruby\1.8\net/http.rb	2006-07-20 14:26:52.169055700 -0700
+++ c:\ruby\lib\ruby\1.8\net.1.8.5.preview1/http.rb	2006-06-21 19:54:38.000000000 -0700
@@ -1043,25 +1043,6 @@
         begin
           res = HTTPResponse.read_new(@socket)
         end while res.kind_of?(HTTPContinue)
-        # If proxy was specified, and the server is demanding authentication, negotiate with it
-        if res.kind_of?(HTTPProxyAuthenticationRequired) && proxy? && RUBY_PLATFORM.include?("win32") && res["Proxy-Authenticate"].include?("Negotiate")
-          require 'net/rubysspi'
-          n = SSPI::NegotiateAuth.new
-          res.reading_body(@socket, req.response_body_permitted?) { }
-          req["Proxy-Authorization"] = "Negotiate #{n.get_initial_token}"
-          req.exec @socket, @curr_http_version, edit_path(req.path)
-          begin
-            res = HTTPResponse.read_new(@socket)
-          end while res.kind_of?(HTTPContinue)
-          if res["Proxy-Authenticate"]
-            res.reading_body(@socket, req.response_body_permitted?) { }
-            req["Proxy-Authorization"] = "Negotiate #{n.complete_authentication res["Proxy-Authenticate"]}"
-            req.exec @socket, @curr_http_version, edit_path(req.path)
-            begin
-              res = HTTPResponse.read_new(@socket)
-            end while res.kind_of?(HTTPContinue)
-          end
-        end
         res.reading_body(@socket, req.response_body_permitted?) {
           yield res if block_given?
         }
diff -Nu c:\ruby\lib\ruby\1.8\net/rubysspi.rb c:\ruby\lib\ruby\1.8\net.1.8.5.preview1/rubysspi.rb
--- c:\ruby\lib\ruby\1.8\net/rubysspi.rb	2006-07-20 15:11:22.718863300 -0700
+++ c:\ruby\lib\ruby\1.8\net.1.8.5.preview1/rubysspi.rb	1969-12-31 16:00:00.000000000 -0800
@@ -1,332 +0,0 @@
-#
-# = net/rubysspi.rb
-#
-# Copyright (c) 2006 Justin Bailey
-# 
-# Written and maintained by Justin Bailey <jgbailey@gmail.com>.
-#
-# This library implements basic support on Win32 systems for authenticating
-# with proxies which require NTLM/Negotiate authentication. It will authenticate
-# as the currently logged in user. It will not authenticate as an arbitrary user.
-#
-# This program is free software. You can re-distribute and/or
-# modify this program under the same terms of ruby itself ---
-# Ruby Distribution License or GNU General Public License.
-
-require 'Win32API'
-require 'base64'
-
-# Implements bindings to Win32 SSPI functions, focused on authentication to a proxy server over HTTP.
-module SSPI
-  # Specifies how credential structure requested will be used. Only SECPKG_CRED_OUTBOUND is used
-  # here.
-  SECPKG_CRED_INBOUND = 0x00000001
-  SECPKG_CRED_OUTBOUND = 0x00000002
-  SECPKG_CRED_BOTH = 0x00000003
-
-  # Format of token. NETWORK format is used here.
-  SECURITY_NATIVE_DREP = 0x00000010
-  SECURITY_NETWORK_DREP = 0x00000000
-
-  # InitializeSecurityContext Requirement flags
-  ISC_REQ_REPLAY_DETECT = 0x00000004
-  ISC_REQ_SEQUENCE_DETECT = 0x00000008
-  ISC_REQ_CONFIDENTIALITY = 0x00000010
-  ISC_REQ_USE_SESSION_KEY = 0x00000020
-  ISC_REQ_PROMPT_FOR_CREDS = 0x00000040
-  ISC_REQ_CONNECTION = 0x00000800
-
-  # Win32 API Functions. Uses Win32API to bind methods to constants contained in class. 
-  module API
-    # Can be called with AcquireCredentialsHandle.call()
-    AcquireCredentialsHandle = Win32API.new("secur32", "AcquireCredentialsHandle", 'ppLpppppp', 'L')
-    # Can be called with InitializeSecurityContext.call()
-    InitializeSecurityContext = Win32API.new("secur32", "InitializeSecurityContext", 'pppLLLpLpppp', 'L')
-    # Can be called with DeleteSecurityContext.call()
-    DeleteSecurityContext = Win32API.new("secur32", "DeleteSecurityContext", 'P', 'L')
-    # Can be called with FreeCredentialsHandle.call()
-    FreeCredentialsHandle = Win32API.new("secur32", "FreeCredentialsHandle", 'P', 'L')
-  end
-  
-  # SecHandle struct
-  class SecurityHandle
-    def upper
-      @struct.unpack("LL")[1]
-    end
-    
-    def lower
-      @struct.unpack("LL")[0]
-    end
-    
-    def to_p
-      @struct ||= "\0" * 8
-    end
-  end
-  
-  # Some familiar aliases for the SecHandle structure
-  CredHandle = CtxtHandle = SecurityHandle
-
-  # TimeStamp struct
-  class TimeStamp
-    attr_reader :struct
-
-    def to_p
-      @struct ||= "\0" * 8
-    end
-  end
-  
-  # Creates binary representaiton of a SecBufferDesc structure,
-  # including the SecBuffer contained inside.
-  class SecurityBuffer
-
-    SECBUFFER_TOKEN = 2   # Security token
-    
-    TOKENBUFSIZE = 12288
-    SECBUFFER_VERSION = 0
-
-    def initialize(buffer = nil)
-      @buffer = buffer || "\0" * TOKENBUFSIZE
-      @bufferSize = @buffer.length
-      @type = SECBUFFER_TOKEN
-    end
-    
-    def bufferSize
-      unpack
-      @bufferSize
-    end
-    
-    def bufferType
-      unpack
-      @type
-    end
-    
-    def token
-      unpack
-      @buffer
-    end
-    
-    def to_p
-      # Assumption is that when to_p is called we are going to get a packed structure. Therefore,
-      # set @unpacked back to nil so we know to unpack when accessors are next accessed.
-      @unpacked = nil
-      # Assignment of inner structure to variable is very important here. Without it,
-      # will not be able to unpack changes to the structure. Alternative, nested unpacks,
-      # does not work (i.e. @struct.unpack("LLP12")[2].unpack("LLP12") results in "no associated pointer")
-      @sec_buffer ||= [@bufferSize, @type, @buffer].pack("LLP")
-      @struct ||= [SECBUFFER_VERSION, 1, @sec_buffer].pack("LLP")    
-    end
-  
-  private
-  
-    # Unpacks the SecurityBufferDesc structure into member variables. We
-    # only want to do this once per struct, so the struct is deleted
-    # after unpacking. 
-    def unpack
-      if ! @unpacked && @sec_buffer && @struct
-        @bufferSize, @type = @sec_buffer.unpack("LL")
-        @buffer = @sec_buffer.unpack("LLP#{@bufferSize}")[2]
-        @struct = nil
-        @sec_buffer = nil
-        @unpacked = true
-      end
-    end
-  end
-  
-  # SEC_WINNT_AUTH_IDENTITY structure
-  class Identity
-    SEC_WINNT_AUTH_IDENTITY_ANSI = 0x1
-
-    attr_accessor :user, :domain, :password
-    
-    def initialize(user = nil, domain = nil, password = nil)
-      @user = user
-      @domain = domain
-      @password = password
-      @flags = SEC_WINNT_AUTH_IDENTITY_ANSI
-    end
-    
-    def to_p
-      [@user, @user ? @user.length : 0, 
-       @domain, @domain ? @domain.length : 0,
-       @password, @password ? @password.length : 0,
-       @flags].pack("PLPLPLL")
-    end    
-  end
-
-  # Takes a return result from an SSPI function and interprets the value.
-  class SSPIResult 
-    # Good results
-    SEC_E_OK = 0x00000000
-    SEC_I_CONTINUE_NEEDED = 0x00090312
-
-    # These are generally returned by InitializeSecurityContext
-    SEC_E_INSUFFICIENT_MEMORY = 0x80090300
-    SEC_E_INTERNAL_ERROR = 0x80090304
-    SEC_E_INVALID_HANDLE = 0x80090301
-    SEC_E_INVALID_TOKEN = 0x80090308
-    SEC_E_LOGON_DENIED = 0x8009030C
-    SEC_E_NO_AUTHENTICATING_AUTHORITY = 0x80090311
-    SEC_E_NO_CREDENTIALS = 0x8009030E
-    SEC_E_TARGET_UNKNOWN = 0x80090303
-    SEC_E_UNSUPPORTED_FUNCTION = 0x80090302
-    SEC_E_WRONG_PRINCIPAL = 0x80090322
-
-    # These are generally returned by AcquireCredentialsHandle
-    SEC_E_NOT_OWNER = 0x80090306
-    SEC_E_SECPKG_NOT_FOUND = 0x80090305
-    SEC_E_UNKNOWN_CREDENTIALS = 0x8009030D
-    
-    @@map = {}
-    constants.each { |v| @@map[self.const_get(v.to_s)] = v }
-
-    attr_reader :value
-    
-    def initialize(value)
-      # convert to unsigned long
-      value = [value].pack("L").unpack("L").first
-      raise "#{value.to_s(16)} is not a recognized result" unless @@map.has_key? value
-      @value = value
-    end
-    
-    def to_s
-      @@map[@value].to_s
-    end
-    
-    def ok?
-      @value == SEC_I_CONTINUE_NEEDED || @value == SEC_E_OK
-    end
-    
-    def ==(other)
-      if other.is_a?(SSPIResult)
-        @value == other.value
-      elsif other.is_a?(Fixnum)
-        @value == @@map[other]
-      else
-        false
-      end
-    end
-  end
-
-  # Handles "Negotiate" type authentication. Geared towards authenticating with a proxy server over HTTP
-  class NegotiateAuth  
-    attr_accessor :credentials, :context, :contextAttributes, :user, :domain
-
-    # Default request flags for SSPI functions
-    REQUEST_FLAGS = ISC_REQ_CONFIDENTIALITY | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONNECTION
-
-    # NTLM tokens start with this header always. Encoding alone adds "==" and newline, so remove those
-    B64_TOKEN_PREFIX = Base64.encode64("NTLMSSP").delete("=\n")  
-
-    # Given a connection and a request path, performs authentication as the current user and returns
-    # the response from a GET request. The connnection should be a Net::HTTP object, and it should
-    # have been constructed using the Net::HTTP.Proxy method, but anything that responds to "get" will work.
-    # If a user and domain are given, will authenticate as the given user.
-    # Returns the response received from the get method (usually Net::HTTPResponse)
-    def NegotiateAuth.proxy_auth_get(http, path, user = nil, domain = nil)
-      raise "http must respond to :get" unless http.respond_to?(:get)
-      nego_auth = self.new user, domain
-      
-      resp = http.get path, { "Proxy-Authorization" => "Negotiate " + nego_auth.get_initial_token }
-      if resp["Proxy-Authenticate"]
-        resp = http.get path, { "Proxy-Authorization" => "Negotiate " + nego_auth.complete_authentication(resp["Proxy-Authenticate"].split(" ").last.strip) }
-      end
-
-      resp
-    end
-    
-    # Creates a new instance ready for authentication as the given user in the given domain.
-    # Defaults to current user and domain as defined by ENV["USERDOMAIN"] and ENV["USERNAME"] if
-    # no arguments are supplied.
-    def initialize(user = nil, domain = nil)
-      if user.nil? && domain.nil? && ENV["USERNAME"].nil? && ENV["USERDOMAIN"].nil?
-        raise "A username or domain must be supplied since they cannot be retrieved from the environment"
-      end
-      
-      @user = user || ENV["USERNAME"]
-      @domain = domain || ENV["USERDOMAIN"]
-    end
-
-    # Gets the initial Negotiate token. Returns it as a base64 encoded string suitable for use in HTTP. Can
-    # be easily decoded, however.
-    def get_initial_token
-      raise "This object is no longer usable because its resources have been freed." if @cleaned_up
-      get_credentials
-
-      outputBuffer = SecurityBuffer.new
-      @context = CtxtHandle.new
-      @contextAttributes = "\0" * 4
-
-      result = SSPIResult.new(API::InitializeSecurityContext.call(@credentials.to_p, nil, nil, 
-        REQUEST_FLAGS,0, SECURITY_NETWORK_DREP, nil, 0, @context.to_p, outputBuffer.to_p, @contextAttributes, TimeStamp.new.to_p))
-
-      if result.ok? then
-        return encode_token(outputBuffer.token)
-      else
-        raise "Error: #{result.to_s}"
-      end
-    end
-    
-    # Takes a token and gets the next token in the Negotiate authentication chain. Token can be Base64 encoded or not. 
-    # The token can include the "Negotiate" header and it will be stripped.
-    # Does not indicate if SEC_I_CONTINUE or SEC_E_OK was returned.
-    # Token returned is Base64 encoded w/ all new lines removed.
-    def complete_authentication(token)
-      raise "This object is no longer usable because its resources have been freed." if @cleaned_up
-
-      # Nil token OK, just set it to empty string      
-      token = "" if token.nil?
-
-      if token.include? "Negotiate"
-        # If the Negotiate prefix is passed in, assume we are seeing "Negotiate <token>" and get the token.
-        token = token.split(" ").last
-      end
-
-      if token.include? B64_TOKEN_PREFIX 
-        # indicates base64 encoded token
-        token = Base64.decode64(token.strip)
-      end
-      
-      outputBuffer = SecurityBuffer.new
-      result = SSPIResult.new(API::InitializeSecurityContext.call(@credentials.to_p, @context.to_p, nil, 
-        REQUEST_FLAGS, 0, SECURITY_NETWORK_DREP, SecurityBuffer.new(token).to_p, 0, 
-        @context.to_p,
-        outputBuffer.to_p, @contextAttributes, TimeStamp.new.to_p))
-       
-      if result.ok? then
-        return encode_token(outputBuffer.token)
-      else
-        raise "Error: #{result.to_s}"
-      end
-    ensure
-      # need to make sure we don't clean up if we've already cleaned up.
-      clean_up unless @cleaned_up
-    end
-
-   private
-
-    def clean_up
-      # free structures allocated
-      @cleaned_up = true
-      API::FreeCredentialsHandle.call(@credentials.to_p)
-      API::DeleteSecurityContext.call(@context.to_p)
-      @context = nil
-      @credentials = nil
-      @contextAttributes = nil
-    end
-
-    # Gets credentials based on user, domain or both. If both are nil, an error occurs
-    def get_credentials
-      @credentials = CredHandle.new
-      ts = TimeStamp.new
-      @identity = Identity.new @user, @domain
-      result = SSPIResult.new(API::AcquireCredentialsHandle.call(nil, "Negotiate", SECPKG_CRED_OUTBOUND, nil, @identity.to_p, 
-        nil, nil, @credentials.to_p, ts.to_p))
-      raise "Error acquire credentials: #{result}" unless result.ok?
-    end
-
-    def encode_token(t)
-      # encode64 will add newlines every 60 characters so we need to remove those.
-      Base64.encode64(t).delete("\n")
-    end
-  end
-end
test.patch.txt (6.85 KB, text/x-diff)
diff -N -u c:\ruby\src\ruby-1.8.4\test\net\http.1.8.5.preview1/ruby_sspi_test.rb c:\ruby\src\ruby-1.8.4\test\net\http/ruby_sspi_test.rb
--- c:\ruby\src\ruby-1.8.4\test\net\http.1.8.5.preview1/ruby_sspi_test.rb	1969-12-31 16:00:00.000000000 -0800
+++ c:\ruby\src\ruby-1.8.4\test\net\http/ruby_sspi_test.rb	2006-07-20 15:13:29.611112500 -0700
@@ -0,0 +1,87 @@
+#
+# = test/net/http/ruby_sspi_test.rb
+#
+# Copyright (c) 2006 Justin Bailey
+# 
+# Written and maintained by Justin Bailey <jgbailey@gmail.com>.
+#
+# This program is free software. You can re-distribute and/or
+# modify this program under the same terms of ruby itself ---
+# Ruby Distribution License or GNU General Public License.
+
+require 'test/unit'
+require 'net/http'
+require 'net/rubysspi'
+
+# These tests use the SSPI library directly.
+class NTLMTest < Test::Unit::TestCase
+  def test_auth
+    proxy = get_proxy
+    
+    Net::HTTP.start(proxy.host, proxy.port) do |http|
+      nego_auth = SSPI::NegotiateAuth.new 
+      sr = http.request_get "http://www.google.com/", { "Proxy-Authorization" => "Negotiate " + nego_auth.get_initial_token }
+      resp = http.get "http://www.google.com/", { "Proxy-Authorization" => "Negotiate " + nego_auth.complete_authentication(sr["Proxy-Authenticate"].split(" ").last.strip) }
+      assert resp.code.to_i == 200, "Resposne code not as expected: #{resp.inspect}"
+      resp = http.get "http://www.google.com/foobar.html"
+      assert resp.code.to_i == 404, "Response code not as expected: #{resp.inspect}"
+    end
+  end
+  
+  def test_proxy_auth_get
+    proxy = get_proxy
+    
+    Net::HTTP.start(proxy.host, proxy.port) do |http|
+      resp = SSPI::NegotiateAuth.proxy_auth_get http, "http://www.google.com/"
+      assert resp.code.to_i == 200, "Response code not as expected: #{resp.inspect}"
+    end
+  end
+  
+  def test_one_time_use_only
+    proxy = get_proxy
+    
+    Net::HTTP.start(proxy.host, proxy.port) do |http|
+      nego_auth = SSPI::NegotiateAuth.new 
+      sr = http.request_get "http://www.google.com/", { "Proxy-Authorization" => "Negotiate " + nego_auth.get_initial_token }
+      resp = http.get "http://www.google.com/", { "Proxy-Authorization" => "Negotiate " + nego_auth.complete_authentication(sr["Proxy-Authenticate"].split(" ").last.strip) }
+      assert resp.code.to_i == 200, "Response code not as expected: #{resp.inspect}"
+      assert_raises(RuntimeError, "Should not be able to call complete_authentication again") do
+        nego_auth.complete_authentication "foo"
+      end
+    end
+  end
+  
+  def test_token_variations
+    proxy = get_proxy
+
+    # Test that raw token works
+    Net::HTTP.start(proxy.host, proxy.port) do |http|
+      nego_auth = SSPI::NegotiateAuth.new 
+      sr = http.request_get "http://www.google.com/", { "Proxy-Authorization" => "Negotiate " + nego_auth.get_initial_token }
+      token = Base64.decode64(sr["Proxy-Authenticate"].split(" ").last.strip)
+      completed_token = nego_auth.complete_authentication(token)
+      resp = http.get "http://www.google.com/", { "Proxy-Authorization" => "Negotiate " + completed_token }
+      assert resp.code.to_i == 200, "Response code not as expected: #{resp.inspect}"
+    end
+
+    # Test that token w/ "Negotiate" header included works
+    Net::HTTP.start(proxy.host, proxy.port) do |http|
+      nego_auth = SSPI::NegotiateAuth.new 
+      sr = http.request_get "http://www.google.com/", { "Proxy-Authorization" => "Negotiate " + nego_auth.get_initial_token }
+      resp = http.get "http://www.google.com/", { "Proxy-Authorization" => "Negotiate " + nego_auth.complete_authentication(sr["Proxy-Authenticate"]) }
+      assert resp.code.to_i == 200, "Response code not as expected: #{resp.inspect}"
+    end
+  end
+  
+private
+  
+  # Gets the proxy from the environment and makes some assertions
+  def get_proxy
+    assert ENV["http_proxy"], "http_proxy environment variable must be set."
+    proxy = URI.parse(ENV["http_proxy"])
+    assert proxy.host && proxy.port, "Could not parse http_proxy (#{ENV["http_proxy"]}). http_proxy should be a URL with a port (e.g. http://proxy.corp.com:8080)."
+    
+    return proxy
+  end
+  
+end
diff -N -u c:\ruby\src\ruby-1.8.4\test\net\http.1.8.5.preview1/test_gem_list.rb c:\ruby\src\ruby-1.8.4\test\net\http/test_gem_list.rb
--- c:\ruby\src\ruby-1.8.4\test\net\http.1.8.5.preview1/test_gem_list.rb	1969-12-31 16:00:00.000000000 -0800
+++ c:\ruby\src\ruby-1.8.4\test\net\http/test_gem_list.rb	2006-07-20 15:13:23.736037300 -0700
@@ -0,0 +1,30 @@
+#
+# = test/net/http/test_gem_list.rb
+#
+# Copyright (c) 2006 Justin Bailey
+# 
+# Written and maintained by Justin Bailey <jgbailey@gmail.com>.
+#
+# This program is free software. You can re-distribute and/or
+# modify this program under the same terms of ruby itself ---
+# Ruby Distribution License or GNU General Public License.
+
+require 'test/unit'
+require 'net/http'
+require 'rubygems'
+
+class NTLMTest < Test::Unit::TestCase
+  def setup
+    assert ENV["http_proxy"], "http_proxy must be set before running tests."
+  end
+  
+  # Previous implementation of rubysspi used dl/win32 and a
+  # bug occurred when gem list was executed. This tests to ensure
+  # bug does not come back.
+  def test_gem_list
+    Gem.manage_gems
+    assert_nothing_raised "'gem list --remote rubysspi' failed to execute"  do
+      Gem::GemRunner.new.run(["list", "--remote", "rubysspi"])
+    end
+  end
+end
diff -N -u c:\ruby\src\ruby-1.8.4\test\net\http.1.8.5.preview1/test_net_http.rb c:\ruby\src\ruby-1.8.4\test\net\http/test_net_http.rb
--- c:\ruby\src\ruby-1.8.4\test\net\http.1.8.5.preview1/test_net_http.rb	1969-12-31 16:00:00.000000000 -0800
+++ c:\ruby\src\ruby-1.8.4\test\net\http/test_net_http.rb	2006-07-20 15:12:36.422931700 -0700
@@ -0,0 +1,31 @@
+#
+# = test/net/http/test_net_http.rb
+#
+# Copyright (c) 2006 Justin Bailey
+# 
+# Written and maintained by Justin Bailey <jgbailey@gmail.com>.
+#
+# This program is free software. You can re-distribute and/or
+# modify this program under the same terms of ruby itself ---
+# Ruby Distribution License or GNU General Public License.
+
+require 'test/unit'
+require 'net/http'
+
+class NTLMTest < Test::Unit::TestCase
+  def setup
+    assert ENV["http_proxy"], "http_proxy must be set before running tests."
+  end
+  
+  def test_net_http
+
+    assert ENV["http_proxy"], "http_proxy environment variable must be set."
+    proxy = URI.parse(ENV["http_proxy"])
+    assert proxy.host && proxy.port, "Could not parse http_proxy (#{ENV["http_proxy"]}). http_proxy should be a URL with a port (e.g. http://proxy.corp.com:8080)."
+    
+    Net::HTTP.Proxy(proxy.host, proxy.port).start("www.google.com") do |http|
+      resp = http.get("/")
+      assert resp.code.to_i == 200, "Did not get response from Google as expected."
+    end
+  end
+end

In This Thread

Prev Next