ruby - 如何在我的类上动态设置 HTTParty 配置参数?

标签 ruby xml parameters header httparty

下面的 simple_client.rb 文件在我的仿真 cas 服务器上工作得很好;然而,casport.rb 文件(oa-casport OmniAuth 策略的主文件)没有正确设置或传递 header /格式。它需要动态分配给类以允许初始化程序选项能够创建它们,但我不知道除了我在这里尝试的方法之外还能怎么做。我相当确定我在某个时候可以正常工作,但鉴于客户端文件的简单性,我看不到为什么这不起作用的任何其他解释。

非常感谢任何帮助,了解如何在我的 Casport 类中动态设置 HTTParty 的 formatheaders 设置。实际上,它只是不断返回该特定用户的 HTML View 。

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

最佳答案

这显然工作正常,我没有做的是为 Content-Type 提供 header :

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

一旦我添加了附加行,一切就会正常启动。

关于ruby - 如何在我的类上动态设置 HTTParty 配置参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6742296/

相关文章:

Android 填充布局中的空白区域

javascript - 单击时的 div 重定向到另一个 HTML 页面并调用 javascript 以显示特定的 div

asp.net-mvc - 使用带有操作参数的 ASP.NET MVC 子 Controller ?

ruby - 查找数组是否为二维数组的简单方法?

ruby-on-rails - 需要更改什么才能在 Linux 中运行在 Windows 上创建的 Rails 应用程序?

ruby - 从 Markdown 文件中对前面的内容进行排序

ruby-on-rails - 尝试抓取网站时出现 Ruby SSL 错误

c# - Linq to xml,检索基于通用接口(interface)的列表

xml - 使用 XSLT 排除 XML 空节点

安卓相机应用 : Spot Metering