2011-07-19 29 views
2

下面的simple_client.rb文件對我的模擬cas服務器完全正常工作;但是,casport.rb文件(oa-casport OmniAuth策略的主文件)沒有正確設置或傳遞標題/格式。它需要動態分配給類,以允許初始化選項能夠創建它們,但我不知道除了我在這裏嘗試做什麼以外還有什麼別的辦法。我相當確定我在某個時候有這個工作,但是我看不到任何其他解釋,爲什麼在客戶端文件簡單的情況下這不起作用。如何動態地在我的類上設置HTTParty配置參數?

任何幫助都非常感謝在搞清楚如何在我的Casport類中動態地最佳地設置HTTParty的formatheaders設置。因爲它只是不斷返回該特定用戶的HTML視圖。

simple_client.rb:

### simple_client.rb - works properly w/ parsed XML response 
### The cas.dev project is coming from this Github repo: 
### https://github.com/stevenhaddox/oa-casport-server 
require 'rubygems' 
require 'httparty' 
require 'awesome_print' 

class Casport 
    include HTTParty 
    base_uri 'cas.dev/users' 
    format :xml 
    headers 'Accept' => 'application/xml' 

    def self.find_user(id) 
    get("/#{id}").parsed_response 
    end 

end 

user = Casport.find_user(1) 
ap user 

casport.rb:

# lib/omniauth/strategies/casport.rb 
require 'omniauth/core' 
require 'httparty' 
require 'redis' 
require 'uri' 

module OmniAuth 
    module Strategies 
    # 
    # Authentication to CASPORT 
    # 
    # @example Basic Usage 
    # 
    # use OmniAuth::Strategies::Casport, { 
    #  :setup  => true 
    #  } 
    # @example Full Options Usage 
    # 
    # use OmniAuth::Strategies::Casport, { 
    #  :setup   => true, 
    #  :cas_server => 'http://cas.slkdemos.com/users/', 
    #  :format  => 'xml', 
    #  :format_header => 'application/xml', 
    #  :ssl_ca_file => 'path/to/ca_file.crt', 
    #  :pem_cert  => '/path/to/cert.pem', 
    #  :pem_cert_pass => 'keep it secret, keep it safe.' 
    #  } 
    class Casport 

     include OmniAuth::Strategy 
     include HTTParty 

     def initialize(app, options) 
     super(app, :casport) 
     @options = options 
     @options[:cas_server] ||= 'http://cas.dev/users' 
     @options[:format]  ||= 'xml' 
     @options[:format_header] ||= 'application/xml' 
     end 

     def request_phase 
     Casport.setup_httparty(@options) 
     redirect(callback_path) 
     end 

     def callback_phase 
     begin 
      raise 'We seemed to have misplaced your credentials... O_o' if user.nil? 
      super 
     rescue => e 
      redirect(request_path) 
#   fail!(:invalid_credentials, e) 
     end 
     call_app! 
     end 

     def auth_hash 
     # store user in a local var to avoid new method calls for each attribute 
     # convert all Java camelCase keys to Ruby snake_case, it just feels right! 
     user_obj = user.inject({}){|memo, (k,v)| memo[k.gsub(/[A-Z]/){|c| '_'+c.downcase}] = v; memo} 
     begin 
      user_obj = user_obj['userinfo'] 
     rescue => e 
      fail!(:invalid_user, e) 
     end 
     OmniAuth::Utils.deep_merge(super, { 
      'uid'  => user_obj['uid'], 
      'user_info' => { 
          'name' => user_obj['full_name'], 
          'email' => user_obj['email'] 
         }, 
      'extra'  => {'user_hash' => user_obj} 
     }) 
     end 

     # Set HTTParty params that we need to set after initialize is called 
     # These params come from @options within initialize and include the following: 
     # :ssl_ca_file - SSL CA File for SSL connections 
     # :format - 'json', 'xml', 'html', etc. || Defaults to 'xml' 
     # :format_header - :format Header string || Defaults to 'application/xml' 
     # :pem_cert - /path/to/a/pem_formatted_certificate.pem for SSL connections 
     # :pem_cert_pass - plaintext password, not recommended! 
     def self.setup_httparty(opts) 
     format opts[:format].to_sym 
     headers 'Accept' => opts[:format_header] 
     if opts[:ssl_ca_file] 
      ssl_ca_file opts[:ssl_ca_file] 
      if opts[:pem_cert_pass] 
      pem File.read(opts[:pem_cert]), opts[:pem_cert_pass] 
      else 
      pem File.read(opts[:pem_cert]) 
      end 
     end 
     end 

     def user 
     # Can't get user data without a UID from the application 
     begin 
      raise "No UID set in request.env['omniauth.strategy'].options[:uid]" if @options[:uid].nil? 
      @options[:uid] = @options[:uid].to_s 
     rescue => e 
      fail!(:uid_not_found, e) 
     end 

     url = URI.escape(@options[:cas_server] + '/' + @options[:uid]) 
# It appears the headers aren't going through properly to HTTParty... 
# The URL + .xml works in the application & the url w/out .xml works in standalone file 
# Which means somehow the setup with self.setup_httparty isn't kicking in properly :(
ap Casport.get(url+'.xml').parsed_response 
     begin 
      cache = @options[:redis_options].nil? ? Redis.new : Redis.new(@options[:redis_options]) 
      unless @user = (cache.get @options[:uid]) 
      # User is not in the cache 
      # Retrieving the user data from CASPORT 
      # {'userinfo' => {{'uid' => UID}, {'fullName' => NAME},...}}, 
      @user = Casport.get(url).parsed_response 
      cache.set @options[:uid], @user 
      # CASPORT expiration time for user (24 hours => 1440 seconds) 
      cache.expire @options[:uid], 1440 
      end 
     # If we can't connect to Redis... 
     rescue Errno::ECONNREFUSED => e 
      @user ||= Casport.get(url).parsed_response 
     end 
     @user = nil if user_empty? 
     @user 
     end 

     # Investigate user_obj to see if it's empty (or anti-pattern data) 
     def user_empty? 
     is_empty = false 
     is_empty = true if @user.nil? 
     is_empty = true if @user.empty? 
     # If it isn't empty yet, let's convert it into a Hash object for easy parsing via eval 
     unless @user.class == Hash 
      is_empty = true 
      raise "String returned when a Hash was expected." 
     end 
     is_empty == true ? true : nil 
     end 

    end 
    end 
end 

回答

6

這顯然是正常,什麼我沒做的是提供的Content-Type頭:

... 
def self.setup_httparty(opts) 
format opts[:format].to_sym 
headers 'Accept' => opts[:format_header] 
headers 'Content-Type' => opts[:format_header] 
... 

一旦我添加了額外的行,一切正常踢。

+2

對我來說,這個答案的最好的部分是它展示瞭如何使用'headers'原語添加_multiple_標頭。 –