问答

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

 来源    2019-08-26    1  

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

在弄清楚如何在我的Casport类中动态地设置HTTParty的格式和头设置时,非常感谢任何帮助.因为它只是继续返回该特定用户的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

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

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

一旦我添加了额外的行,所有内容都正常启动.

ruby – 在class decaration之后设置类继承或在const_set类上设置类继承
问答如果一个类已经被定义了如何告诉它从一个父类继承 例如: class Parent .. end class Klass .. end 现在我希望它继承自父母 我不能重新打开该类并设置它,因为我会得到一 ...
1
c – 为动态创建的TComponent派生类实例传递NULL Owner参数好吗?
问答我与C RAD Studio和Builder 6合作很多,并且经常在编写非可视代码时动态创建表单或动态创建非可视组件.在设计表单时,自动设置放在该表单上的组件的Owner属性,所以我从不担心它.但是, ...
ruby – 如何使用散列键作为类上的方法?
问答我有一个类和一个哈希.如何使用密钥作为方法名称来获取散列的成员动态地成为类的方法? class User def initialize @attributes = {"sn" =& ...
1
ruby-on-rails – Ruby on Rails 3:在特定路由上设置固定的语言环境
问答我在我的本地化网站上安装了rails_admin gem(3种语言),我需要管理区域(/ admin)始终使用英语.知道怎么做吗?也许我可以强制路由的语言环境? 谢谢.::我没有使用过rails_ad ...
1
objective-c – EXC_BAD_ACCESS在初始化时在自定义类上设置属性?
问答我有一个简单的Answer类,如下所示: @interface Answer : NSObject { NSString *_text; NSNumber *_votes; } @property(n ...
1
xaml – Silverlight 5:在IMarkupExtension类上设置ConstructorArgument
问答我想有一个MarkupExtension可以只用一个值启动,就像Binding: 而不是 在WPF中,这是使用ConstructorArgumentAttribute完成的,但这在Silverligh ...
1
AspNet Core Web 应用程序的启动 当项目中 没有Startup.cs 类如何设置启动 配置等等
日志感叹: Core 16年6月1号 在中国宣布上线 到现在已经快经历两年时间了,目前版本已经到了2.0 就目前的前景来看,个人感觉 到2020年才可能有所起色,等到Core更成熟 个人看法:在.net这 ...
设计模式(一)单例模式:创建模式 ASPNET CORE WEB 应用程序的启动 当项目中 没有STARTUP.CS 类如何设置启动 配置等等
日志设计模式(一)单例模式:创建模式 先聊一下关于设计的几个原则(1)单一原则(SRP):一个类应该仅有一个引起它变化的原因 :意思就是 (一个类,最好只负责一件事情,并且只有一个引起它变化的原因(2)开 ...
1
在Ruby中动态创建类
问答我有一个类应该看起来像这样: class Family_Type1 @people = Array.new(3) @people[0] = Policeman.new('Peter', 0) @peo ...
1
在Ruby中动态定义命名类
问答我正在Ruby中编写一个内部DSL.为此,我需要以编程方式创建命名类和嵌套类.这样做最好的方法是什么?我发现有两种方法可以做到这一点: >使用Class.new创建一个匿名类,然后使用defin ...
1
ruby-on-rails – 在Ruby中动态地向类添加类
问答假设我像这样动态创建一个模块: app = Object.const_set('CoolModule', Module.new) 反正有没有为该模块添加一个类?这样的事可能吗? app << ...
1
ruby对象模型的好解释 – 主要是“类是对象”?
问答我正在研究红宝石对象模型,并有一些问题.我理解一个对象只存储实例变量的想法,方法存储在类中,一个对象有一个引用.我也了解"自我"的想法 – 它是什么,它如何变化等等. 但是,我不明 ...
2
什么是Ruby的Python变量的类比,在类定义中未声明?
问答我可以在Python的类实例中将未定义的任何变量存储在类定义中. 我怎么能在Ruby中做这样的事情? class C: pass a = C() b = C() a.a = 1 a.b = 2 b.t ...
1
Ruby的attr_accessor如何产生类变量或类实例变量而不是实例变量?
问答如果我有一个类与attr_accessor,它默认创建一个实例变量以及相应的getters和setters.但是,不是创建一个实例变量,有没有办法让它创建一个类变量或类实例变量?::喜欢这个: cla ...
1
ruby – 如何动态地向SitePrism页面对象添加节?
问答我正在使用SitePrism来测试我的Web应用程序.我有许多扩展SitePrism :: Page的类,许多经常使用的HTML片段由扩展SitePrism :: Section的匹配类表示 clas ...
2
动态添加函数到r6类实例
问答我试图忘记refclasses(R5)并转移到R6,但动态代码存在问题.我会添加一个新功能,它在R5中工作: clsTrn <- setRefClass("clsTrn", ...
1
ruby – 使用MIddleman 3.0 – 如何在动态页面上设置单个页面标题?
问答我正在中间人组建一个简单的投资组合网站.我根据本地YAML数据动态生成"工作"页面.这是在config.rb中: data.work.projects.each do |proje ...
1
java – 我可以在同一个Maven项目的源文件中动态生成和引用一个类吗?
问答在Maven Build中,我使用字节码生成库(Byte Buddy)动态生成一些Java类型.当然,这些类文件没有相应的源文件.这样只能生成几个类.该项目的大部分代码将是Java源代码.理想情况下, ...
1
ruby-on-rails – Ruby可以动态增加文件大小以进行测试
问答这可能听起来很奇怪,或者你为什么要那样做. 我正在尝试编写黄瓜功能来测试上传大图像文件(> 16M)所以,我不想将大文件存储在github或我的项目中.我正在使用imagemagick创建一个图 ...
2