jpatokal/mediawiki-gateway — Issue #25: NTLM support hacked in -- seeking better way
Author: raels
Created: 2011-12-01 07:07:08+00:00
State: open

I was stuck on this for a while, but finally got it working.

I was able to get RestClient to work fine with ruby-ntlm by making a RestClient.get to one of the protected wiki pages, with a call to ntlm_auth in a before_execution_proc. However, when I tried to use it with MWG, it was getting stuck with an argument error. traced to this routine in Net::HTTPGenericRequest

```ruby

# File lib/net/http.rb, line 1630
def set_body_internal(str) #:nodoc: internal use only
raise ArgumentError, "both of body argument and HTTPRequest#body set" if str and (@body or @body_stream)
self.body = str if str
end
```

A short debugging session later, it was clearly in this code that the error lies. I changed the code above and the way credentials are handled with some duck punching, and got the following:

```ruby
require 'rubygems'
require 'ntlm/http'
require 'media_wiki'
require 'pp'

# Some serious duck punching here to see if it will work this way
module RestClient

class Request
def setup_credentials(req)
req.ntlm_auth('me','example.com','password')
end
end

end

module Net
class HTTPGenericRequest
def set_body_internal(str) #:nodoc: internal use only
raise ArgumentError, "both of body argument and HTTPRequest#body set" if (str and @body and str != @body) or (str and @body_stream)
self.body = str if str
end
end
end

mw = MediaWiki::Gateway.new('https://example.com/wiki/api.php')

pp mw.get('api_test/test_page')
```

Using this code, things work. The only real hack is to let the set_body_internal method succeed if the str value is the same as the current @body (but not for streams) -- asking to change something to what it already is doesn't seem like an error so much to me. Still, this is the Net module here, so I don't want to muck with it unless its inescapable.

It seems that there must be something in MWG that is exercising this error. The stack trace points to:

```
ArgumentError: both of body argument and HTTPRequest#body set
from /Users/raels/.rvm/rubies/ruby-1.8.7-p334/lib/ruby/1.8/net/http.rb:1523:in `set_body_internal'
from /Users/raels/.rvm/rubies/ruby-1.8.7-p334/lib/ruby/1.8/net/http.rb:1046:in `__request__'
from /Users/raels/.rvm/gems/ruby-1.8.7-p334/gems/rest-client-1.6.7/lib/restclient/net_http_ext.rb:51:in `request_without_ntlm_auth'
from /Users/raels/.rvm/gems/ruby-1.8.7-p334/gems/ruby-ntlm-0.0.1/lib/ntlm/http.rb:42:in `request'
from /Users/raels/.rvm/gems/ruby-1.8.7-p334/gems/rest-client-1.6.7/lib/restclient/request.rb:176:in `transmit'
from /Users/raels/.rvm/rubies/ruby-1.8.7-p334/lib/ruby/1.8/net/http.rb:543:in `start'
from /Users/raels/.rvm/gems/ruby-1.8.7-p334/gems/rest-client-1.6.7/lib/restclient/request.rb:172:in `transmit'
from /Users/raels/.rvm/gems/ruby-1.8.7-p334/gems/rest-client-1.6.7/lib/restclient/request.rb:64:in `execute'
from /Users/raels/.rvm/gems/ruby-1.8.7-p334/gems/rest-client-1.6.7/lib/restclient/request.rb:33:in `execute'
from /Users/raels/.rvm/gems/ruby-1.8.7-p334/gems/rest-client-1.6.7/lib/restclient.rb:72:in `post'
from /Users/raels/.rvm/gems/ruby-1.8.7-p334/gems/mediawiki-gateway-0.4.3/lib/media_wiki/gateway.rb:573:in `make_api_request'
from /Users/raels/.rvm/gems/ruby-1.8.7-p334/gems/mediawiki-gateway-0.4.3/lib/media_wiki/gateway.rb:64:in `get'
```

I am guessing that this is some strange interaction between all three gems and the "request" methods in each.

So, before I go any deeper, is there an approved way to do NTLM auth in MGW? If not, any ideas about what might be the interaction here?

Any help appreciated.