Howdy,
I wanted to send a patch for advance review, primarily to see if anyone had a better
course of action to recommend.
I have the innocuous-sounding #2462, 'As a user, I want Conductor to use
imagefactory's REST API with oauth.' Since I'd already written a generic OAuth
client [1] for Conductor, and since ImageFactory already has a two-legged OAuth server, I
assumed this would be a walk in the park.
Where I ran into trouble is that ActiveResource and the OAuth gem (and the client I had
build on top of it) don't seem to want to play nicely. Each implements its own
'request' method that ultimately dumps into Net::HTTP. OAuth legitimately needs to
own the request, because it has to sign the request before injecting its authentication
headers. ActiveResource does some setup and handling in its request method that neither
Net::HTTP nor OAuth do.
I tried to implement 'request' in Aeolus::Image::Factory::Base, which feels like
the right thing to do. That way I can implement something that generates a signed request
with OAuth and that also does the setup that other components in ActiveResource expect.
But as I started, I realized that I don't see how I can make this work. We don't
call .request in any of our code; it's far more indirect. When we call, say,
Image.find, Aeolus::Image::Factory::Base is nowhere in the chain, so our .request never
gets called.
What I ended up doing in this (draft) patch is to monkey-patch ActiveResource::Connection
and substitute in our own .request method, which returns all the stuff they want [2] but
also signs the request like OAuth does [3]. There are some pretty obvious reasons why this
isn't ideal, but it also has the pretty obvious advantage of actually working.
This code still needs some work; as the comments indicate, I need to bring over some of
OAuth's error-detection/error-handling code, and, obviously, I need to not have
credentials and a URL hard-coded in the method. Plus this module isn't actually being
included yet.
What I'm looking for at this point is simply feedback on whether there's a better
solution that I'm overlooking. If this pattern is too objectionable, or if there's
just a cleaner solution, I'd greatly welcome your feedback before I continue with this
approach.
Best,
Matt
[1]
https://github.com/aeolusproject/conductor/blob/master/src/lib/oauth_clie...
[2]
https://github.com/rails/rails/blob/6b4bbb427455ec1af6bdf0896a62129bd3c8c...
[3]
https://github.com/oauth/oauth-ruby/blob/master/lib/oauth/consumer.rb#L151